Exemplo n.º 1
0
int skymedi_verify_llf_and_fw(struct mmc *mmc)
{
	int ret;
	card_power_off_on();
	mmc->has_init = 0;
	mmc->init_in_progress = 0;
	ret = mmc_init(mmc);
	if (ret)
		return ret;
	mmc_set_bus_width(mmc, 1);

	ret = skymedi_set_func(mmc, 0x00000055);
	if (ret)
		return ret;
	ret = skymedi_set_func(mmc, 0x00000057);
	if (ret)
		return ret;
	ret = skymedi_write_file(mmc, 0x80000014, "ERASE.bin", 3000);
	if (ret == 0)
		return -1;
	ret = skymedi_set_func(mmc, 0x00000056);
	if (ret)
		return ret;
	ret = skymedi_read_blocks(mmc, sector_buff, 0xFFFFFF47, 512 / 512);
	if (ret == 0)
		return -1;
	//check version  ???

	//compare test from address 0 at least 10 sectors data ????

	return 0;
}
Exemplo n.º 2
0
static int mmc_bustest_write(struct mmc_host *host,
				 struct mmc_card *card, int buswidth)
{
	struct mmc_request mrq;
	struct mmc_command cmd;
	struct mmc_data data;
	struct scatterlist sg;
	int bustest_send_pat[4] = { 0x80, 0x0, 0x5A, 0x55AA };
	u32 *test_pat;
	int err = 0;

	test_pat = kmalloc(512, GFP_KERNEL);
	if (test_pat == NULL)
		return -ENOMEM;

	memset(&mrq, 0, sizeof(struct mmc_request));
	memset(&cmd, 0, sizeof(struct mmc_command));
	memset(&data, 0, sizeof(struct mmc_data));

	mrq.cmd = &cmd;
	mrq.data = &data;

	cmd.opcode = MMC_BUSTEST_W;
	cmd.arg = 0;
	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;

	data.blksz = 4; /* Generic blksz that works for 8 / 4 / 1 bit modes */
	data.blocks = 1;
	data.flags = MMC_DATA_WRITE;
	data.sg = &sg;
	data.sg_len = 1;

	/* The mmc bus test timeout is primarily dependent on mmc clock and
	*  the host controller since the card acts as a loopback device as
	*  there is no data is being written to/read from the card's memory.
	*  Since the test will be conducted at the frequency of operation
	*  (20 MHz or higher), 1ms timeout is more than adequate. The same
	*  timeout values are used for read bustest as well.
	*/
	data.timeout_ns = 1000000;
	data.timeout_clks = 0;

	test_pat[0] = bustest_send_pat[buswidth];
	mmc_set_bus_width(card->host, buswidth);
	sg_init_one(&sg, test_pat, 4);

	mmc_wait_for_req(host, &mrq);

	pr_debug("%s: Test Pattern sent: 0x%x\n", __func__, test_pat[0]);
	if (cmd.error || data.error) {
		pr_err("%s: cmd.error : %d data.error: %d\n",
			__func__, cmd.error, data.error);
		err = -1;
	}
	kfree(test_pat);
	return err;
}
Exemplo n.º 3
0
static int mmc_bustest_write(struct mmc_host *host,
				 struct mmc_card *card, int buswidth)
{
	struct mmc_request mrq;
	struct mmc_command cmd;
	struct mmc_data data;
	struct scatterlist sg;
	int bustest_send_pat[4] = { 0x80, 0x0, 0x5A, 0x55AA };
	u32 *test_pat;
	int err = 0;

	test_pat = kmalloc(512, GFP_KERNEL);
	if (test_pat == NULL)
		return -ENOMEM;

	memset(&mrq, 0, sizeof(struct mmc_request));
	memset(&cmd, 0, sizeof(struct mmc_command));
	memset(&data, 0, sizeof(struct mmc_data));

	mrq.cmd = &cmd;
	mrq.data = &data;

	cmd.opcode = MMC_BUSTEST_W;
	cmd.arg = 0;
	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;

	data.blksz = 4; /* Generic blksz that works for 8 / 4 / 1 bit modes */
	data.blocks = 1;
	data.flags = MMC_DATA_WRITE;
	data.sg = &sg;
	data.sg_len = 1;
// HYNIX EMMC - bus check delay around 800ms ~ 1s.
#if 1
	data.timeout_ns = 100000000;
	data.timeout_clks = 0;
#else
	data.timeout_ns = card->csd.tacc_ns * 10;
	data.timeout_clks = card->csd.tacc_clks * 10;
#endif

	test_pat[0] = bustest_send_pat[buswidth];
	mmc_set_bus_width(card->host, buswidth);
	sg_init_one(&sg, test_pat, 4);

	mmc_wait_for_req(host, &mrq);

	pr_debug("%s: Test Pattern sent: 0x%x\n", __func__, test_pat[0]);
	if (cmd.error || data.error) {
		pr_err("%s: cmd.error : %d data.error: %d\n",
			__func__, cmd.error, data.error);
		err = -1;
	}
	kfree(test_pat);
	return err;
}
Exemplo n.º 4
0
/*
 * UHS-I specific initialization procedure
 */
static int mmc_sd_init_uhs_card(struct mmc_card *card)
{
	int err;
	u8 *status;

	if (!card->scr.sda_spec3)
		return 0;

	if (!(card->csd.cmdclass & CCC_SWITCH))
		return 0;

	status = kmalloc(64, GFP_KERNEL);
	if (!status) {
		printk(KERN_ERR "%s: could not allocate a buffer for "
			"switch capabilities.\n", mmc_hostname(card->host));
		return -ENOMEM;
	}

	/* Set 4-bit bus width */
	if ((card->host->caps & MMC_CAP_4_BIT_DATA) &&
	    (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
		err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
		if (err)
			goto out;

		mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
	}

	/* Set the driver strength for the card */
	err = sd_select_driver_type(card, status);
	if (err)
		goto out;

	/* Set bus speed mode of the card */
	err = sd_set_bus_speed_mode(card, status);
	if (err)
		goto out;

	/* SPI mode doesn't define CMD19 */
	if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning)
		err = card->host->ops->execute_tuning(card->host);
out:
	kfree(status);

	return err;
}
Exemplo n.º 5
0
int skymedi_open_mmc_card(void)
{
	int ret;
	struct mmc *mmc;
	mmc = find_mmc_device(MMC_DEV_NUM);
	if (!mmc) {
		printf("no mmc device %x\n", MMC_DEV_NUM);
		return -1;
	}
	memset(sector_buff, 0, sizeof(sector_buff));

	/* 1. Card Initial */
	mmc->has_init = 0;
	mmc->init_in_progress = 0;
	ret = mmc_init(mmc);
	if (ret)
		return -1;
	mmc_set_bus_width(mmc, 1);
	/* 2. Validation Process */
	ret = skymedi_validation_process(mmc);
	if (ret)
		return -1;
	/* 3. Low Level Process */
	ret = skymedi_low_level_process(mmc);
	if (ret)
		return -1;
	/* 4. Verify LLF result & FW Patch Version */
	ret = skymedi_verify_llf_and_fw(mmc);
	if (ret)
		return -1;
	/* 5. CID Programming */
	ret = skymedi_cid_program(mmc);
	if (ret)
		return -1;

	ret = skymedi_judge_result(mmc);
	if (ret)
		return -1;

	return 0;
}
Exemplo n.º 6
0
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err, count;
	u32 cid[4];
	unsigned int max_dtr;
	u32 status;

	BUG_ON(!host);
	WARN_ON(!host->claimed);

	/*
	 * Since we're changing the OCR value, we seem to
	 * need to tell some cards to go back to the idle
	 * state.  We wait 1ms to give cards time to
	 * respond.
	 */
	mmc_go_idle(host);

	/* The extra bit indicates that we support high capacity */
	err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
	if (err)
		goto err;

	/*
	 * For SPI, enable CRC as appropriate.
	 */
	if (mmc_host_is_spi(host)) {
		err = mmc_spi_set_crc(host, use_spi_crc);
		if (err)
			goto err;
	}

	/*
	 * Fetch CID from card.
	 */
	if (mmc_host_is_spi(host))
		err = mmc_send_cid(host, cid);
	else
		err = mmc_all_send_cid(host, cid);
	if (err)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
			err = -ENOENT;
			goto err;
		}

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host, &mmc_type);
		if (IS_ERR(card)) {
			err = PTR_ERR(card);
			goto err;
		}

		card->type = MMC_TYPE_MMC;
		card->rca = 1;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
	}

	/*
	 * For native busses:  set card RCA and quit open drain mode.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_set_relative_addr(card);
		if (err)
			goto free_card;

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}

	if (!oldcard) {
		/*
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err)
			goto free_card;
		err = mmc_decode_cid(card);
		if (err)
			goto free_card;
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
			goto free_card;
	}

	if (!oldcard) {
		/*
		 * Fetch and process extended CSD.
		 */
		err = mmc_read_ext_csd(card);
		if (err)
			goto free_card;
	}

	/*
	 * Activate high speed (if supported)
	 */
	if ((card->ext_csd.hs_max_dtr != 0) &&
		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_HS_TIMING, 1);
		if (err)
			goto free_card;

		mmc_card_set_highspeed(card);

		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
	}

	count = 0;
	do {
		err = mmc_send_status(card, &status);
		if (err)
			goto free_card;
		if (status & R1_READY_FOR_DATA)
			break;
		else
			mdelay(1);
	} while (++count < WAIT_CMD6_MAX);

	/*
	 * Compute bus speed.
	 */
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->ext_csd.hs_max_dtr)
			max_dtr = card->ext_csd.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}

	mmc_set_clock(host, max_dtr);

	/*
	 * Activate wide bus (if supported).
	 */
	if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
	    (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
		unsigned ext_csd_bit, bus_width;

		if (host->caps & MMC_CAP_8_BIT_DATA) {
			ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
			bus_width = MMC_BUS_WIDTH_8;
		} else {
			ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
			bus_width = MMC_BUS_WIDTH_4;
		}

		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_BUS_WIDTH, ext_csd_bit);

		if (err)
			goto free_card;

		mmc_set_bus_width(card->host, bus_width);

		count = 0;
		do {
			err = mmc_send_status(card, &status);
			if (err)
				goto free_card;
			if (status & R1_READY_FOR_DATA)
				break;
			else
				mdelay(1);
		} while (++count < WAIT_CMD6_MAX);
	}

	if (!oldcard)
		host->card = card;

	return 0;

free_card:
	if (!oldcard)
		mmc_remove_card(card);
err:

	return err;
}
Exemplo n.º 7
0
/*
 * Read and decode extended CSD. Switch to high-speed and wide bus
 * if supported.
 */
static int mmc_process_ext_csd(struct mmc_card *card)
{
	int err;
	u8 *ext_csd;

	BUG_ON(!card);

	err = MMC_ERR_FAILED;

	if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
		return MMC_ERR_NONE;

	/*
	 * As the ext_csd is so large and mostly unused, we don't store the
	 * raw block in mmc_card.
	 */
	ext_csd = kmalloc(512, GFP_KERNEL);
	if (!ext_csd) {
		printk(KERN_ERR "%s: could not allocate a buffer to "
			"receive the ext_csd. mmc v4 cards will be "
			"treated as v3.\n", mmc_hostname(card->host));
		return MMC_ERR_FAILED;
	}

	err = mmc_send_ext_csd(card, ext_csd);
	if (err != MMC_ERR_NONE) {
		if (card->csd.capacity == (4096 * 512)) {
			printk(KERN_ERR "%s: unable to read EXT_CSD "
				"on a possible high capacity card. "
				"Card will be ignored.\n",
				mmc_hostname(card->host));
		} else {
			printk(KERN_WARNING "%s: unable to read "
				"EXT_CSD, performance might "
				"suffer.\n",
				mmc_hostname(card->host));
			err = MMC_ERR_NONE;
		}
		goto out;
	}

	card->ext_csd.sectors =
		ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
		ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
		ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
		ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
	if (card->ext_csd.sectors)
		mmc_card_set_blockaddr(card);

	switch (ext_csd[EXT_CSD_CARD_TYPE]) {
	case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
		card->ext_csd.hs_max_dtr = 52000000;
		break;
	case EXT_CSD_CARD_TYPE_26:
		card->ext_csd.hs_max_dtr = 26000000;
		break;
	default:
		/* MMC v4 spec says this cannot happen */
		printk(KERN_WARNING "%s: card is mmc v4 but doesn't "
			"support any high-speed modes.\n",
			mmc_hostname(card->host));
		goto out;
	}

	if (card->host->caps & MMC_CAP_MMC_HIGHSPEED) {
		/* Activate highspeed support. */
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_HS_TIMING, 1);
		if (err != MMC_ERR_NONE) {
			printk(KERN_WARNING "%s: failed to switch "
				"card to mmc v4 high-speed mode.\n",
			       mmc_hostname(card->host));
			err = MMC_ERR_NONE;
			goto out;
		}

		mmc_card_set_highspeed(card);

		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
	}

	/* Check for host support for wide-bus modes. */
	if (card->host->caps & MMC_CAP_4_BIT_DATA) {
		/* Activate 4-bit support. */
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4);
		if (err != MMC_ERR_NONE) {
			printk(KERN_WARNING "%s: failed to switch "
				"card to mmc v4 4-bit bus mode.\n",
			       mmc_hostname(card->host));
			err = MMC_ERR_NONE;
			goto out;
		}

		mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
	}

out:
	kfree(ext_csd);

	return err;
}
Exemplo n.º 8
0
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err, ddr = 0;
	u32 cid[4];
	unsigned int max_dtr;
	u32 rocr;
	u8 *ext_csd = NULL;
#if defined(CONFIG_MMC_DISABLE_WP_RFG_5)
	/* 2012 March detect write protection status for SHR/SHR#K workaround */
	/* mfg partition start sector = LBA 65536                             */
	unsigned char WP_STATUS[8] = {0};
#endif
	BUG_ON(!host);
	WARN_ON(!host->claimed);

	/*
	 * Since we're changing the OCR value, we seem to
	 * need to tell some cards to go back to the idle
	 * state.  We wait 1ms to give cards time to
	 * respond.
	 */
	mmc_go_idle(host);

	/* The extra bit indicates that we support high capacity */
	err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
	if (err)
		goto err;

	/*
	 * For SPI, enable CRC as appropriate.
	 */
	if (mmc_host_is_spi(host)) {
		err = mmc_spi_set_crc(host, use_spi_crc);
		if (err)
			goto err;
	}

	/*
	 * Fetch CID from card.
	 */
	if (mmc_host_is_spi(host))
		err = mmc_send_cid(host, cid);
	else
		err = mmc_all_send_cid(host, cid);
	if (err)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
			err = -ENOENT;
			goto err;
		}

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host, &mmc_type);
		if (IS_ERR(card)) {
			err = PTR_ERR(card);
			goto err;
		}

		card->type = MMC_TYPE_MMC;
		card->rca = 1;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
	}

	/*
	 * For native busses:  set card RCA and quit open drain mode.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_set_relative_addr(card);
		if (err)
			goto free_card;

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}

	if (!oldcard) {
		/*
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err)
			goto free_card;
		err = mmc_decode_cid(card);
		if (err)
			goto free_card;
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
			goto free_card;
	}

	if (!oldcard) {
		/*
		 * Fetch and process extended CSD.
		 */

		err = mmc_get_ext_csd(card, &ext_csd);
		if (err)
			goto free_card;
		err = mmc_read_ext_csd(card, ext_csd);
		if (err)
			goto free_card;

		/* If doing byte addressing, check if required to do sector
		 * addressing.  Handle the case of <2GB cards needing sector
		 * addressing.  See section 8.1 JEDEC Standard JED84-A441;
		 * ocr register has bit 30 set for sector addressing.
		 */
		if (!(mmc_card_blockaddr(card)) && (rocr & (1<<30)))
			mmc_card_set_blockaddr(card);

		/* Erase size depends on CSD and Extended CSD */
		mmc_set_erase_size(card);

		if (card->ext_csd.sectors && (rocr & MMC_CARD_SECTOR_ADDR))
			mmc_card_set_blockaddr(card);
	}

	/* If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF     */
	/* bit.  This bit will be lost every time after a reset or power off.  */
	/* For 2GB eMMC, there will no HC_ERASE_GROUP define                   */

	if (card->ext_csd.sectors > 4194304) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_ERASE_GROUP_DEF, 1, 0);

		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			err = 0;
			/*
			 * Just disable enhanced area off & sz
			 * will try to enable ERASE_GROUP_DEF
			 * during next time reinit
			 */
			card->ext_csd.enhanced_area_offset = -EINVAL;
			card->ext_csd.enhanced_area_size = -EINVAL;
		} else {
			card->ext_csd.erase_group_def = 1;
			/*
			 * enable ERASE_GRP_DEF successfully.
			 * This will affect the erase size, so
			 * here need to reset erase size
			 */
			mmc_set_erase_size(card);
		}
	}

	/*
	 * Ensure eMMC user default partition is enabled
	 */
	if (card->ext_csd.part_config & EXT_CSD_PART_CONFIG_ACC_MASK) {
		card->ext_csd.part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONFIG,
				 card->ext_csd.part_config,
				 card->ext_csd.part_time);
		if (err && err != -EBADMSG)
			goto free_card;
	}

	/* For SanDisk X3, we have to enable power class 4 */
	if (card->cid.manfid == 0x45) {
		if (card->ext_csd.sectors > 33554432) { /* the storage size larger than 16GB */
				err = mmc_switch(card, EXT_CSD_CMD_SET_ZERO, EXT_CSD_POWER_CLASS, 4, 0);
				if (err && err != -EBADMSG)
					goto free_card;

				if (err) {
					printk(KERN_WARNING "%s: switch to power class 4 failed\n",
						mmc_hostname(card->host));
					err = 0;
				} else {
					printk(KERN_WARNING "%s: switch to power class 4 sucessfully\n",
						mmc_hostname(card->host));
				}
		} else if (card->ext_csd.sectors == 31105024) {
				err = mmc_switch(card, EXT_CSD_CMD_SET_ZERO, EXT_CSD_POWER_CLASS, 4, 0);
				if (err && err != -EBADMSG)
					goto free_card;

				if (err) {
					printk(KERN_WARNING "%s: switch to power class 4 failed\n",
						mmc_hostname(card->host));
					err = 0;
				} else {
					printk(KERN_WARNING "%s: switch to power class 4 sucessfully\n",
						mmc_hostname(card->host));
				}
		}
	}

	/*
	 * Activate high speed (if supported)
	 */
	if ((card->ext_csd.hs_max_dtr != 0) &&
		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_HS_TIMING, 1, 0);
		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			printk(KERN_WARNING "%s: switch to highspeed failed\n",
			       mmc_hostname(card->host));
			err = 0;
		} else {
			mmc_card_set_highspeed(card);
			mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
		}
	}
	if (card->cid.manfid == 0x45) {
		/* Sandisk 24nm extreme 16G */
		if ((card->ext_csd.sectors == 31105024) && !strcmp(card->cid.prod_name, "SEM16G"))
			card->wr_perf = 12;
		/* Sandisk 24nm extreme 32G */
		else if ((card->ext_csd.sectors == 62324736) && !strcmp(card->cid.prod_name, "SEM32G"))
			card->wr_perf = 12;
	} else if (card->cid.manfid == 0x15) {
		pr_info("%s: sectors %u\n", mmc_hostname(card->host), card->ext_csd.sectors);
		/* Samsung 27nm 16G */
		if ((card->ext_csd.sectors == 30777344) && !strcmp(card->cid.prod_name, "KYL00M"))
			card->wr_perf = 11;
		else if ((card->ext_csd.sectors == 62521344) && !strcmp(card->cid.prod_name, "MBG8FA"))
			card->wr_perf = 11;
		/* Samsung 21nm 16G */
		else if ((card->ext_csd.sectors == 30535680) && !strcmp(card->cid.prod_name, "MAG2GA"))
			card->wr_perf = 14;
	}

	/*
	 * Compute bus speed.
	 */
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->ext_csd.hs_max_dtr)
			max_dtr = card->ext_csd.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}

	mmc_set_clock(host, max_dtr);

	/*
	 * Indicate DDR mode (if supported).
	 */
	if (mmc_card_highspeed(card)) {
		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
			&& ((host->caps & (MMC_CAP_1_8V_DDR |
			     MMC_CAP_UHS_DDR50))
				== (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50)))
				ddr = MMC_1_8V_DDR_MODE;
		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
			&& ((host->caps & (MMC_CAP_1_2V_DDR |
			     MMC_CAP_UHS_DDR50))
				== (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50)))
				ddr = MMC_1_2V_DDR_MODE;
	}

	/*
	 * Activate wide bus and DDR (if supported).
	 */
	if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
	    (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
		static unsigned ext_csd_bits[][2] = {
			{ EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
			{ EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 },
			{ EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 },
		};
		static unsigned bus_widths[] = {
			MMC_BUS_WIDTH_8,
			MMC_BUS_WIDTH_4,
			MMC_BUS_WIDTH_1
		};
		unsigned idx, bus_width = 0;

		if (host->caps & MMC_CAP_8_BIT_DATA)
			idx = 0;
		else
			idx = 1;
		for (; idx < ARRAY_SIZE(bus_widths); idx++) {
			bus_width = bus_widths[idx];
			if (bus_width == MMC_BUS_WIDTH_1)
				ddr = 0; /* no DDR for 1-bit width */
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					 EXT_CSD_BUS_WIDTH,
					 ext_csd_bits[idx][0],
					 0);
			if (!err) {
				mmc_set_bus_width(card->host, bus_width);

				/*
				 * If controller can't handle bus width test,
				 * compare ext_csd previously read in 1 bit mode
				 * against ext_csd at new bus width
				 */
				if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
					err = mmc_compare_ext_csds(card,
						bus_width);
				else
					err = mmc_bus_test(card, bus_width);
				if (!err)
					break;
			}
		}

		if (!err && ddr) {
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					 EXT_CSD_BUS_WIDTH,
					 ext_csd_bits[idx][1],
					 0);
		}
		if (err) {
			printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
				"failed\n", mmc_hostname(card->host),
				1 << bus_width, ddr);
			goto free_card;
		} else if (ddr) {
			/*
			 * eMMC cards can support 3.3V to 1.2V i/o (vccq)
			 * signaling.
			 *
			 * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq.
			 *
			 * 1.8V vccq at 3.3V core voltage (vcc) is not required
			 * in the JEDEC spec for DDR.
			 *
			 * Do not force change in vccq since we are obviously
			 * working and no change to vccq is needed.
			 *
			 * WARNING: eMMC rules are NOT the same as SD DDR
			 */
			if (ddr == MMC_1_2V_DDR_MODE) {
				err = mmc_set_signal_voltage(host,
					MMC_SIGNAL_VOLTAGE_120, 0);
				if (err)
					goto err;
			}
			mmc_card_set_ddr_mode(card);
			mmc_set_timing(card->host, MMC_TIMING_UHS_DDR50);
			mmc_set_bus_width(card->host, bus_width);
		}
	}

#if defined(CONFIG_MMC_DISABLE_WP_RFG_5)
	/* 2012 March detect write protection status for SHR/SHR#K workaround */
	/* mfg partition start sector = LBA 65536                             */
	err = mmc_set_block_length(card, 8);

	if (err && err != -EBADMSG)
		goto free_card;

	if (err) {
		pr_err("%s: set block length to 8 fail\n", mmc_hostname(card->host));
		err = 0;
	}

	err = mmc_send_write_prot_type(card, WP_STATUS, 65536);

	if (err && err != -EBADMSG)
		goto free_card;

	if (err) {
		pr_err("%s: send write protection type at address 65536 failed\n", mmc_hostname(card->host));
		err = 0;
	}

	if (WP_STATUS[0] & 0xAA) {
		pr_info("%s: trigger software write protection\n", mmc_hostname(card->host));
		card->write_prot_type = 1;
	} else {
		pr_info("%s: disable software write protection\n", mmc_hostname(card->host));
		card->write_prot_type = 0;
	}

	err = mmc_set_block_length(card, 512);

	if (err && err != -EBADMSG)
		goto free_card;

	if (err) {
		pr_err("%s: set block length to 512 fail\n", mmc_hostname(card->host));
		err = 0;
	}
#endif
#if defined(CONFIG_ARCH_MSM7230)
	/* 2012 March detect write protection status for Kingston workaround
	   System partition start sector = LBA 200704 */
	if (card->cid.manfid == 0x70) {
		unsigned char WP_STATUS[8] = {0};
		err = mmc_set_block_length(card, 8);

		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			pr_err("%s: set block length to 8 fail\n", mmc_hostname(card->host));
			err = 0;
		}

		err = mmc_send_write_prot_type(card, WP_STATUS, 200704);

		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			pr_err("%s: send write protection type at address 200704 failed\n", mmc_hostname(card->host));
			err = 0;
		}

		if (WP_STATUS[0] & 0xAA) {
			pr_info("%s: trigger Kingston write protection\n", mmc_hostname(card->host));
			card->write_prot_type = 1;
		} else {
			pr_info("%s: disable Kingston write protection\n", mmc_hostname(card->host));
			card->write_prot_type = 0;
		}

		err = mmc_set_block_length(card, 512);

		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			pr_err("%s: set block length to 512 fail\n", mmc_hostname(card->host));
			err = 0;
		}
	}
#endif
	if (!oldcard)
		host->card = card;

	mmc_free_ext_csd(ext_csd);
	return 0;

free_card:
	if (!oldcard)
		mmc_remove_card(card);
err:
	mmc_free_ext_csd(ext_csd);

	return err;
}
Exemplo n.º 9
0
static int mmc_awake(struct mmc_host *host)
{
	struct mmc_card *card = host->card;
	int err = -ENOSYS;
	int ddr = 0;
	unsigned int max_dtr;
	if (card && card->ext_csd.rev >= 3) {
		err = mmc_card_sleepawake(host, 0);
		if (err < 0) {
			pr_debug("%s: Error %d while awaking sleeping card",
				 mmc_hostname(host), err);
			return err;
		}
		/*
		* Ensure eMMC user default partition is enabled
		*/
		if (card->ext_csd.part_config & EXT_CSD_PART_CONFIG_ACC_MASK) {
			card->ext_csd.part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONFIG,
					card->ext_csd.part_config,
					card->ext_csd.part_time);
			if (err && err != -EBADMSG)
				goto err;
		}

		/*
		* Activate high speed (if supported)
		*/
		if ((card->ext_csd.hs_max_dtr != 0) &&
			(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
				mmc_card_set_highspeed(card);
				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
		}
		/*
		* Compute bus speed.
		*/
		max_dtr = (unsigned int)-1;

		if (mmc_card_highspeed(card)) {
			if (max_dtr > card->ext_csd.hs_max_dtr)
				max_dtr = card->ext_csd.hs_max_dtr;
		} else if (max_dtr > card->csd.max_dtr) {
			max_dtr = card->csd.max_dtr;
		}

		mmc_set_clock(host, max_dtr);
		/*
		* Indicate DDR mode (if supported).
		*/
		if (mmc_card_highspeed(card)) {
			if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
				&& ((host->caps & (MMC_CAP_1_8V_DDR |
					MMC_CAP_UHS_DDR50))
					== (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50)))
					ddr = MMC_1_8V_DDR_MODE;
			else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
				&& ((host->caps & (MMC_CAP_1_2V_DDR |
					MMC_CAP_UHS_DDR50))
					== (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50)))
					ddr = MMC_1_2V_DDR_MODE;
		}
		/*
		* Activate wide bus and DDR (if supported).
		*/
		if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
			(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
			static unsigned ext_csd_bits[][2] = {
				{ EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
				{ EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 },
				{ EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 },
			};

			static unsigned bus_widths[] = {
				MMC_BUS_WIDTH_8,
				MMC_BUS_WIDTH_4,
				MMC_BUS_WIDTH_1
			};

			unsigned idx, bus_width = 0;
			if (host->caps & MMC_CAP_8_BIT_DATA)
				idx = 0;
			else
				idx = 1;
			for (; idx < ARRAY_SIZE(bus_widths); idx++) {
				bus_width = bus_widths[idx];
				if (bus_width == MMC_BUS_WIDTH_1)
					ddr = 0; /* no DDR for 1-bit width */
				err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
						EXT_CSD_BUS_WIDTH,
						ext_csd_bits[idx][0],
						0);
				if (!err) {
					mmc_set_bus_width(card->host, bus_width);
					break;

				}
			}

			if (!err && ddr) {
				err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
						EXT_CSD_BUS_WIDTH,
						ext_csd_bits[idx][1],
						0);
			}
			if (err) {
				printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
					"failed\n", mmc_hostname(card->host),
					1 << bus_width, ddr);
				goto err;
			} else if (ddr) {
				/*
				* eMMC cards can support 3.3V to 1.2V i/o (vccq)
				* signaling.
				*
				* EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq.
				*
				* 1.8V vccq at 3.3V core voltage (vcc) is not required
				* in the JEDEC spec for DDR.
				*
				* Do not force change in vccq since we are obviously
				* working and no change to vccq is needed.
				*
				* WARNING: eMMC rules are NOT the same as SD DDR
				*/
				if (ddr == MMC_1_2V_DDR_MODE) {
					err = mmc_set_signal_voltage(host,
						MMC_SIGNAL_VOLTAGE_120, 0);
					if (err)
						goto err;
				}
				mmc_card_set_ddr_mode(card);
				mmc_set_timing(card->host, MMC_TIMING_UHS_DDR50);
				mmc_set_bus_width(card->host, bus_width);
			}
		}
	}
err:
	return err;
}
Exemplo n.º 10
0
/*
 * Given a 128-bit response, decode to our card CSD structure.
 */
static int mmc_decode_csd(struct mmc_card *card)
{
	struct mmc_csd *csd = &card->csd;
	unsigned int e, m, csd_struct;
	u32 *resp = card->raw_csd;

	/*
	 * We only understand CSD structure v1.1 and v1.2.
	 * v1.2 has extra information in bits 15, 11 and 10.
	 */
	csd_struct = UNSTUFF_BITS(resp, 126, 2);
#if defined(CONFIG_MACH_OMAP3630_EDP1) || defined(CONFIG_MACH_OMAP3621_EDP1) || defined(CONFIG_MACH_OMAP3621_BOXER) || defined(CONFIG_MACH_OMAP3621_EVT1A) || defined(CONFIG_MACH_OMAP3621_GOSSAMER)
	/* To recognize Boxer board eMMC */
	if (csd_struct != 1 && csd_struct != 2 && csd_struct != 3) {
#else
	if (csd_struct != 1 && csd_struct != 2) {
#endif
		printk(KERN_ERR "%s: unrecognised CSD structure version %d\n",
			mmc_hostname(card->host), csd_struct);
		return -EINVAL;
	}

	csd->mmca_vsn	 = UNSTUFF_BITS(resp, 122, 4);
	m = UNSTUFF_BITS(resp, 115, 4);
	e = UNSTUFF_BITS(resp, 112, 3);
	csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
	csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;

	m = UNSTUFF_BITS(resp, 99, 4);
	e = UNSTUFF_BITS(resp, 96, 3);
	csd->max_dtr	  = tran_exp[e] * tran_mant[m];
	csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);

	e = UNSTUFF_BITS(resp, 47, 3);
	m = UNSTUFF_BITS(resp, 62, 12);
	csd->capacity	  = (1 + m) << (e + 2);

	csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
	csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
	csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
	csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
	csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
	csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
	csd->write_partial = UNSTUFF_BITS(resp, 21, 1);

	return 0;
}

/*
 * Read and decode extended CSD.
 */
static int mmc_read_ext_csd(struct mmc_card *card)
{
	int err;
	u8 *ext_csd;

	BUG_ON(!card);

	if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
		return 0;

	/*
	 * As the ext_csd is so large and mostly unused, we don't store the
	 * raw block in mmc_card.
	 */
	ext_csd = kmalloc(512, GFP_KERNEL);
	if (!ext_csd) {
		printk(KERN_ERR "%s: could not allocate a buffer to "
			"receive the ext_csd.\n", mmc_hostname(card->host));
		return -ENOMEM;
	}

	err = mmc_send_ext_csd(card, ext_csd);
	if (err) {
		/*
		 * We all hosts that cannot perform the command
		 * to fail more gracefully
		 */
		if (err != -EINVAL)
			goto out;

		/*
		 * High capacity cards should have this "magic" size
		 * stored in their CSD.
		 */
		if (card->csd.capacity == (4096 * 512)) {
			printk(KERN_ERR "%s: unable to read EXT_CSD "
				"on a possible high capacity card. "
				"Card will be ignored.\n",
				mmc_hostname(card->host));
		} else {
			printk(KERN_WARNING "%s: unable to read "
				"EXT_CSD, performance might "
				"suffer.\n",
				mmc_hostname(card->host));
			err = 0;
		}

		goto out;
	}

	card->ext_csd.rev = ext_csd[EXT_CSD_REV];
#if defined(CONFIG_MACH_OMAP3630_EDP1) || defined(CONFIG_MACH_OMAP3621_EDP1) || defined(CONFIG_MACH_OMAP3621_BOXER) || defined(CONFIG_MACH_OMAP3621_EVT1A) || defined(CONFIG_MACH_OMAP3621_GOSSAMER)
	/* To recognize Boxer board eMMC */
	if (card->ext_csd.rev > 5) {
#else
	if (card->ext_csd.rev > 2) {
#endif
		printk(KERN_ERR "%s: unrecognised EXT_CSD structure "
			"version %d\n", mmc_hostname(card->host),
			card->ext_csd.rev);
		err = -EINVAL;
		goto out;
	}

#ifdef CONFIG_HC_Broken_eMMC_ZOOM2
	/*
	 * Hack: eMMC on Zoom2 seems to have a lower EXT_CSD Rev.
	 * This is incorrect as it is an HC card. The card becomes
	 * unusable if not set to blockaddr mode.
	 * The low level driver sets up the unused bit for MMC2 on Zoom2.
	 * Revert this hack once it is fixed in the card.
	 */
	if (card->host->unused) {
		card->ext_csd.sectors =
			ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
			ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
			ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
			ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
		if (card->ext_csd.sectors)
			mmc_card_set_blockaddr(card);
	} else
#endif
	if (card->ext_csd.rev >= 2) {
		card->ext_csd.sectors =
			ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
			ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
			ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
			ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
		if (mmc_card_blockaddr(card))
			mmc_card_set_blockaddr(card);
	}

	/* disable DDR detection */
	ext_csd[EXT_CSD_CARD_TYPE] &= EXT_CSD_CARD_TYPE_MASK;

	switch (ext_csd[EXT_CSD_CARD_TYPE]) {
	case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
		card->ext_csd.hs_max_dtr = 52000000;
		break;
	case EXT_CSD_CARD_TYPE_26:
		card->ext_csd.hs_max_dtr = 26000000;
		break;
	default:
		/* MMC v4 spec says this cannot happen */
		printk(KERN_WARNING "%s: card is mmc v4 but doesn't "
			"support any high-speed modes.\n",
			mmc_hostname(card->host));
		goto out;
	}

	if (card->ext_csd.rev >= 3) {
		u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT];

		/* Sleep / awake timeout in 100ns units */
		if (sa_shift > 0 && sa_shift <= 0x17)
			card->ext_csd.sa_timeout =
					1 << ext_csd[EXT_CSD_S_A_TIMEOUT];
		else{
			card->ext_csd.sa_timeout = MMC_SLEEP_TIMEOUT_DEFAULT;
			printk(KERN_WARNING "%s: card's S_A_TIMEOUT is out of range.\n",mmc_hostname(card->host));
		}
	}

out:
	kfree(ext_csd);

	return err;
}

MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
	card->raw_cid[2], card->raw_cid[3]);
MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
	card->raw_csd[2], card->raw_csd[3]);
MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);

static struct attribute *mmc_std_attrs[] = {
	&dev_attr_cid.attr,
	&dev_attr_csd.attr,
	&dev_attr_date.attr,
	&dev_attr_fwrev.attr,
	&dev_attr_hwrev.attr,
	&dev_attr_manfid.attr,
	&dev_attr_name.attr,
	&dev_attr_oemid.attr,
	&dev_attr_serial.attr,
	NULL,
};

static struct attribute_group mmc_std_attr_group = {
	.attrs = mmc_std_attrs,
};

static struct attribute_group *mmc_attr_groups[] = {
	&mmc_std_attr_group,
	NULL,
};

static struct device_type mmc_type = {
	.groups = mmc_attr_groups,
};

/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err;
	u32 cid[4];
	u32 rocr;
	unsigned int max_dtr;

	BUG_ON(!host);
	WARN_ON(!host->claimed);

	/*
	 * Since we're changing the OCR value, we seem to
	 * need to tell some cards to go back to the idle
	 * state.  We wait 1ms to give cards time to
	 * respond.
	 */
	mmc_go_idle(host);

	/* The extra bit indicates that we support high capacity */
	err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
	if (err)
		goto err;

	/*
	 * For SPI, enable CRC as appropriate.
	 */
	if (mmc_host_is_spi(host)) {
		err = mmc_spi_set_crc(host, use_spi_crc);
		if (err)
			goto err;
	}

	/*
	 * Fetch CID from card.
	 */
	if (mmc_host_is_spi(host))
		err = mmc_send_cid(host, cid);
	else
		err = mmc_all_send_cid(host, cid);
	if (err)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
			err = -ENOENT;
			goto err;
		}

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host, &mmc_type);
		if (IS_ERR(card)) {
			err = PTR_ERR(card);
			goto err;
		}

		card->type = MMC_TYPE_MMC;
		card->rca = 1;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));

		/*
		 * If the OCR response to OP_COND from
		 * the card ack block addressing then
		 * enable it
                 */
		if (rocr & MMC_CARD_ACCESS_MODE_MASK)
			mmc_card_set_blockaddr(card);

	}

	/*
	 * For native busses:  set card RCA and quit open drain mode.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_set_relative_addr(card);
		if (err)
			goto free_card;

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}

	if (!oldcard) {
		/*
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err)
			goto free_card;
		err = mmc_decode_cid(card);
		if (err)
			goto free_card;
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
			goto free_card;
	}

	if (!oldcard) {
		/*
		 * Fetch and process extended CSD.
		 */
		err = mmc_read_ext_csd(card);
		if (err)
			goto free_card;
	}

	/*
	 * Activate high speed (if supported)
	 */
	if ((card->ext_csd.hs_max_dtr != 0) &&
		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_HS_TIMING, 1);
		if (err)
			goto free_card;

		mmc_card_set_highspeed(card);

		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
	}

	/*
	 * Compute bus speed.
	 */
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->ext_csd.hs_max_dtr)
			max_dtr = card->ext_csd.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}

	mmc_set_clock(host, max_dtr);

	/*
	 * Activate wide bus (if supported).
	 */
	if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
	    (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
		unsigned ext_csd_bit, bus_width;

		if (host->caps & MMC_CAP_8_BIT_DATA) {
			ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
			bus_width = MMC_BUS_WIDTH_8;
		} else {
			ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
			bus_width = MMC_BUS_WIDTH_4;
		}

		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_BUS_WIDTH, ext_csd_bit);

		if (err)
			goto free_card;

		mmc_set_bus_width(card->host, bus_width);
	}

	if (!oldcard)
		host->card = card;

	return 0;

free_card:
	if (!oldcard)
		mmc_remove_card(card);
err:

	return err;
}

/*
 * Host is being removed. Free up the current card.
 */
static void mmc_remove(struct mmc_host *host)
{
	BUG_ON(!host);
	BUG_ON(!host->card);

	mmc_remove_card(host->card);
	host->card = NULL;
}
Exemplo n.º 11
0
int skymedi_low_level_process(struct mmc *mmc)
{
	int ret;
	card_power_off_on();
	mmc->has_init = 0;
	mmc->init_in_progress = 0;
	ret = mmc_init(mmc);
	if (ret)
		return ret;
	mmc_set_bus_width(mmc, 1);

	ret = skymedi_set_func(mmc, 0x00000055);
	if (ret)
		return ret;
	ret = skymedi_set_func(mmc, 0x00000057);	//disable special function
	if (ret)
		return ret;
	ret = skymedi_write_file(mmc, 0x80000014, "ERASE.bin", 3000);
	if (ret == 0)
		return -1;
	ret = skymedi_set_func(mmc, 0x00000056);
	if (ret)
		return ret;
	ret = skymedi_write_file(mmc, 0xE0000001, "LLF_Parameter.bin", 3000);
	if (ret == 0)
		return -1;

	ret = skymedi_perform_erase(mmc, 0x00000000, 100000);
	if (ret)
		return ret;
	ret = skymedi_set_func(mmc, 0x00000057);
	if (ret)
		return ret;

	card_power_off_on();
	mmc->has_init = 0;
	mmc->init_in_progress = 0;
	ret = mmc_init(mmc);
	if (ret)
		return ret;

	ret = skymedi_set_func(mmc, 0x00000055);
	if (ret)
		return ret;
	ret = skymedi_set_func(mmc, 0x00000057);
	if (ret)
		return ret;
	ret = skymedi_write_file(mmc, 0x80000014, "LLF1.bin", 3000);
	if (ret == 0)
		return -1;
	ret = skymedi_set_func(mmc, 0x00000056);
	if (ret)
		return ret;
	ret = skymedi_write_file(mmc, 0xE0000001, "LLF_Parameter.bin", 100000);
	if (ret == 0)
		return -1;

	ret = skymedi_read_one_block(mmc, sector_buff, 0x00000072);	//Temp.bin
	if (sector_buff[0] != 0x65 || sector_buff[1] != 0x67) {
		printf("LLF STATUS = %x %x\n", sector_buff[0], sector_buff[1]);
		return -1;
	}

	ret = skymedi_set_func(mmc, 0x00000057);
	if (ret)
		return ret;
	ret = skymedi_write_file(mmc, 0x80000014, "ERASE.bin", 3000);
	if (ret == 0)
		return -1;
	ret = skymedi_set_func(mmc, 0x00000056);
	if (ret)
		return ret;
	ret = skymedi_write_file(mmc, 0xFFFFFF10, "FDM.bin", 3000);
	if (ret == 0)
		return -1;
	ret =
	    skymedi_read_blocks(mmc, sector_buff, 0xFFFFFF10, 64 * 1024 / 512);
	if (ret == 0)
		return -1;
	//Compare temp1.bin with FDM.bin ?????

	ret = skymedi_write_file(mmc, 0xFFFFFF20, "FDM.bin", 3000);
	if (ret == 0)
		return -1;
	ret =
	    skymedi_read_blocks(mmc, sector_buff, 0xFFFFFF20, 64 * 1024 / 512);
	if (ret == 0)
		return -1;
	//Compare temp1.bin with FDM.bin ?????

	return 0;
}
Exemplo n.º 12
0
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err;
	u32 cid[4];
	unsigned int max_dtr;
#ifdef CONFIG_MMC_PARANOID_SD_INIT
	int retries;
#endif
	BUG_ON(!host);
	WARN_ON(!host->claimed);

	/*
	 * Since we're changing the OCR value, we seem to
	 * need to tell some cards to go back to the idle
	 * state.  We wait 1ms to give cards time to
	 * respond.
	 */
	mmc_go_idle(host);

	/*
	 * If SD_SEND_IF_COND indicates an SD 2.0
	 * compliant card and we should set bit 30
	 * of the ocr to indicate that we can handle
	 * block-addressed SDHC cards.
	 */
	err = mmc_send_if_cond(host, ocr);
	if (!err)
		ocr |= 1 << 30;

	err = mmc_send_app_op_cond(host, ocr, NULL);
	if (err)
		goto err;

	/*
	 * Fetch CID from card.
	 */
	if (mmc_host_is_spi(host))
		err = mmc_send_cid(host, cid);
	else
		err = mmc_all_send_cid(host, cid);
	if (err)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
			err = -ENOENT;
			goto err;
		}

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host, &sd_type);
		if (IS_ERR(card)) {
			err = PTR_ERR(card);
			goto err;
		}

		card->type = MMC_TYPE_SD;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
	}

	/*
	 * For native busses:  get card RCA and quit open drain mode.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_send_relative_addr(host, &card->rca);
		if (err)
			goto free_card;

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}

	if (!oldcard) {
		/*
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err)
			goto free_card;

		mmc_decode_cid(card);
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
			goto free_card;
	}

	if (!oldcard) {
		/*
		 * Fetch SCR from card.
		 */
		err = mmc_app_send_scr(card, card->raw_scr);
		if (err)
			goto free_card;

		err = mmc_decode_scr(card);
		if (err < 0)
			goto free_card;
		/*
		 * Fetch switch information from card.
		 */
#ifdef CONFIG_MMC_PARANOID_SD_INIT
		for (retries = 1; retries <= 3; retries++) {
			err = mmc_read_switch(card);
			if (!err) {
				if (retries > 1) {
					printk(KERN_WARNING
					       "%s: recovered\n", 
					       mmc_hostname(host));
				}
				break;
			} else {
				printk(KERN_WARNING
				       "%s: read switch failed (attempt %d)\n",
				       mmc_hostname(host), retries);
			}
		}
#else
		err = mmc_read_switch(card);
#endif

		if (err)
			goto free_card;
	}

	/*
	 * For SPI, enable CRC as appropriate.
	 * This CRC enable is located AFTER the reading of the
	 * card registers because some SDHC cards are not able
	 * to provide valid CRCs for non-512-byte blocks.
	 */
	if (mmc_host_is_spi(host)) {
		err = mmc_spi_set_crc(host, use_spi_crc);
		if (err)
			goto free_card;
	}

	/*
	 * Attempt to change to high-speed (if supported)
	 */
	err = mmc_switch_hs(card);
	if (err)
		goto free_card;

	/*
	 * Compute bus speed.
	 */
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->sw_caps.hs_max_dtr)
			max_dtr = card->sw_caps.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}

	mmc_set_clock(host, max_dtr);

	/*
	 * Switch to wider bus (if supported).
	 */
	if ((host->caps & MMC_CAP_4_BIT_DATA) &&
		(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
		err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
		if (err)
			goto free_card;

		mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
	}

	/*
	 * Check if read-only switch is active.
	 */
	if (!oldcard) {
		if (!host->ops->get_ro || host->ops->get_ro(host) < 0) {
			printk(KERN_WARNING "%s: host does not "
				"support reading read-only "
				"switch. assuming write-enable.\n",
				mmc_hostname(host));
		} else {
			if (host->ops->get_ro(host) > 0)
				mmc_card_set_readonly(card);
		}
	}

	if (!oldcard)
		host->card = card;

	return 0;

free_card:
	if (!oldcard)
		mmc_remove_card(card);
err:

	return err;
}
Exemplo n.º 13
0
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err, ddr = 0;
	int card_is_null = 0;
	u32 cid[4];
	unsigned int max_dtr;
	u32 rocr;
	u8 *ext_csd = NULL;

	BUG_ON(!host);
	WARN_ON(!host->claimed);

	/*
	 * Since we're changing the OCR value, we seem to
	 * need to tell some cards to go back to the idle
	 * state.  We wait 1ms to give cards time to
	 * respond.
	 */
	mmc_go_idle(host);

	/* The extra bit indicates that we support high capacity */
	err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
	if (err)
		goto err;

	/*
	 * For SPI, enable CRC as appropriate.
	 */
	if (mmc_host_is_spi(host)) {
		err = mmc_spi_set_crc(host, use_spi_crc);
		if (err)
			goto err;
	}

	/*
	 * Fetch CID from card.
	 */
	if (mmc_host_is_spi(host))
		err = mmc_send_cid(host, cid);
	else
		err = mmc_all_send_cid(host, cid);
	if (err)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
			err = -ENOENT;
			goto err;
		}

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host, &mmc_type);
		if (IS_ERR(card)) {
			err = PTR_ERR(card);
			goto err;
		}

		card->type = MMC_TYPE_MMC;
		card->rca = 1;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
	}

	/*
	 * For native busses:  set card RCA and quit open drain mode.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_set_relative_addr(card);
		if (err)
			goto free_card;

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}

	if (!oldcard) {
		/*
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err)
			goto free_card;
		err = mmc_decode_cid(card);
		if (err)
			goto free_card;
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
			goto free_card;
	}

	if (!oldcard) {
		/*
		 * Fetch and process extended CSD.
		 */

		err = mmc_get_ext_csd(card, &ext_csd);
		if (err)
			goto free_card;
		err = mmc_read_ext_csd(card, ext_csd);
		if (err)
			goto free_card;

		/* If doing byte addressing, check if required to do sector
		 * addressing.  Handle the case of <2GB cards needing sector
		 * addressing.  See section 8.1 JEDEC Standard JED84-A441;
		 * ocr register has bit 30 set for sector addressing.
		 */
		if (!(mmc_card_blockaddr(card)) && (rocr & (1<<30)))
			mmc_card_set_blockaddr(card);

		/* Erase size depends on CSD and Extended CSD */
		mmc_set_erase_size(card);
	}

	/*
	 * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
	 * bit.  This bit will be lost every time after a reset or power off.
	 */
	if (card->ext_csd.enhanced_area_en) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_ERASE_GROUP_DEF, 1, 0);

		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			err = 0;
			/*
			 * Just disable enhanced area off & sz
			 * will try to enable ERASE_GROUP_DEF
			 * during next time reinit
			 */
			card->ext_csd.enhanced_area_offset = -EINVAL;
			card->ext_csd.enhanced_area_size = -EINVAL;
		} else {
			card->ext_csd.erase_group_def = 1;
			/*
			 * enable ERASE_GRP_DEF successfully.
			 * This will affect the erase size, so
			 * here need to reset erase size
			 */
			mmc_set_erase_size(card);
		}
	}

	/*
	 * Ensure eMMC user default partition is enabled
	 */
	if (card->ext_csd.part_config & EXT_CSD_PART_CONFIG_ACC_MASK) {
		card->ext_csd.part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONFIG,
				 card->ext_csd.part_config,
				 card->ext_csd.part_time);
		if (err && err != -EBADMSG)
			goto free_card;
	}

	/*
	 * Activate high speed (if supported)
	 */
	if ((card->ext_csd.hs_max_dtr != 0) &&
		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_HS_TIMING, 1, 0);
		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			printk(KERN_WARNING "%s: switch to highspeed failed\n",
			       mmc_hostname(card->host));
			err = 0;
		} else {
			mmc_card_set_highspeed(card);
			mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
		}
	}

	/*
	 * Compute bus speed.
	 */
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->ext_csd.hs_max_dtr)
			max_dtr = card->ext_csd.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}

	mmc_set_clock(host, max_dtr);

	if (!host->card) {
		host->card = card;
		card_is_null = 1;
	}

	if (card->host->ops->execute_tuning)
		card->host->ops->execute_tuning(card->host);

	/*
	 * Indicate DDR mode (if supported).
	 */
	if (mmc_card_highspeed(card)) {
		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
			&& ((host->caps & (MMC_CAP_1_8V_DDR |
			     MMC_CAP_UHS_DDR50))
				== (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50)))
				ddr = MMC_1_8V_DDR_MODE;
		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
			&& ((host->caps & (MMC_CAP_1_2V_DDR |
			     MMC_CAP_UHS_DDR50))
				== (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50)))
				ddr = MMC_1_2V_DDR_MODE;
	}

	/*
	 * Activate wide bus and DDR (if supported).
	 */
	if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
	    (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
		static unsigned ext_csd_bits[][2] = {
			{ EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
			{ EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 },
			{ EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 },
		};
		static unsigned bus_widths[] = {
			MMC_BUS_WIDTH_8,
			MMC_BUS_WIDTH_4,
			MMC_BUS_WIDTH_1
		};
		unsigned idx, bus_width = 0;

		if (host->caps & MMC_CAP_8_BIT_DATA)
			idx = 0;
		else
			idx = 1;
		for (; idx < ARRAY_SIZE(bus_widths); idx++) {
			bus_width = bus_widths[idx];
			if (bus_width == MMC_BUS_WIDTH_1)
				ddr = 0; /* no DDR for 1-bit width */
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					 EXT_CSD_BUS_WIDTH,
					 ext_csd_bits[idx][0],
					 0);
			if (!err) {
				mmc_set_bus_width(card->host, bus_width);

				/*
				 * If controller can't handle bus width test,
				 * compare ext_csd previously read in 1 bit mode
				 * against ext_csd at new bus width
				 */
				if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST)) {
					/*
					err = mmc_compare_ext_csds(card,
						ext_csd,
						bus_width);
					*/
				} else
					err = mmc_bus_test(card, bus_width);
				if (!err)
					break;
			}
		}

		if (!err && ddr) {
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					 EXT_CSD_BUS_WIDTH,
					 ext_csd_bits[idx][1],
					 0);
		}
		if (err) {
			printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
				"failed\n", mmc_hostname(card->host),
				1 << bus_width, ddr);
			if (card_is_null)
				host->card = NULL;

			goto free_card;
		} else if (ddr) {
			/*
			 * eMMC cards can support 3.3V to 1.2V i/o (vccq)
			 * signaling.
			 *
			 * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq.
			 *
			 * 1.8V vccq at 3.3V core voltage (vcc) is not required
			 * in the JEDEC spec for DDR.
			 *
			 * Do not force change in vccq since we are obviously
			 * working and no change to vccq is needed.
			 *
			 * WARNING: eMMC rules are NOT the same as SD DDR
			 */
			if (ddr == EXT_CSD_CARD_TYPE_DDR_1_2V) {
				err = mmc_set_signal_voltage(host,
					MMC_SIGNAL_VOLTAGE_120, 0);
				if (err) {
					if (card_is_null)
						host->card = NULL;
					goto err;
				}
			}
			mmc_card_set_ddr_mode(card);
			mmc_set_timing(card->host, MMC_TIMING_UHS_DDR50);
			mmc_set_bus_width(card->host, bus_width);
		}
	}

	if (!oldcard)
		host->card = card;

	if (card->host->ops->execute_tuning)
		card->host->ops->execute_tuning(card->host);

	mmc_free_ext_csd(ext_csd);
	return 0;

free_card:
	if (!oldcard)
		mmc_remove_card(card);
err:
	mmc_free_ext_csd(ext_csd);

	return err;
}
Exemplo n.º 14
0
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err;
	u32 cid[4];

	BUG_ON(!host);
	WARN_ON(!host->claimed);

	err = mmc_sd_get_cid(host, ocr, cid);
	if (err)
		return err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
			return -ENOENT;

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host, &sd_type);
		if (IS_ERR(card))
			return PTR_ERR(card);

		card->type = MMC_TYPE_SD;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
	}

	/*
	 * For native busses:  get card RCA and quit open drain mode.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_send_relative_addr(host, &card->rca);
		if (err)
			return err;

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}

	if (!oldcard) {
		err = mmc_sd_get_csd(host, card);
		if (err)
			return err;

		mmc_decode_cid(card);
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
			return err;
	}

	err = mmc_sd_setup_card(host, card, oldcard != NULL);
	if (err)
		goto free_card;

	/*
	 * Attempt to change to high-speed (if supported)
	 */
	err = mmc_sd_switch_hs(card);
	if (err > 0)
		mmc_sd_go_highspeed(card);
	else if (err)
		goto free_card;

	/*
	 * Set bus speed.
	 */
	mmc_set_clock(host, mmc_sd_get_max_clock(card));

	/*
	 * Switch to wider bus (if supported).
	 */
	if ((host->caps & MMC_CAP_4_BIT_DATA) &&
		(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
		err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
		if (err)
			goto free_card;

		mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
	}

	host->card = card;
	return 0;

free_card:
	if (!oldcard)
		mmc_remove_card(card);

	return err;
}
Exemplo n.º 15
0
int mmc_test_mem_card(struct mmc_test_config *cfg)
{
    int id, count, forever;
    int ret, chk_result, tid = 0, result = 0;
    unsigned int chunks, chunk_blks, left_blks, pass = 0, fail = 0;
    unsigned int total_blks;
    unsigned int i, j;
    unsigned int blksz;
    unsigned int clkhz;    
    char pattern = 0;
    char *buf;
    unsigned long blknr;
    struct mmc_host *host;
    struct mmc_card *card;

    id    = cfg->id;
    count = cfg->count;
    buf   = cfg->buf;
    blknr = cfg->blknr;
    blksz = cfg->blksz;

    chk_result = cfg->chk_result;
    chunk_blks = cfg->chunk_blks;
    total_blks = (cfg->total_size + blksz - 1) / blksz;
    forever    = (count == -1) ? 1 : 0;

    host = mmc_get_host(id);
    card = mmc_get_card(id);

    while (forever || count--) {
        printf("[TST] ==============================================\n");
        printf("[TST] BEGIN: %d/%d, No Stop(%d)\n", 
            (cfg->count != -1) ? cfg->count - count : 0, 
            (cfg->count != -1) ? cfg->count : 0, forever);
        printf("[TST] ----------------------------------------------\n");
        printf("[TST] Mode    : %d\n", cfg->mode);
        printf("[TST] Clock   : %d kHz\n", cfg->clock / 1000);
        printf("[TST] BusWidth: %d bits\n", cfg->buswidth);
        printf("[TST] BurstSz : %d bytes\n", 0x1 << cfg->burstsz);
        printf("[TST] BlkAddr : %xh\n", blknr);
        printf("[TST] BlkSize : %dbytes\n", blksz);
        printf("[TST] TstBlks : %d\n", total_blks);
#if defined(BB_MT6575)
        printf("[TST] AutoCMD : 12(%d), 23(%d)\n", 
            (cfg->autocmd & MSDC_AUTOCMD12) ? 1 : 0, 
            (cfg->autocmd & MSDC_AUTOCMD23) ? 1 : 0);
#endif
        printf("[TST] ----------------------------------------------\n");


        if (mmc_init_host(host, id) != 0) {
            result = -__LINE__;
            goto failure;
        }
        if (mmc_init_card(host, card) != 0) {
            result = -__LINE__;
            goto failure;
        }
#if defined(BB_MT6575)
        msdc_set_dma(host, (u8)cfg->burstsz, (u32)cfg->flags);
        msdc_set_autocmd(host, cfg->autocmd, 1);
#endif

        /* change uhs-1 mode */
#if 0        
        if (mmc_card_uhs1(card)) {
            if (mmc_switch_uhs1(host, card, cfg->uhsmode) != 0) {
                result = -__LINE__;
                goto failure;
            }
        }
#endif

        /* change clock */
        if (cfg->clock) {
            clkhz = card->maxhz < cfg->clock ? card->maxhz : cfg->clock;
            mmc_set_clock(host, mmc_card_ddr(card), clkhz); 
        }
        if (mmc_card_sd(card) && cfg->buswidth == HOST_BUS_WIDTH_8) {
            printf("[TST] SD card doesn't support 8-bit bus width (SKIP)\n");
            result = MMC_ERR_NONE;
        }
        if (mmc_set_bus_width(host, card, cfg->buswidth) != 0) {
            result = -__LINE__;
            goto failure;
        }

        /* cmd16 is illegal while card is in ddr mode */
        if (!(mmc_card_mmc(card) && mmc_card_ddr(card))) {
            if (mmc_set_blk_length(host, blksz) != 0) {
                result = -__LINE__;
                goto failure;            
            }
        }

#if defined(BB_MT6575)
        if (cfg->piobits) {
            printf("[TST] PIO bits: %d\n", cfg->piobits);
            msdc_set_pio_bits(host, cfg->piobits);
        }
#endif
        tid = result = 0;        

        if (mmc_erase_start(card, blknr * blksz) != MMC_ERR_NONE) {
            result = -__LINE__;
            goto failure;
        }
        if (mmc_erase_end(card, (blknr + total_blks) * blksz) != MMC_ERR_NONE) {
            result = -__LINE__;
            goto failure;
        }
        if (mmc_erase(card, MMC_ERASE_NORMAL) != MMC_ERR_NONE) {
            result = -__LINE__;
            goto failure;        
        }
        printf("[TST] 0x%x - 0x%x Erased\n", blknr * blksz, 
            (blknr + total_blks) * blksz);

        mmc_send_status(host, card, &status);

        if (cfg->tst_single) {
            /* single block write */
            for (i = 0; i < total_blks; i++) {
                pattern = (i + count) % 256;
                memset(buf, pattern, blksz);
                ret = mmc_block_write(id, blknr + i, 1, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    printf("test single block write failed (%d)\n", i);
                    result = -__LINE__;
                    goto failure;
                }
            }

            printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, 
                "test single block write\n");

            if (result)
                break;
            
            /* single block read */
            for (i = 0; i < total_blks && !result; i++) {
                pattern = (i + count) % 256;
                /* populate buffer with different pattern */
                memset(buf, pattern + 1, blksz);
                ret = mmc_block_read(id, blknr + i, 1, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    goto failure;
                }
                if (chk_result) {
                    for (j = 0; j < blksz; j++) {
                        if (buf[j] != pattern) {
                            result = -__LINE__;
                            goto failure;
                        }
                    }
                }
            }
            printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, 
                "test single block read\n");

            if (result) {
                printf("[SD%d]\t\tread back pattern(0x%.2x) failed\n", 
                    id, pattern);
                goto failure;
            }
        }

        mmc_send_status(host, card, &status);
        
        if (cfg->tst_multiple) {
            /* multiple block write */
            chunks = total_blks / chunk_blks;
            left_blks = total_blks % chunk_blks;   
            for (i = 0; i < chunks; i++) {
                pattern = (i + count) % 256;
                memset(buf, pattern, blksz * chunk_blks);
                ret = mmc_block_write(id, blknr + i * chunk_blks, 
                    chunk_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    goto failure;
                }
            }
            
            if (!result && left_blks) {
                pattern = (i + count) % 256;
                memset(buf, pattern, blksz * left_blks);
                ret = mmc_block_write(id, blknr + chunks * chunk_blks, 
                    left_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    goto failure;
                }
            }

            printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, 
                "test multiple block write\n");

            if (result)
                goto failure;

            /* multiple block read */
            for (i = 0; i < chunks; i++) {
                pattern = (i + count) % 256;
                /* populate buffer with different pattern */
                memset(buf, pattern + 1, blksz);
                ret = mmc_block_read(id, blknr + i * chunk_blks, 
                    chunk_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    printf("[SD%d]\t\tread %d blks failed(ret = %d blks)\n",
                        host->id, chunk_blks, ret);
                    result = -__LINE__;
                    goto failure;
                }
                if (chk_result) {
                    for (j = 0; j < chunk_blks * blksz; j++) {
                        if (buf[j] == pattern)
                            continue;
                        result = -__LINE__;
                        printf("[SD%d]\t\t%xh = %x (!= %x)\n",
                            host->id, blknr + i * chunk_blks + j, buf[j], pattern);
                        goto failure;
                    }
                }
            }

            if (!result && left_blks) {
                pattern = i % 256;
                /* populate buffer with different pattern */
                memset(buf, pattern + 1, blksz);
                ret = mmc_block_read(id, blknr + chunks * chunk_blks, 
                    left_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    printf("[SD%d]\t\tread %d blks failed(ret = %d blks)\n",
                        host->id, left_blks, ret);
                    result = -__LINE__;
                    goto failure;
                }
                if (chk_result) {
                    for (j = 0; j < left_blks * blksz; j++) {
                        if (buf[j] == pattern)
                            continue;
                        printf("[SD%d]\t\t%xh = %x (!= %x)\n",
                            host->id, blknr + chunks * chunk_blks + j, buf[j], pattern);
                        result = -__LINE__;
                        goto failure;
                    }
                }
            }

            printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, 
                "test multiple block read\n");

            if (result)
                goto failure;
        }

        mmc_send_status(host, card, &status);

        if (cfg->tst_interleave) {
            /* multiple block write */
            chunks = total_blks / chunk_blks;
            left_blks = total_blks % chunk_blks;   
            for (i = 0; i < chunks; i++) {
                pattern = (i + count) % 256;
                memset(buf, pattern, blksz * chunk_blks);
                ret = mmc_block_write(id, blknr + i * chunk_blks, 
                    chunk_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    goto failure;
                }

                /* populate buffer with different pattern */
                memset(buf, pattern + 1, blksz * chunk_blks);
                ret = mmc_block_read(id, blknr + i * chunk_blks, 
                    chunk_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    goto failure;
                }
                if (chk_result) {
                    for (j = 0; j < chunk_blks * blksz; j++) {
                        if (buf[j] == pattern) 
                            continue;
                        result = -__LINE__;
                        goto failure;
                    }
                }                
            }           

            if (!result && left_blks) {
                pattern = (i + count) % 256;
                memset(buf, pattern, blksz * left_blks);
                ret = mmc_block_write(id, blknr + chunks * chunk_blks, 
                    left_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    goto failure;
                }

                /* populate buffer with different pattern */
                memset(buf, pattern + 1, blksz * left_blks);
                ret = mmc_block_read(id, blknr + chunks * chunk_blks, 
                    left_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    break;
                }
                if (chk_result) {
                    for (j = 0; j < left_blks * blksz; j++) {
                        if (buf[j] == pattern)
                            continue;
                        result = -__LINE__;
                        goto failure;
                    }
                }
            }

            printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, 
                "test multiple block interleave write-read\n");

            if (result)
                goto failure;
        }
        if (cfg->desc) {
            printf("[TST] ----------------------------------------------\n");
            printf("[TST] Report - %s \n", cfg->desc);
            printf("[TST] ----------------------------------------------\n");
        }
        mmc_prof_dump(id);

failure:
        if (result) {
            printf("[SD%d] mmc test failed (%d)\n", host->id, result);
            fail++;
        } else {
            pass++;
        }
        printf("[TST] ----------------------------------------------\n");
        printf("[TST] Test Result: TOTAL(%d/%d), PASS(%d), FAIL(%d) \n", 
            cfg->count - count, cfg->count, pass, fail);
        printf("[TST] ----------------------------------------------\n");    
    	//mdelay(1000);
    }

    return result;
}
Exemplo n.º 16
0
Arquivo: mmc.c Projeto: cilynx/dd-wrt
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "curcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err;
	u32 cid[4];
	unsigned int max_dtr;

	BUG_ON(!host);
	BUG_ON(!host->claimed);

	/*
	 * Since we're changing the OCR value, we seem to
	 * need to tell some cards to go back to the idle
	 * state.  We wait 1ms to give cards time to
	 * respond.
	 */
	mmc_go_idle(host);

	/* The extra bit indicates that we support high capacity */
	err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
	if (err != MMC_ERR_NONE)
		goto err;

	/*
	 * Fetch CID from card.
	 */
	err = mmc_all_send_cid(host, cid);
	if (err != MMC_ERR_NONE)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
			goto err;

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host);
		if (IS_ERR(card))
			goto err;

		card->type = MMC_TYPE_MMC;
		card->rca = 1;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
	}

	/*
	 * Set card RCA.
	 */
	err = mmc_set_relative_addr(card);
	if (err != MMC_ERR_NONE)
		goto free_card;

	mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);

	if (!oldcard) {
		/*
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err != MMC_ERR_NONE)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err < 0)
			goto free_card;
		err = mmc_decode_cid(card);
		if (err < 0)
			goto free_card;
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	err = mmc_select_card(card);
	if (err != MMC_ERR_NONE)
		goto free_card;

	if (!oldcard) {
		/*
		 * Fetch and process extened CSD.
		 */
		err = mmc_read_ext_csd(card);
		if (err != MMC_ERR_NONE)
			goto free_card;
	}

	/*
	 * Activate high speed (if supported)
	 */
	if ((card->ext_csd.hs_max_dtr != 0) &&
		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_HS_TIMING, 1);
		if (err != MMC_ERR_NONE)
			goto free_card;

		mmc_card_set_highspeed(card);

		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
	}

	/*
	 * Compute bus speed.
	 */
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->ext_csd.hs_max_dtr)
			max_dtr = card->ext_csd.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}

	mmc_set_clock(host, max_dtr);

	/*
	 * Activate wide bus (if supported).
	 */
	if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
		(host->caps & MMC_CAP_4_BIT_DATA)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4);
		if (err != MMC_ERR_NONE)
			goto free_card;

		mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
	}

	if (!oldcard)
		host->card = card;

	return MMC_ERR_NONE;

free_card:
	if (!oldcard)
		mmc_remove_card(card);
err:

	return MMC_ERR_FAILED;
}
Exemplo n.º 17
0
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "curcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err;
	u32 cid[4];
	unsigned int max_dtr;
	unsigned int card_supports_8bit = 1;

	BUG_ON(!host);
	BUG_ON(!host->claimed);

	/*
	 * Since we're changing the OCR value, we seem to
	 * need to tell some cards to go back to the idle
	 * state.  We wait 1ms to give cards time to
	 * respond.
	 */
	mmc_go_idle(host);

	/* The extra bit indicates that we support high capacity */
	err = mmc_send_op_cond(host, ocr | (1 << 30), &ocr);
	if (err != MMC_ERR_NONE)
		goto err;

	/*
	 * Fetch CID from card.
	 */
	err = mmc_all_send_cid(host, cid);
	if (err != MMC_ERR_NONE)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
			goto err;

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host);
		if (IS_ERR(card))
			goto err;

		card->type = MMC_TYPE_MMC;
		card->rca = 1;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));

		printk(KERN_WARNING "[kwwo]%s: mmc-card detected\n",	mmc_hostname(card->host));
	}

	/*
	 * Set card RCA.
	 */
	err = mmc_set_relative_addr(card);
	if (err != MMC_ERR_NONE)
		goto free_card;

	mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);

	if (!oldcard) {
		/*
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err != MMC_ERR_NONE)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err < 0)
			goto free_card;
		err = mmc_decode_cid(card);
		if (err < 0)
			goto free_card;
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	err = mmc_select_card(card);
	if (err != MMC_ERR_NONE)
		goto free_card;

	if (!oldcard) {
		/*
		 * Fetch and process extened CSD.
		 */
		err = mmc_read_ext_csd(card);
		if (err != MMC_ERR_NONE)
			goto free_card;
	}

	/*
	 * Activate block addressing mode (if supported)
	 */
	if ( (ocr & (3 << 29)) == (2 << 29))
		mmc_card_set_blockaddr(card);

	/*
	 * Activate high speed (if supported)
	 */
	if ((card->ext_csd.hs_max_dtr != 0) &&
		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_HS_TIMING, 1);
		if (err != MMC_ERR_NONE)
			goto free_card;

		mmc_card_set_highspeed(card);

		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
	}

	/*
	 * Compute bus speed.
	 */
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->ext_csd.hs_max_dtr)
			max_dtr = card->ext_csd.hs_max_dtr;
			printk(KERN_INFO "[kwwo]%s: hs ext_csd.hs_max_dtr=%d\n",	mmc_hostname(card->host), max_dtr);
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
		printk(KERN_WARNING "[kwwo]%s: csd.max_dtr=%d\n", mmc_hostname(card->host), max_dtr);
		/* Limit 32nm MoviNAND MMC clock under 20MHz*/
		if ( max_dtr > 20000000 ) {
			max_dtr = 20000000;
			printk(KERN_WARNING "MMC clk forced max. 20 MHz (16.5MHz)\n");
		}
	}

	/*  Workarounds for buggy cards */
	if (card->cid.manfid == MMC_MANUFACTURER_SAMSUNG) {
		const int spare4bmaxspeed = 34700000;
		switch (card->cid.prv) {
			case 0x1b:
			case 0x16:
				if (max_dtr > spare4bmaxspeed) {
					/* reduce clock to below 34.7 MHz, 4 bit mode */
					max_dtr = spare4bmaxspeed;
					card_supports_8bit = 0;
					printk(KERN_INFO "MMC: enabling workaround for movinand spare4b issue\n");
				}
				break;
		}
	}

	mmc_set_clock(host, max_dtr);

	/*
	 * Activate wide bus (if supported).
	 */
	if( card->csd.mmca_vsn >= CSD_SPEC_VER_4 )
	{
#ifdef CONFIG_MMC_8_BIT_TRANSFERS
		if ( (host->caps & MMC_CAP_8_BIT_DATA) && (card_supports_8bit) )
		{
			err = mmc_switch( card, EXT_CSD_CMD_SET_NORMAL,
				EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8 );
			if( err != MMC_ERR_NONE )
				goto free_card;

			mmc_set_bus_width( card->host, MMC_BUS_WIDTH_8 );
		}
		else
#endif
		if( host->caps & MMC_CAP_4_BIT_DATA )
		{
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4);
			if (err != MMC_ERR_NONE)
				goto free_card;

			mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
		}
	}

	if (!oldcard)
		host->card = card;

	return MMC_ERR_NONE;

free_card:
	if (!oldcard)
		mmc_remove_card(card);
err:

	return MMC_ERR_FAILED;
}
static int mmc_set_bus_speed_mode(struct mmc_card *card, u32 speed)
{
	int err = 0;
	u32 clock = 0;
	u32 bus_width = 0;
	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
	u32 caps = card->host->caps, caps2 = card->host->caps2;

	/* HS_TIMING is set to 2 in HS200 and all other modes needs to be 1 */
	if (speed == UHS_DDR50_BUS_SPEED) {
		/* check card and host capability for DDR50 to proceed */
		if (!(((caps & MMC_CAP_1_8V_DDR) &&
				(card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)) ||
		  ((caps & MMC_CAP_1_2V_DDR) &&
				(card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)))) {
			err = -EINVAL;
			goto err_node;
		}
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					EXT_CSD_HS_TIMING, 1, 0);
		if (err) {
			pr_err("%s: switch to HS_TIMING failed with error %d\n",
				mmc_hostname(card->host), err);
			goto err_node;
		} else {
			if (card->host->caps & MMC_CAP_8_BIT_DATA)
				bus_width = EXT_CSD_DDR_BUS_WIDTH_8;
			else
				bus_width = EXT_CSD_DDR_BUS_WIDTH_4;
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					EXT_CSD_BUS_WIDTH,
					bus_width,
					card->ext_csd.generic_cmd6_time);
			if (err) {
				pr_err("%s: switch to bus width failed",
						mmc_hostname(card->host));
				pr_err("with error %d\n", err);
				goto err_node;
			}
			clock = MMC_HIGH_DDR_MAX_DTR;
		}
	} else {
		/* check card and host capability for HS200 to proceed */
		if (!(((caps2 & MMC_CAP2_HS200_1_8V_SDR) &&
				(card_type & EXT_CSD_CARD_TYPE_SDR_1_8V)) ||
		  ((caps2 & MMC_CAP2_HS200_1_2V_SDR) &&
				(card_type & EXT_CSD_CARD_TYPE_SDR_1_2V)))) {
			err = -EINVAL;
			goto err_node;
		}

		/* Based on host capability, set card side bus width */
		if (card->host->caps & MMC_CAP_8_BIT_DATA)
			bus_width = EXT_CSD_BUS_WIDTH_8;
		else if (card->host->caps & MMC_CAP_4_BIT_DATA)
			bus_width = EXT_CSD_BUS_WIDTH_4;
		else
			bus_width = EXT_CSD_BUS_WIDTH_1;

		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					EXT_CSD_BUS_WIDTH,
					bus_width,
					card->ext_csd.generic_cmd6_time);
		if (err) {
			pr_err("%s: switch to bus width failed with error %d\n",
				mmc_hostname(card->host), err);
			goto err_node;
		}
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					EXT_CSD_HS_TIMING, 2, 0);
		if (err) {
			pr_err("%s: switch to HS_TIMING failed with error %d\n",
				mmc_hostname(card->host), err);
			goto err_node;
		}
		clock = MMC_HS200_MAX_DTR;
	}
	mmc_set_timing(card->host, card->host->ios.timing);
	if (card->host->ios.timing == MMC_TIMING_UHS_DDR50) {
		mmc_card_set_ddr_mode(card);
		card->state &= ~(MMC_STATE_HIGHSPEED_200
				 | MMC_STATE_HIGHSPEED_400
				 | MMC_STATE_HIGHSPEED);
	} else if (card->host->ios.timing == MMC_TIMING_MMC_HS200) {
		mmc_card_set_hs200(card);
		card->state &= ~(MMC_STATE_HIGHSPEED_DDR
				 | MMC_STATE_HIGHSPEED_400
				 | MMC_STATE_HIGHSPEED);
	}
	/* Based on bus width selected for card, set host side bus width */
	switch (bus_width) {
	case EXT_CSD_BUS_WIDTH_8:
	case EXT_CSD_DDR_BUS_WIDTH_8:
		mmc_set_bus_width(card->host, MMC_BUS_WIDTH_8);
		break;
	case EXT_CSD_BUS_WIDTH_4:
	case EXT_CSD_DDR_BUS_WIDTH_4:
		mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
		break;
	default:
		mmc_set_bus_width(card->host, MMC_BUS_WIDTH_1);
	}

	mmc_set_clock(card->host, clock);

err_node:
	return err;
}
Exemplo n.º 19
0
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err;
	u32 cid[4];
	unsigned int max_dtr;
	u32 rocr;

	BUG_ON(!host);
	WARN_ON(!host->claimed);

	/*
	 * Since we're changing the OCR value, we seem to
	 * need to tell some cards to go back to the idle
	 * state.  We wait 1ms to give cards time to
	 * respond.
	 */
	mmc_go_idle(host);

	/* The extra bit indicates that we support high capacity */
	err = mmc_send_op_cond(host, ocr | MMC_CARD_SECTOR_ADDR, &rocr);
	if (err)
		goto err;

	/*
	 * For SPI, enable CRC as appropriate.
	 */
	if (mmc_host_is_spi(host)) {
		err = mmc_spi_set_crc(host, use_spi_crc);
		if (err)
			goto err;
	}

	/*
	 * Fetch CID from card.
	 */
	if (mmc_host_is_spi(host))
		err = mmc_send_cid(host, cid);
	else
		err = mmc_all_send_cid(host, cid);
	if (err)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
			err = -ENOENT;
			goto err;
		}

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host, &mmc_type);
		if (IS_ERR(card)) {
			err = PTR_ERR(card);
			goto err;
		}

		card->type = MMC_TYPE_MMC;
		card->rca = 1;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
	}

	/*
	 * For native busses:  set card RCA and quit open drain mode.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_set_relative_addr(card);
		if (err)
			goto free_card;

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}

	if (!oldcard) {
		/*
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err)
			goto free_card;
		err = mmc_decode_cid(card);
		if (err)
			goto free_card;
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
			goto free_card;
	}

	if (!oldcard) {
		/*
		 * Fetch and process extended CSD.
		 */
		err = mmc_read_ext_csd(card);
		if (err)
			goto free_card;

		if (card->ext_csd.sectors && (rocr & MMC_CARD_SECTOR_ADDR))
			mmc_card_set_blockaddr(card);
	}

	/*
	 * Activate high speed (if supported)
	 */
	if ((card->ext_csd.hs_max_dtr != 0) &&
		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_HS_TIMING, 1);
		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			printk(KERN_WARNING "%s: switch to highspeed failed\n",
			       mmc_hostname(card->host));
			err = 0;
		} else {
			mmc_card_set_highspeed(card);
			mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
		}
	}

	/*
	 * Compute bus speed.
	 */
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->ext_csd.hs_max_dtr)
			max_dtr = card->ext_csd.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}

	mmc_set_clock(host, max_dtr);

	/*
	 * Activate wide bus (if supported).
	 */
	if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
	    (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
		unsigned ext_csd_bit, bus_width;

		if ((host->caps & MMC_CAP_8_BIT_DATA) &&
				!(mmc_bustest(host, card, MMC_BUS_WIDTH_8))) {
			pr_info("Setting the bus width to 8 bit\n");
			ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
			bus_width = MMC_BUS_WIDTH_8;
		} else if (!(mmc_bustest(host, card, MMC_BUS_WIDTH_4))) {
			pr_info("Setting the bus width to 4 bit\n");
			ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
			bus_width = MMC_BUS_WIDTH_4;
		} else {
			pr_info("Setting the bus width to 1 bit\n");
			ext_csd_bit = EXT_CSD_BUS_WIDTH_1;
			bus_width = MMC_BUS_WIDTH_1;
		}
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_BUS_WIDTH, ext_csd_bit);

		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			printk(KERN_WARNING "%s: switch to bus width %d "
			       "failed\n", mmc_hostname(card->host),
			       1 << bus_width);
			err = 0;
		} else {
			mmc_set_bus_width(card->host, bus_width);
		}
	}

	if (!oldcard)
		host->card = card;

	return 0;

free_card:
	if (!oldcard)
		mmc_remove_card(card);
err:

	return err;
}
Exemplo n.º 20
0
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err;
	u32 cid[4];
	unsigned int max_dtr;

	BUG_ON(!host);
	WARN_ON(!host->claimed);

	/*
	 * Since we're changing the OCR value, we seem to
	 * need to tell some cards to go back to the idle
	 * state.  We wait 1ms to give cards time to
	 * respond.
	 */
	mmc_go_idle(host);

	/* The extra bit indicates that we support high capacity */
#if !defined(CONFIG_PLAT_BCM476X)   // @KP: 090306
	err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
#else
	err = mmc_send_op_cond(host, ocr | (1 << 30), &(host->ocr));
#endif
	if (err)
		goto err;

	/*
	 * For SPI, enable CRC as appropriate.
	 */
	if (mmc_host_is_spi(host)) {
		err = mmc_spi_set_crc(host, use_spi_crc);
		if (err)
			goto err;
	}

	/*
	 * Fetch CID from card.
	 */
	if (mmc_host_is_spi(host))
		err = mmc_send_cid(host, cid);
	else
		err = mmc_all_send_cid(host, cid);
	if (err)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
			err = -ENOENT;
			goto err;
		}

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host, &mmc_type);
		if (IS_ERR(card)) {
			err = PTR_ERR(card);
			goto err;
		}

		card->type = MMC_TYPE_MMC;
		card->rca = 1;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
	}

	/*
	 * For native busses:  set card RCA and quit open drain mode.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_set_relative_addr(card);
		if (err)
			goto free_card;

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}

	if (!oldcard) {
		/*
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err)
			goto free_card;
		err = mmc_decode_cid(card);
		if (err)
			goto free_card;
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
			goto free_card;
	}

	if (!oldcard) {
		/*
		 * Fetch and process extended CSD.
		 */
		err = mmc_read_ext_csd(card);
		if (err)
			goto free_card;
	}

	/*
	 * Activate wide bus (if supported).
	 */
    if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
	    (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
        unsigned ext_csd_bit, bus_width;

        if (host->caps & MMC_CAP_8_BIT_DATA) {
            ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
            bus_width = MMC_BUS_WIDTH_8;
            printk(KERN_INFO "%s: mmc_init_card: Switching to 8-bit bus width\n", mmc_hostname(card->host));
        } else {
            ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
            bus_width = MMC_BUS_WIDTH_4;
        }

	    err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
		    EXT_CSD_BUS_WIDTH, ext_csd_bit);
	    if (err)
		    goto free_card;

	    mmc_set_bus_width(card->host, bus_width);
    }

	/*
	 * Activate high speed (if supported)
	 */
	if ((card->ext_csd.hs_max_dtr != 0) &&
#ifdef CONFIG_MMC_BCM_SD
        (host->f_max > SDHCI_HOST_MAX_CLK_LS_MODE) &&
#endif
		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_HS_TIMING, 1);
		if (err)
			goto free_card;

		mmc_card_set_highspeed(card);

		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
	}

	/*
	 * Compute bus speed.
	 */
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->ext_csd.hs_max_dtr)
			max_dtr = card->ext_csd.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}
#if (defined(CONFIG_ARCH_FPGA11107))
   max_dtr >>= 5;                /* Divide clock by 32 for FPGA scale factor */
#endif

	mmc_set_clock(host, max_dtr);

	if (!oldcard)
		host->card = card;

	return 0;

free_card:
	if (!oldcard)
		mmc_remove_card(card);
err:

	return err;
}
Exemplo n.º 21
0
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err;
	u32 cid[4];
#if defined(CONFIG_INAND_VERSION_PATCH)
	u32 rocr[1];
#endif
	unsigned int max_dtr;

	BUG_ON(!host);
	WARN_ON(!host->claimed);

	/*
	 * Since we're changing the OCR value, we seem to
	 * need to tell some cards to go back to the idle
	 * state.  We wait 1ms to give cards time to
	 * respond.
	 */
	mmc_go_idle(host);

	/* The extra bit indicates that we support high capacity */
#if defined(CONFIG_INAND_VERSION_PATCH)		
	err = mmc_send_op_cond(host, ocr | (1 << 30), rocr);
#else
	err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
#endif
	if (err)
		goto err;

	/*
	 * For SPI, enable CRC as appropriate.
	 */
	if (mmc_host_is_spi(host)) {
		err = mmc_spi_set_crc(host, use_spi_crc);
		if (err)
			goto err;
	}

	/*
	 * Fetch CID from card.
	 */
	if (mmc_host_is_spi(host))
		err = mmc_send_cid(host, cid);
	else
		err = mmc_all_send_cid(host, cid);
	if (err)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
			err = -ENOENT;
			goto err;
		}

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host, &mmc_type);
		if (IS_ERR(card)) {
			err = PTR_ERR(card);
			goto err;
		}

		card->type = MMC_TYPE_MMC;
		card->rca = 1;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
		host->card = card;
	}

	/*
	 * For native busses:  set card RCA and quit open drain mode.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_set_relative_addr(card);
		if (err)
			goto free_card;

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}

	if (!oldcard) {
		/*
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err)
			goto free_card;
		err = mmc_decode_cid(card);
		if (err)
			goto free_card;
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
			goto free_card;
	}

	if (!oldcard) {
		/*
		 * Fetch and process extended CSD.
		 */
		err = mmc_read_ext_csd(card);
		if (err)
			goto free_card;
#if defined(CONFIG_INAND_VERSION_PATCH)		
		if (rocr[0] & 0x40000000)
			mmc_card_set_blockaddr(card);
#endif
//[NAGSM_Android_HDLNC_SDcard_SEOJW_2011_01_12 : eMMC Trim add 
#if defined (CONFIG_MMC_DISCARD) && defined (CONFIG_S5PC110_DEMPSEY_BOARD)
		mmc_set_erase_size(card);
#endif /* CONFIG_MMC_DISCARD */
	}

	/*
	 * Activate high speed (if supported)
	 */
	if ((card->ext_csd.hs_max_dtr != 0) &&
		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_HS_TIMING, 1);
		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			printk(KERN_WARNING "%s: switch to highspeed failed\n",
			       mmc_hostname(card->host));
			err = 0;
		} else {
			mmc_card_set_highspeed(card);
			mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
		}
	}

	/*
	 * Compute bus speed.
	 */
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->ext_csd.hs_max_dtr)
			max_dtr = card->ext_csd.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}

	mmc_set_clock(host, max_dtr);

	/*
	 * Activate wide bus (if supported).
	 */
	if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
	    (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
		unsigned ext_csd_bit, bus_width;

		if (host->caps & MMC_CAP_8_BIT_DATA) {
			ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
			bus_width = MMC_BUS_WIDTH_8;
		} else {
			ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
			bus_width = MMC_BUS_WIDTH_4;
		}

		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_BUS_WIDTH, ext_csd_bit);

		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			printk(KERN_WARNING "%s: switch to bus width %d "
			       "failed\n", mmc_hostname(card->host),
			       1 << bus_width);
			err = 0;
		} else {
			mmc_set_bus_width(card->host, bus_width);
			printk(KERN_WARNING "%s: switch to bus width %d "
			       , mmc_hostname(card->host),
			       1 << bus_width);
		}
	}

	return 0;

free_card:
	if (!oldcard) {
		mmc_remove_card(card);
		host->card = NULL;
	}
err:

	return err;
}
Exemplo n.º 22
0
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err, ddr = 0;
	u32 cid[4];
	unsigned int max_dtr;
	u32 rocr;

	BUG_ON(!host);
	WARN_ON(!host->claimed);

	/*
	 * Since we're changing the OCR value, we seem to
	 * need to tell some cards to go back to the idle
	 * state.  We wait 1ms to give cards time to
	 * respond.
	 */
	mmc_go_idle(host);

	/* The extra bit indicates that we support high capacity */
	err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
	if (err)
		goto err;

	/*
	 * For SPI, enable CRC as appropriate.
	 */
	if (mmc_host_is_spi(host)) {
		err = mmc_spi_set_crc(host, use_spi_crc);
		if (err)
			goto err;
	}

	/*
	 * Fetch CID from card.
	 */
	if (mmc_host_is_spi(host))
		err = mmc_send_cid(host, cid);
	else
		err = mmc_all_send_cid(host, cid);
	if (err)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
			err = -ENOENT;
			goto err;
		}

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host, &mmc_type);
		if (IS_ERR(card)) {
			err = PTR_ERR(card);
			goto err;
		}

		card->type = MMC_TYPE_MMC;
		card->rca = 1;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
	}

	/*
	 * For native busses:  set card RCA and quit open drain mode.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_set_relative_addr(card);
		if (err)
			goto free_card;

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}

	if (!oldcard) {
		/*
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err)
			goto free_card;
		err = mmc_decode_cid(card);
		if (err)
			goto free_card;
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
			goto free_card;
	}

	if (!oldcard) {
		/*
		 * Fetch and process extended CSD.
		 */
		err = mmc_read_ext_csd(card);
		if (err)
			goto free_card;

		/* If doing byte addressing, check if required to do sector
		 * addressing.  Handle the case of <2GB cards needing sector
		 * addressing.  See section 8.1 JEDEC Standard JED84-A441;
		 * ocr register has bit 30 set for sector addressing.
		 */
		if (!(mmc_card_blockaddr(card)) && (rocr & (1<<30)))
			mmc_card_set_blockaddr(card);

		/* Erase size depends on CSD and Extended CSD */
		mmc_set_erase_size(card);
	}

#if defined(CONFIG_ARCH_ACER_T20) || defined(CONFIG_ARCH_ACER_T30)
	if (card->cid.manfid == SANDISK_X3_CID_MID) {
		err = mmc_switch(card, 0x0, EXT_CSD_POWER_CLASS, 4);
		if (err)
			printk(KERN_ERR "%s: switch power class fail \n", mmc_hostname(card->host));
	}
#endif

	/*
	 * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
	 * bit.  This bit will be lost every time after a reset or power off.
	 */
	if (card->ext_csd.enhanced_area_en) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				EXT_CSD_ERASE_GROUP_DEF, 1);

		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			err = 0;
			/*
			 * Just disable enhanced area off & sz
			 * will try to enable ERASE_GROUP_DEF
			 * during next time reinit
			 */
			card->ext_csd.enhanced_area_offset = -EINVAL;
			card->ext_csd.enhanced_area_size = -EINVAL;
		} else {
			card->ext_csd.erase_group_def = 1;
			/*
			 * enable ERASE_GRP_DEF successfully.
			 * This will affect the erase size, so
			 * here need to reset erase size
			 */
			mmc_set_erase_size(card);
		}
	}

	/*
	 * Activate high speed (if supported)
	 */
	if ((card->ext_csd.hs_max_dtr != 0) &&
		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_HS_TIMING, 1);
		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			printk(KERN_WARNING "%s: switch to highspeed failed\n",
			       mmc_hostname(card->host));
			err = 0;
		} else {
			mmc_card_set_highspeed(card);
			mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
		}
	}

	/*
	 * Enable HPI feature (if supported)
	 */
	if (card->ext_csd.hpi && (card->host->caps & MMC_CAP_BKOPS)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_HPI_MGMT, 1);
		if (err && err != -EBADMSG)
			goto free_card;
		if (err) {
			pr_warning("%s: Enabling HPI failed\n",
				   mmc_hostname(card->host));
			err = 0;
		} else {
			card->ext_csd.hpi_en = 1;
		}
	}

	/*
	 * Enable Background ops feature (if supported)
	 */
	if (card->ext_csd.bk_ops && (card->host->caps & MMC_CAP_BKOPS)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_BKOPS_EN, 1);
		if (err && err != -EBADMSG)
			goto free_card;
		if (err) {
			pr_warning("%s: Enabling BK ops failed\n",
				   mmc_hostname(card->host));
			err = 0;
		} else {
			card->ext_csd.bk_ops_en = 1;
		}
	}

	/*
	 * Compute bus speed.
	 */
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->ext_csd.hs_max_dtr)
			max_dtr = card->ext_csd.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}

	mmc_set_clock(host, max_dtr);

	/*
	 * Indicate DDR mode (if supported).
	 */
	if (mmc_card_highspeed(card)) {
		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
			&& ((host->caps & (MMC_CAP_1_8V_DDR |
			     MMC_CAP_UHS_DDR50))
				== (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50)))
				ddr = MMC_1_8V_DDR_MODE;
		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
			&& ((host->caps & (MMC_CAP_1_2V_DDR |
			     MMC_CAP_UHS_DDR50))
				== (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50)))
				ddr = MMC_1_2V_DDR_MODE;
	}

	/*
	 * Activate wide bus and DDR (if supported).
	 */
	if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
	    (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
		static unsigned ext_csd_bits[][2] = {
			{ EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
			{ EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 },
			{ EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 },
		};
		static unsigned bus_widths[] = {
			MMC_BUS_WIDTH_8,
			MMC_BUS_WIDTH_4,
			MMC_BUS_WIDTH_1
		};
		unsigned idx, bus_width = 0;

		if (host->caps & MMC_CAP_8_BIT_DATA)
			idx = 0;
		else
			idx = 1;
		for (; idx < ARRAY_SIZE(bus_widths); idx++) {
			bus_width = bus_widths[idx];
			if (bus_width == MMC_BUS_WIDTH_1)
				ddr = 0; /* no DDR for 1-bit width */
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					 EXT_CSD_BUS_WIDTH,
					 ext_csd_bits[idx][0]);
			if (!err) {
				mmc_set_bus_width(card->host, bus_width);
				/*
				 * If controller can't handle bus width test,
				 * use the highest bus width to maintain
				 * compatibility with previous MMC behavior.
				 */
				if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
					break;
				err = mmc_bus_test(card, bus_width);
				if (!err)
					break;
			}
		}

		if (!err && ddr) {
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					EXT_CSD_BUS_WIDTH,
					ext_csd_bits[idx][1]);
		}
		if (err) {
			printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
				"failed\n", mmc_hostname(card->host),
				1 << bus_width, ddr);
			goto free_card;
		} else if (ddr) {
			/*
			 * eMMC cards can support 3.3V to 1.2V i/o (vccq)
			 * signaling.
			 *
			 * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq.
			 *
			 * 1.8V vccq at 3.3V core voltage (vcc) is not required
			 * in the JEDEC spec for DDR.
			 *
			 * Do not force change in vccq since we are obviously
			 * working and no change to vccq is needed.
			 *
			 * WARNING: eMMC rules are NOT the same as SD DDR
			 */
			if (ddr == EXT_CSD_CARD_TYPE_DDR_1_2V) {
				err = mmc_set_signal_voltage(host,
					MMC_SIGNAL_VOLTAGE_120);
				if (err)
					goto err;
			}
			mmc_card_set_ddr_mode(card);
			mmc_set_timing(card->host, MMC_TIMING_UHS_DDR50);
			mmc_set_bus_width(card->host, bus_width);
		}
	}

	if (!oldcard)
		host->card = card;

#if defined(CONFIG_ARCH_ACER_T20) || defined(CONFIG_ARCH_ACER_T30)
	switch (card->type) {
		case MMC_TYPE_MMC:
			sprintf(emmc_type, "MMC");
			break;
		case MMC_TYPE_SD:
			sprintf(emmc_type, "SD");
			break;
		case MMC_TYPE_SDIO:
			sprintf(emmc_type, "SDIO");
			break;
		case MMC_TYPE_SD_COMBO:
			sprintf(emmc_type, "SDcombo");
			break;
		default:
			sprintf(emmc_type, "unknow");
	}

	sprintf(emmc_date, "%02d/%04d", card->cid.month, card->cid.year);
	emmc_size = card->ext_csd.sectors >> 11;
	emmc_name = card->cid.prod_name;

	if (device_info_kobj == NULL) {
		device_info_kobj = kobject_create_and_add("dev-info_rom", NULL);
		if (device_info_kobj == NULL) {
			pr_warning("%s: subsystem_register failed\n",
					mmc_hostname(card->host));
		} else {
			err = sysfs_create_group(device_info_kobj, &attr_group);
			if(err) {
				pr_warning("%s: sysfs_create_group failed\n",
						mmc_hostname(card->host));
			}
		}
	}
#endif

	return 0;

free_card:
	if (!oldcard)
		mmc_remove_card(card);
err:

	return err;
}
Exemplo n.º 23
0
static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err;
	u32 cid[4];
	unsigned int max_dtr;
#ifdef CONFIG_MMC_PARANOID_SD_INIT
	int retries;
#endif
	BUG_ON(!host);
	WARN_ON(!host->claimed);

	
	mmc_go_idle(host);

	
	err = mmc_send_if_cond(host, ocr);
	if (!err)
		ocr |= 1 << 30;

	err = mmc_send_app_op_cond(host, ocr, NULL);
	if (err)
		goto err;

	
	if (mmc_host_is_spi(host))
		err = mmc_send_cid(host, cid);
	else
		err = mmc_all_send_cid(host, cid);
	if (err)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
			err = -ENOENT;
			goto err;
		}

		card = oldcard;
	} else {
		
		card = mmc_alloc_card(host, &sd_type);
		if (IS_ERR(card)) {
			err = PTR_ERR(card);
			goto err;
		}

		card->type = MMC_TYPE_SD;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
	}

	
	if (!mmc_host_is_spi(host)) {
		err = mmc_send_relative_addr(host, &card->rca);
		if (err)
			goto free_card;

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}

	if (!oldcard) {
		
		err = mmc_send_csd(card, card->raw_csd);
		if (err)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err)
			goto free_card;

		mmc_decode_cid(card);
	}

	
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
			goto free_card;
	}

	if (!oldcard) {
		
		err = mmc_app_send_scr(card, card->raw_scr);
		if (err)
			goto free_card;

		err = mmc_decode_scr(card);
		if (err < 0)
			goto free_card;
		
#ifdef CONFIG_MMC_PARANOID_SD_INIT
		for (retries = 1; retries <= 3; retries++) {
			err = mmc_read_switch(card);
			if (!err) {
				if (retries > 1) {
					printk(KERN_WARNING
					       "%s: recovered\n", 
					       mmc_hostname(host));
				}
				break;
			} else {
				printk(KERN_WARNING
				       "%s: read switch failed (attempt %d)\n",
				       mmc_hostname(host), retries);
			}
		}
#else
		err = mmc_read_switch(card);
#endif

		if (err)
			goto free_card;
	}

	
	if (mmc_host_is_spi(host)) {
		err = mmc_spi_set_crc(host, use_spi_crc);
		if (err)
			goto free_card;
	}

	
	err = mmc_switch_hs(card);
	if (err)
		goto free_card;

	
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->sw_caps.hs_max_dtr)
			max_dtr = card->sw_caps.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}

	mmc_set_clock(host, max_dtr);

	
	if ((host->caps & MMC_CAP_4_BIT_DATA) &&
		(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
		err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
		if (err)
			goto free_card;

		mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
	}

	
	if (!oldcard) {
		if (!host->ops->get_ro || host->ops->get_ro(host) < 0) {
			printk(KERN_WARNING "%s: host does not "
				"support reading read-only "
				"switch. assuming write-enable.\n",
				mmc_hostname(host));
		} else {
			if (host->ops->get_ro(host) > 0)
				mmc_card_set_readonly(card);
		}
	}

	if (!oldcard)
		host->card = card;

	return 0;

free_card:
	if (!oldcard)
		mmc_remove_card(card);
err:

	return err;
}
Exemplo n.º 24
0
/* 2. Validation Process */
int skymedi_validation_process(struct mmc *mmc)
{
	struct mmc_cmd cmd;
	int ret;
	unsigned int hwversion;
	unsigned int fwversion;
	unsigned int flashid;

	ret = skymedi_set_func(mmc, 0x00000055);	//entry debug mode
	if (ret)
		return ret;
	ret = skymedi_read_one_block(mmc, sector_buff, 0x00000068);	//read hw_version
	if (ret != 1)
		return -1;

	hwversion = skymedi_get_hwversion(sector_buff);
	if (hwversion != HW_VERSION_SK6617) {
		printf("error hw_version : %4x\n", hwversion);
		return -1;
	}

	ret = skymedi_read_one_block(mmc, sector_buff, 0x00000067);	//read hw_version
	if (ret != 1)
		return -1;
	fwversion = skymedi_get_fwversion(sector_buff);
	if (fwversion != FW_VERSION_SK6617) {
		printf("error hw_version : %4x\n", hwversion);
		return -1;
	}

	ret = skymedi_read_one_block(mmc, sector_buff, 0x00000065);	//read flash id
	if (ret != 1)
		return -1;

	flashid = skymedi_get_flashid(sector_buff);
	printf("flash_id = %x\n", flashid);
	/* Please verify the flash id. The function is not implemented */

	ret = skymedi_set_func(mmc, 0x000000aa);	//exit debug mode
	if (ret)
		return ret;
	cmd.cmdidx = MMC_CMD_APP_CMD;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = 0x00020000;
	ret = mmc_send_cmd(mmc, &cmd, NULL);
	if (ret)
		return ret;
	ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4);	//set bus width 4
	if (ret)
		return ret;
	mmc_set_bus_width(mmc, 4);

	ret = skymedi_set_func(mmc, 0x00000055);
	if (ret)
		return ret;
	ret = skymedi_read_one_block(mmc, sector_buff, 0x00000065);	//read flash id
	if (ret != 1)
		return -1;

	flashid = skymedi_get_flashid(sector_buff);
	printf("flash_id = %x\n", flashid);
	/* Please verify the flash id. The function is not implemented */

	return 0;
}