static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)
{
	unsigned int bus_speed = 0, timing = 0;
	int err;

	/*
	 * If the host doesn't support any of the UHS-I modes, fallback on
	 * default speed.
	 */
	if (!(card->host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
	    MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50)))
		return 0;

	if ((card->host->caps & MMC_CAP_UHS_SDR104) &&
	    (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) {
			bus_speed = UHS_SDR104_BUS_SPEED;
			timing = MMC_TIMING_UHS_SDR104;
			card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR;
	} else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&
		   (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) {
			bus_speed = UHS_DDR50_BUS_SPEED;
			timing = MMC_TIMING_UHS_DDR50;
			card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR;
	} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
		    MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode &
		    SD_MODE_UHS_SDR50)) {
			bus_speed = UHS_SDR50_BUS_SPEED;
			timing = MMC_TIMING_UHS_SDR50;
			card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR;
	} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
		    MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) &&
		   (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) {
			bus_speed = UHS_SDR25_BUS_SPEED;
			timing = MMC_TIMING_UHS_SDR25;
			card->sw_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR;
	} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
		    MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
		    MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode &
		    SD_MODE_UHS_SDR12)) {
			bus_speed = UHS_SDR12_BUS_SPEED;
			timing = MMC_TIMING_UHS_SDR12;
			card->sw_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR;
	}

	card->sd_bus_speed = bus_speed;
	err = mmc_sd_switch(card, 1, 0, bus_speed, status);
	if (err)
		return err;

	if ((status[16] & 0xF) != bus_speed) {
		printk(KERN_WARNING "%s: Problem setting bus speed mode!\n",
			mmc_hostname(card->host));
	}
	else {
		mmc_set_timing(card->host, timing);
		mmc_set_clock(card->host, card->sw_caps.uhs_max_dtr);
	}

	return 0;
}
Example #2
0
/*
 * Test if the card supports high-speed mode and, if so, switch to it.
 */
static int mmc_switch_hs(struct mmc_request *request)
{
	unsigned int status[64 / 4];

	mmc_sd_switch(request, 1, 0, 1, (unsigned char *) status);
	return 0;
}
Example #3
0
static int
mmc_set_timing(struct mmc_softc *sc, int timing)
{
	int err;
	uint8_t	value;
	u_char switch_res[64];

	switch (timing) {
	case bus_timing_normal:
		value = 0;
		break;
	case bus_timing_hs:
		value = 1;
		break;
	default:
		return (MMC_ERR_INVALID);
	}
	if (mmcbr_get_mode(sc->dev) == mode_sd)
		err = mmc_sd_switch(sc, SD_SWITCH_MODE_SET, SD_SWITCH_GROUP1,
		    value, switch_res);
	else
		err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL,
		    EXT_CSD_HS_TIMING, value);
	return (err);
}
Example #4
0
/*
 * Fetches and decodes switch information
 */
static int mmc_read_switch(struct mmc_card *card)
{
	int err;
	u8 *status;

#if defined(CONFIG_AMBARELLA_IPC) && defined(CONFIG_MMC_AMBARELLA) && !defined(CONFIG_NOT_SHARE_SD_CONTROLLER_WITH_UITRON)
	struct ipc_sdinfo *sdinfo = ambarella_sd_get_sdinfo(card->host);
	if (sdinfo->from_ipc && sdinfo->is_init) {
		card->sw_caps.hs_max_dtr = 50000000;
		return 0;
	}
#endif
	if (card->scr.sda_vsn < SCR_SPEC_VER_1)
		return 0;

	if (!(card->csd.cmdclass & CCC_SWITCH)) {
		printk(KERN_WARNING "%s: card lacks mandatory switch "
			"function, performance might suffer.\n",
			mmc_hostname(card->host));
		return 0;
	}

	err = -EIO;

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

	err = mmc_sd_switch(card, 0, 0, 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 switch "
			"capabilities, performance might suffer.\n",
			mmc_hostname(card->host));
		err = 0;

		goto out;
	}

	if (status[13] & 0x02)
		card->sw_caps.hs_max_dtr = 50000000;

out:
	kfree(status);

	return err;
}
Example #5
0
/*
 * Test if the card supports high-speed mode and, if so, switch to it.
 */
static int mmc_switch_hs(struct mmc_card *card)
{
	int err;
	u8 *status;
	DBG("[%s] s\n",__func__);

	if (card->scr.sda_vsn < SCR_SPEC_VER_1) {
		DBG("[%s] e1\n",__func__);
		return 0;
	}

	if (!(card->csd.cmdclass & CCC_SWITCH)) {
		DBG("[%s] e2\n",__func__);
		return 0;
	}

	if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) {
		DBG("[%s] e3\n",__func__);
		return 0;
	}

	if (card->sw_caps.hs_max_dtr == 0) {
		DBG("[%s] e4\n",__func__);
		return 0;
	}

	err = -EIO;

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

	err = mmc_sd_switch(card, 1, 0, 1, status);
	if (err)
		goto out;

	if ((status[16] & 0xF) != 1) {
		printk(KERN_WARNING "%s: Problem switching card "
			"into high-speed mode!\n",
			mmc_hostname(card->host));
	} else {
		mmc_card_set_highspeed(card);
		mmc_set_timing(card->host, MMC_TIMING_SD_HS);
	}

out:
	kfree(status);

	DBG("[%s] e6\n",__func__);
	return err;
}
Example #6
0
/*
 * Fetches and decodes switch information
 */
static int mmc_read_switch(struct mmc_card *card)
{
	int err;
	u8 *status;
	DBG("[%s] s\n",__func__);
	
	if (card->scr.sda_vsn < SCR_SPEC_VER_1) {
		DBG("[%s] e\n",__func__);
		return 0;
	}

	if (!(card->csd.cmdclass & CCC_SWITCH)) {
		printk(KERN_WARNING "%s: card lacks mandatory switch "
			"function, performance might suffer.\n",
			mmc_hostname(card->host));
		DBG("[%s] e1\n",__func__);
		return 0;
	}

	err = -EIO;

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

	err = mmc_sd_switch(card, 0, 0, 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 switch "
			"capabilities, performance might suffer.\n",
			mmc_hostname(card->host));
		err = 0;

		goto out;
	}

	if (status[13] & 0x02)
		card->sw_caps.hs_max_dtr = 50000000;

out:
	kfree(status);

	DBG("[%s] e3\n",__func__);
	return err;
}
Example #7
0
/*
 * Fetches and decodes switch information
 */
static int  mmc_read_switch(struct mmc_request *request)
{
	unsigned int status[64 / 4];

	memset ((unsigned char *)status,0,64);
	mmc_sd_switch(request, 0, 0, 1, (unsigned char *) status);
	
        if (((unsigned char *)status)[13] & 0x02)
		return 0;
	else 
		 return 1;
}
static int sd_select_driver_type(struct mmc_card *card, u8 *status)
{
	int host_drv_type = 0, card_drv_type = 0;
	int err;

	/*
	 * If the host doesn't support any of the Driver Types A,C or D,
	 * default Driver Type B is used.
	 */
	if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C
	    | MMC_CAP_DRIVER_TYPE_D)))
		return 0;

	if (card->host->caps & MMC_CAP_DRIVER_TYPE_A) {
		host_drv_type = MMC_SET_DRIVER_TYPE_A;
		if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A)
			card_drv_type = MMC_SET_DRIVER_TYPE_A;
		else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_B)
			card_drv_type = MMC_SET_DRIVER_TYPE_B;
		else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
			card_drv_type = MMC_SET_DRIVER_TYPE_C;
	} else if (card->host->caps & MMC_CAP_DRIVER_TYPE_C) {
		host_drv_type = MMC_SET_DRIVER_TYPE_C;
		if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
			card_drv_type = MMC_SET_DRIVER_TYPE_C;
	} else if (!(card->host->caps & MMC_CAP_DRIVER_TYPE_D)) {
		/*
		 * If we are here, that means only the default driver type
		 * B is supported by the host.
		 */
		host_drv_type = MMC_SET_DRIVER_TYPE_B;
		if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_B)
			card_drv_type = MMC_SET_DRIVER_TYPE_B;
		else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
			card_drv_type = MMC_SET_DRIVER_TYPE_C;
	}

	err = mmc_sd_switch(card, 1, 2, card_drv_type, status);
	if (err)
		return err;

	if ((status[15] & 0xF) != card_drv_type) {
		printk(KERN_WARNING "%s: Problem setting driver strength!\n",
			mmc_hostname(card->host));
		return 0;
	}

	mmc_set_driver_type(card->host, host_drv_type);

	return 0;
}
Example #9
0
/*
 * Test if the card supports high-speed mode and, if so, switch to it.
 */
int mmc_sd_switch_hs(struct mmc_card *card)
{
	int err;
	u8 *status;

#if defined(CONFIG_AMBARELLA_IPC) && defined(CONFIG_MMC_AMBARELLA) && !defined(CONFIG_NOT_SHARE_SD_CONTROLLER_WITH_UITRON)
	struct ipc_sdinfo *sdinfo = ambarella_sd_get_sdinfo(card->host);
	if (sdinfo->from_ipc)
		return 0;
#endif

	if (card->scr.sda_vsn < SCR_SPEC_VER_1)
		return 0;

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

	if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
		return 0;

	if (card->sw_caps.hs_max_dtr == 0)
		return 0;

	err = -EIO;

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

	err = mmc_sd_switch(card, 1, 0, 1, status);
	if (err)
		goto out;

	if ((status[16] & 0xF) != 1) {
		printk(KERN_WARNING "%s: Problem switching card "
			"into high-speed mode!\n",
			mmc_hostname(card->host));
		err = 0;
	} else {
		err = 1;
	}

out:
	kfree(status);

	return err;
}
Example #10
0
/*
 * Fetches and decodes switch information
 */
static int mmc_read_switch(struct mmc_card *card)
{
	int err;
	u8 *status;

	if (card->scr.sda_vsn < SCR_SPEC_VER_1)
		return 0;

	if (!(card->csd.cmdclass & CCC_SWITCH)) {
		printk(KERN_WARNING "%s: card lacks mandatory switch "
			"function, performance might suffer.\n",
			mmc_hostname(card->host));
		return 0;
	}

	err = -EIO;

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

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

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

		goto out;
	}

	if (status[13] & 0x02)
		card->sw_caps.hs_max_dtr = 50000000;

out:
	kfree(status);

	return err;
}
Example #11
0
/*
 * Test if the card supports high-speed mode and, if so, switch to it.
 */
static int mmc_switch_hs(struct mmc_card *card)
{
	int err;
	u8 *status;

	if (card->scr.sda_vsn < SCR_SPEC_VER_1)
		return 0;

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

	if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
		return 0;

	if (card->sw_caps.hs_max_dtr == 0)
		return 0;

	/* LIBtt04854 : All of 2GB sd card set to 24Mhz */
	if (card->csd.read_blkbits == 10)
		return 0;

	err = -EIO;

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

	err = mmc_sd_switch(card, 1, 0, 1, status);
	if (err)
		goto out;

	if ((status[16] & 0xF) != 1) {
		printk(KERN_WARNING "%s: Problem switching card "
			"into high-speed mode!\n",
			mmc_hostname(card->host));
	} else {
		mmc_card_set_highspeed(card);
		mmc_set_timing(card->host, MMC_TIMING_SD_HS);
	}

out:
	kfree(status);

	return err;
}
Example #12
0
/*
 * Test if the card supports high-speed mode and, if so, switch to it.
 */
int mmc_sd_switch_hs(struct mmc_card *card)
{
	int err;
	u8 *status;

	if (card->scr.sda_vsn < SCR_SPEC_VER_1)
		return 0;

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

	if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
		return 0;

	if (card->sw_caps.hs_max_dtr == 0)
		return 0;

	err = -EIO;

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

	err = mmc_sd_switch(card, 1, 0, 1, status);
	if (err)
		goto out;

	if ((status[16] & 0xF) != 1) {
		printk(KERN_WARNING "%s: Problem switching card "
			"into high-speed mode!\n",
			mmc_hostname(card->host));
		err = 0;
	} else {
		err = 1;
	}

out:
	kfree(status);

	return err;
}
Example #13
0
static int check_assd(struct mmc_host *host, int mode, int func)
{
	int ret = 0;
	struct mmc_card *card;

	BUG_ON(!host);

	pr_debug("assd: check_assd()\n");

	mmc_claim_host(host);
	card = host->card;
	if (card == NULL) {

		ret = -ENODEV;
		goto out;
	}

	/*
	 * SD memory cards compatible with versions earlier than 1.10 do not
	 * support the Switch function command.
	 */
	if (!card->scr.sda_vsn) {

		ret = -ENODEV;
		goto out;
	}

	/*
	 * See [1] chapter "Switch Function Command" for information
	 * about modes, groups, and functions.
	 */
	mmc_sd_switch(card, mode, GROUP_2, func, assd_block);

	/*
	 * We verify the response only if we switched to a non-default
	 * function.
	 */
	if (func) {

		/*
		 * See [1] chapter "Switch Function Status" for information
		 * about the status bits. The function was successfully
		 * switched if bits 383:380 hold the function number,
		 * and in bits 431:416 the function group information show
		 * that our function is supported.
		 */
		if (!(assd_block[11] & (1 << func))) {

			ret = -ENODEV;
			goto out;
		}

		if ((assd_block[16] & 0xf0) != (func << 4)) {

			ret = -ENODEV;
			if (assd_block[27] & (1 << func))
				ret = -EBUSY;
		}
	}
out:
	mmc_release_host(host);
	return ret;
}
/*
 * Fetches and decodes switch information
 */
static int mmc_read_switch(struct mmc_card *card)
{
	int err;
	u8 *status;

	if (card->scr.sda_vsn < SCR_SPEC_VER_1)
		return 0;

	if (!(card->csd.cmdclass & CCC_SWITCH)) {
		printk(KERN_WARNING "%s: card lacks mandatory switch "
			"function, performance might suffer.\n",
			mmc_hostname(card->host));
		return 0;
	}

	err = -EIO;

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

	/* Find out the supported Bus Speed Modes. */
	err = mmc_sd_switch(card, 0, 0, 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 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;

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

			goto out;
		}

		card->sw_caps.sd3_curr_limit = status[7];
	}

	if (status[13] & 0x02)
		card->sw_caps.hs_max_dtr = 50000000;

