* [PATCH] mmc: sd.c Set Non Default Drive Strength via platform
@ 2011-07-06 0:01 Philip Rakity
2011-07-06 15:51 ` [PATCH V2] " Philip Rakity
0 siblings, 1 reply; 4+ messages in thread
From: Philip Rakity @ 2011-07-06 0:01 UTC (permalink / raw)
To: linux-mmc@vger.kernel.org; +Cc: Arindam Nath
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 to 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.
There is not mechanism (like ethernet duplex or speed pulses)
to determine what should be done.
If no platform handler is defined -- use the default value.
Signed-off-by: Philip Rakity <prakity@marvell.com>
---
drivers/mmc/core/sd.c | 68 ++++++++++++++++++++++++++++---------------------
1 files changed, 39 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;
}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH V2] mmc: sd.c Set Non Default Drive Strength via platform
2011-07-06 0:01 [PATCH] mmc: sd.c Set Non Default Drive Strength via platform Philip Rakity
@ 2011-07-06 15:51 ` Philip Rakity
2011-07-06 17:32 ` Nath, Arindam
2011-07-09 22:02 ` Chris Ball
0 siblings, 2 replies; 4+ messages in thread
From: Philip Rakity @ 2011-07-06 15:51 UTC (permalink / raw)
To: linux-mmc@vger.kernel.org; +Cc: Arindam Nath
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@marvell.com>
---
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
^ permalink raw reply related [flat|nested] 4+ messages in thread
* RE: [PATCH V2] mmc: sd.c Set Non Default Drive Strength via platform
2011-07-06 15:51 ` [PATCH V2] " Philip Rakity
@ 2011-07-06 17:32 ` Nath, Arindam
2011-07-09 22:02 ` Chris Ball
1 sibling, 0 replies; 4+ messages in thread
From: Nath, Arindam @ 2011-07-06 17:32 UTC (permalink / raw)
To: Philip Rakity, linux-mmc@vger.kernel.org
Hi Philip,
> -----Original Message-----
> From: Philip Rakity [mailto:prakity@marvell.com]
> Sent: Wednesday, July 06, 2011 9:22 PM
> To: linux-mmc@vger.kernel.org
> 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@marvell.com>
> ---
> 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@amd.com>
Thanks,
Arindam
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH V2] mmc: sd.c Set Non Default Drive Strength via platform
2011-07-06 15:51 ` [PATCH V2] " Philip Rakity
2011-07-06 17:32 ` Nath, Arindam
@ 2011-07-09 22:02 ` Chris Ball
1 sibling, 0 replies; 4+ messages in thread
From: Chris Ball @ 2011-07-09 22:02 UTC (permalink / raw)
To: Philip Rakity; +Cc: linux-mmc@vger.kernel.org, Arindam Nath
Hi Philip,
On Wed, Jul 06 2011, Philip Rakity wrote:
> V2
> --
> Include host.h change for callback to select_drive_strength
Thanks, pushed to mmc-next for 3.1 with Arindam's Reviewed-by.
- Chris.
--
Chris Ball <cjb@laptop.org> <http://printf.net/>
One Laptop Per Child
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2011-07-09 22:02 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-07-06 0:01 [PATCH] mmc: sd.c Set Non Default Drive Strength via platform Philip Rakity
2011-07-06 15:51 ` [PATCH V2] " Philip Rakity
2011-07-06 17:32 ` Nath, Arindam
2011-07-09 22:02 ` Chris Ball
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox