Esempio n. 1
0
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;
}
Esempio n. 2
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;
}