out:
	kfree(status);

	return err;
}
Example #15
0
static int sd_select_driver_type(struct mmc_card *card, u8 *status)
{
	int host_drv_type = SD_DRIVER_TYPE_B;
	int card_drv_type = SD_DRIVER_TYPE_B;
	int drive_strength;
	int err;

	/*
	 * If the host doesn't support any of the Driver Types A,C or D,
	 * or there is no board specific handler then default Driver
	 * Type B is used.
	 */
	if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C
	    | MMC_CAP_DRIVER_TYPE_D)))
		return 0;

	if (!card->host->ops->select_drive_strength)
		return 0;

	if (card->host->caps & MMC_CAP_DRIVER_TYPE_A)
		host_drv_type |= SD_DRIVER_TYPE_A;

	if (card->host->caps & MMC_CAP_DRIVER_TYPE_C)
		host_drv_type |= SD_DRIVER_TYPE_C;

	if (card->host->caps & MMC_CAP_DRIVER_TYPE_D)
		host_drv_type |= SD_DRIVER_TYPE_D;

	if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A)
		card_drv_type |= SD_DRIVER_TYPE_A;

	if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
		card_drv_type |= SD_DRIVER_TYPE_C;

	if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_D)
		card_drv_type |= SD_DRIVER_TYPE_D;

	/*
	 * The drive strength that the hardware can support
	 * depends on the board design.  Pass the appropriate
	 * information and let the hardware specific code
	 * return what is possible given the options
	 */
	drive_strength = card->host->ops->select_drive_strength(
		card->sw_caps.uhs_max_dtr,
		host_drv_type, card_drv_type);

	err = mmc_sd_switch(card, 1, 2, drive_strength, status);
	if (err)
		return err;

	if ((status[15] & 0xF) != drive_strength) {
		printk(KERN_WARNING "%s: Problem setting drive strength!\n",
			mmc_hostname(card->host));
		return 0;
	}

	mmc_set_driver_type(card->host, drive_strength);

	return 0;
}
Example #16
0
static void
mmc_discover_cards(struct mmc_softc *sc)
{
	struct mmc_ivars *ivar = NULL;
	device_t *devlist;
	int err, i, devcount, newcard;
	uint32_t raw_cid[4];
	uint32_t resp, sec_count;
	device_t child;
	uint16_t rca = 2;
	u_char switch_res[64];

	if (bootverbose || mmc_debug)
		device_printf(sc->dev, "Probing cards\n");
	while (1) {
		err = mmc_all_send_cid(sc, raw_cid);
		if (err == MMC_ERR_TIMEOUT)
			break;
		if (err != MMC_ERR_NONE) {
			device_printf(sc->dev, "Error reading CID %d\n", err);
			break;
		}
		newcard = 1;
		if ((err = device_get_children(sc->dev, &devlist, &devcount)) != 0)
			return;
		for (i = 0; i < devcount; i++) {
			ivar = device_get_ivars(devlist[i]);
			if (memcmp(ivar->raw_cid, raw_cid, sizeof(raw_cid)) == 0) {
				newcard = 0;
				break;
			}
		}
		free(devlist, M_TEMP);
		if (bootverbose || mmc_debug) {
			device_printf(sc->dev, "%sard detected (CID %08x%08x%08x%08x)\n",
			    newcard ? "New c" : "C",
			    raw_cid[0], raw_cid[1], raw_cid[2], raw_cid[3]);
		}
		if (newcard) {
			ivar = malloc(sizeof(struct mmc_ivars), M_DEVBUF,
			    M_WAITOK | M_ZERO);
			if (!ivar)
				return;
			memcpy(ivar->raw_cid, raw_cid, sizeof(raw_cid));
		}
		if (mmcbr_get_ro(sc->dev))
			ivar->read_only = 1;
		ivar->bus_width = bus_width_1;
		ivar->timing = bus_timing_normal;
		ivar->mode = mmcbr_get_mode(sc->dev);
		if (ivar->mode == mode_sd) {
			mmc_decode_cid_sd(ivar->raw_cid, &ivar->cid);
			mmc_send_relative_addr(sc, &resp);
			ivar->rca = resp >> 16;
			/* Get card CSD. */
			mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
			mmc_decode_csd_sd(ivar->raw_csd, &ivar->csd);
			ivar->sec_count = ivar->csd.capacity / MMC_SECTOR_SIZE;
			if (ivar->csd.csd_structure > 0)
				ivar->high_cap = 1;
			ivar->tran_speed = ivar->csd.tran_speed;
			ivar->erase_sector = ivar->csd.erase_sector * 
			    ivar->csd.write_bl_len / MMC_SECTOR_SIZE;
			/* Get card SCR. Card must be selected to fetch it. */
			mmc_select_card(sc, ivar->rca);
			mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr);
			mmc_app_decode_scr(ivar->raw_scr, &ivar->scr);
			/* Get card switch capabilities (command class 10). */
			if ((ivar->scr.sda_vsn >= 1) &&
			    (ivar->csd.ccc & (1<<10))) {
				mmc_sd_switch(sc, SD_SWITCH_MODE_CHECK,
				    SD_SWITCH_GROUP1, SD_SWITCH_NOCHANGE,
				    switch_res);
				if (switch_res[13] & 2) {
					ivar->timing = bus_timing_hs;
					ivar->hs_tran_speed = SD_MAX_HS;
				}
			}
			mmc_app_sd_status(sc, ivar->rca, ivar->raw_sd_status);
			mmc_app_decode_sd_status(ivar->raw_sd_status,
			    &ivar->sd_status);
			if (ivar->sd_status.au_size != 0) {
				ivar->erase_sector =
				    16 << ivar->sd_status.au_size;
			}
			mmc_select_card(sc, 0);
			/* Find max supported bus width. */
			if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) &&
			    (ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4))
				ivar->bus_width = bus_width_4;
			if (bootverbose || mmc_debug)
				mmc_log_card(sc->dev, ivar, newcard);
			if (newcard) {
				/* Add device. */
				child = device_add_child(sc->dev, NULL, -1);
				device_set_ivars(child, ivar);
			}
			return;
		}
		mmc_decode_cid_mmc(ivar->raw_cid, &ivar->cid);
		ivar->rca = rca++;
		mmc_set_relative_addr(sc, ivar->rca);
		/* Get card CSD. */
		mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
		mmc_decode_csd_mmc(ivar->raw_csd, &ivar->csd);
		ivar->sec_count = ivar->csd.capacity / MMC_SECTOR_SIZE;
		ivar->tran_speed = ivar->csd.tran_speed;
		ivar->erase_sector = ivar->csd.erase_sector * 
		    ivar->csd.write_bl_len / MMC_SECTOR_SIZE;
		/* Only MMC >= 4.x cards support EXT_CSD. */
		if (ivar->csd.spec_vers >= 4) {
			/* Card must be selected to fetch EXT_CSD. */
			mmc_select_card(sc, ivar->rca);
			mmc_send_ext_csd(sc, ivar->raw_ext_csd);
			/* Handle extended capacity from EXT_CSD */
			sec_count = ivar->raw_ext_csd[EXT_CSD_SEC_CNT] +
			    (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 1] << 8) +
			    (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 2] << 16) +
			    (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
			if (sec_count != 0) {
				ivar->sec_count = sec_count;
				ivar->high_cap = 1;
			}
			/* Get card speed in high speed mode. */
			ivar->timing = bus_timing_hs;
			if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE]
			    & EXT_CSD_CARD_TYPE_52)
				ivar->hs_tran_speed = MMC_TYPE_52_MAX_HS;
			else if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE]
			    & EXT_CSD_CARD_TYPE_26)
				ivar->hs_tran_speed = MMC_TYPE_26_MAX_HS;
			else
				ivar->hs_tran_speed = ivar->tran_speed;
			/* Find max supported bus width. */
			ivar->bus_width = mmc_test_bus_width(sc);
			mmc_select_card(sc, 0);
			/* Handle HC erase sector size. */
			if (ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE] != 0) {
				ivar->erase_sector = 1024 *
				    ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE];
				mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL,
				    EXT_CSD_ERASE_GRP_DEF, 1);
			}
		} else {
			ivar->bus_width = bus_width_1;
			ivar->timing = bus_timing_normal;
		}
		if (bootverbose || mmc_debug)
			mmc_log_card(sc->dev, ivar, newcard);
		if (newcard) {
			/* Add device. */
			child = device_add_child(sc->dev, NULL, -1);
			device_set_ivars(child, ivar);
		}
	}