RE: [PATCH V2] mmc: sd.c Set Non Default Drive Strength via platform

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Philip,


> -----Original Message-----
> From: Philip Rakity [mailto:prakity@xxxxxxxxxxx]
> Sent: Wednesday, July 06, 2011 9:22 PM
> To: linux-mmc@xxxxxxxxxxxxxxx
> Cc: Nath, Arindam
> Subject: [PATCH V2] mmc: sd.c Set Non Default Drive Strength via
> platform
> 
> 
> V2
> --
> Include host.h change for callback to select_drive_strength
> 
> V1
> --
> Non default Drive Strength cannot be set automatically.
> It is a function of the board design and only if there
> is a specific platform handler can it be set.  The platform
> handler needs to take into account the board design.  Pass
> to the platform code the necessary information.
> 
> For example:  The card and host controller may indicate
> they support HIGH and LOW drive strength.  There is no way
> to know what should be chosen without specific board knowledge.
> Setting HIGH may lead to reflections and setting LOW may not
> be sufficient.
> There is no mechanism (like ethernet duplex or speed pulses)
> to determine what should be done automatically.
> 
> If no platform handler is defined -- use the default value.
> 
> Signed-off-by: Philip Rakity <prakity@xxxxxxxxxxx>
> ---
>  drivers/mmc/core/sd.c    |   68 ++++++++++++++++++++++++++------------
> -------
>  include/linux/mmc/host.h |    1 +
>  2 files changed, 40 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
> index ff27741..633975f 100644
> --- a/drivers/mmc/core/sd.c
> +++ b/drivers/mmc/core/sd.c
> @@ -409,52 +409,62 @@ out:
> 
>  static int sd_select_driver_type(struct mmc_card *card, u8 *status)
>  {
> -	int host_drv_type = 0, card_drv_type = 0;
> +	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,
> -	 * default Driver Type B is used.
> +	 * 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->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;
> -	}
> +	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, card_drv_type, status);
> +	err = mmc_sd_switch(card, 1, 2, drive_strength, status);
>  	if (err)
>  		return err;
> 
> -	if ((status[15] & 0xF) != card_drv_type) {
> -		printk(KERN_WARNING "%s: Problem setting driver
> strength!\n",
> +	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, host_drv_type);
> +	mmc_set_driver_type(card->host, drive_strength);
> 
>  	return 0;
>  }
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index ac3fbac..4913f6c 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -139,6 +139,7 @@ struct mmc_host_ops {
>  	int	(*start_signal_voltage_switch)(struct mmc_host *host,
> struct mmc_ios *ios);
>  	int	(*execute_tuning)(struct mmc_host *host);
>  	void	(*enable_preset_value)(struct mmc_host *host, bool enable);
> +	int	(*select_drive_strength)(unsigned int max_dtr, int
> host_drv, int card_drv);
>  };
> 
>  struct mmc_card;
> --
> 1.7.0.4
> 
> 

Looks good to me.

Reviewed-by: Arindam Nath <arindam.nath@xxxxxxx>

Thanks,
Arindam

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux