Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 013909c4 authored by Arindam Nath's avatar Arindam Nath Committed by Chris Ball
Browse files

mmc: sd: query function modes for uhs cards



SD cards which conform to Physical Layer Spec v3.01 can support
additional Bus Speed Modes, Driver Strength, and Current Limit
other than the default values. We use CMD6 mode 0 to read these
additional card functions. The values read here will be used
during UHS-I initialization steps.

Tested by Zhangfei Gao with a Toshiba uhs card and general hs card,
on mmp2 in SDMA mode.

Signed-off-by: default avatarArindam Nath <arindam.nath@amd.com>
Reviewed-by: default avatarPhilip Rakity <prakity@marvell.com>
Tested-by: default avatarPhilip Rakity <prakity@marvell.com>
Acked-by: default avatarZhangfei Gao <zhangfei.gao@marvell.com>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent f2119df6
Loading
Loading
Loading
Loading
+58 −10
Original line number Original line Diff line number Diff line
@@ -189,6 +189,9 @@ static int mmc_decode_scr(struct mmc_card *card)


	scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
	scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
	scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
	scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
	if (scr->sda_vsn == SCR_SPEC_VER_2)
		/* Check if Physical Layer Spec v3.0 is supported */
		scr->sda_spec3 = UNSTUFF_BITS(resp, 47, 1);


	if (UNSTUFF_BITS(resp, 55, 1))
	if (UNSTUFF_BITS(resp, 55, 1))
		card->erased_byte = 0xFF;
		card->erased_byte = 0xFF;
@@ -274,29 +277,74 @@ static int mmc_read_switch(struct mmc_card *card)
	status = kmalloc(64, GFP_KERNEL);
	status = kmalloc(64, GFP_KERNEL);
	if (!status) {
	if (!status) {
		printk(KERN_ERR "%s: could not allocate a buffer for "
		printk(KERN_ERR "%s: could not allocate a buffer for "
			"switch capabilities.\n", mmc_hostname(card->host));
			"switch capabilities.\n",
			mmc_hostname(card->host));
		return -ENOMEM;
		return -ENOMEM;
	}
	}


	/* Find out the supported Bus Speed Modes. */
	err = mmc_sd_switch(card, 0, 0, 1, status);
	err = mmc_sd_switch(card, 0, 0, 1, status);
	if (err) {
	if (err) {
		/* If the host or the card can't do the switch,
		/*
		 * fail more gracefully. */
		 * If the host or the card can't do the switch,
		if ((err != -EINVAL)
		 * fail more gracefully.
		 && (err != -ENOSYS)
		 */
		 && (err != -EFAULT))
		if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
			goto out;

		printk(KERN_WARNING "%s: problem reading Bus Speed modes.\n",
			mmc_hostname(card->host));
		err = 0;

		goto out;
	}

	if (card->scr.sda_spec3) {
		card->sw_caps.sd3_bus_mode = status[13];

		/* Find out Driver Strengths supported by the card */
		err = mmc_sd_switch(card, 0, 2, 1, status);
		if (err) {
			/*
			 * If the host or the card can't do the switch,
			 * fail more gracefully.
			 */
			if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
				goto out;

			printk(KERN_WARNING "%s: problem reading "
				"Driver Strength.\n",
				mmc_hostname(card->host));
			err = 0;

			goto out;
		}

		card->sw_caps.sd3_drv_type = status[9];

		/* Find out Current Limits supported by the card */
		err = mmc_sd_switch(card, 0, 3, 1, status);
		if (err) {
			/*
			 * If the host or the card can't do the switch,
			 * fail more gracefully.
			 */
			if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
				goto out;
				goto out;


		printk(KERN_WARNING "%s: problem reading switch "
			printk(KERN_WARNING "%s: problem reading "
			"capabilities, performance might suffer.\n",
				"Current Limit.\n",
				mmc_hostname(card->host));
				mmc_hostname(card->host));
			err = 0;
			err = 0;


			goto out;
			goto out;
		}
		}


		card->sw_caps.sd3_curr_limit = status[7];
	} else {
		if (status[13] & 0x02)
		if (status[13] & 0x02)
			card->sw_caps.hs_max_dtr = 50000000;
			card->sw_caps.hs_max_dtr = 50000000;
	}


out:
out:
	kfree(status);
	kfree(status);
+4 −0
Original line number Original line Diff line number Diff line
@@ -67,6 +67,7 @@ struct mmc_ext_csd {


struct sd_scr {
struct sd_scr {
	unsigned char		sda_vsn;
	unsigned char		sda_vsn;
	unsigned char		sda_spec3;
	unsigned char		bus_widths;
	unsigned char		bus_widths;
#define SD_SCR_BUS_WIDTH_1	(1<<0)
#define SD_SCR_BUS_WIDTH_1	(1<<0)
#define SD_SCR_BUS_WIDTH_4	(1<<2)
#define SD_SCR_BUS_WIDTH_4	(1<<2)
@@ -80,6 +81,9 @@ struct sd_ssr {


struct sd_switch_caps {
struct sd_switch_caps {
	unsigned int		hs_max_dtr;
	unsigned int		hs_max_dtr;
	unsigned int		sd3_bus_mode;
	unsigned int		sd3_drv_type;
	unsigned int		sd3_curr_limit;
};
};


struct sdio_cccr {
struct sdio_cccr {