* [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs
@ 2015-02-06 12:12 Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 01/11] mmc: core: Reset driver type to default Adrian Hunter
` (11 more replies)
0 siblings, 12 replies; 16+ messages in thread
From: Adrian Hunter @ 2015-02-06 12:12 UTC (permalink / raw)
To: Ulf Hansson, Chris Ball; +Cc: linux-mmc, Philip Rakity, Adrian Hunter
Hi
Here is V2 of some patches to enable a host controller to select
driver strength for eMMCs using HS200 or HS400. These are based
on top of the re-tuning series.
There can be some confusion over the term "driver strength".
SD calls it "drive strength" for the card but "driver type"
for the host. Whereas JEDEC calls it both "driver strength"
and "driver type". The values are the same for both SD
and eMMC:
Value Driver Type Relative strength
0 B x1 default and mandatory support
1 A x1.5
2 C x0.75
3 D x0.5
Except eMMC also defines value 4:
Value Driver Type Relative strength
4 x1.2
Changes in V2:
mmc: core: Add function to read driver-strength device property
Dropped because there are still questions over how to use
device properties.
mmc: sdhci-pci: Add support for drive strength selection for SPT
Amended to reflect the change above.
Adrian Hunter (11):
mmc: core: Reset driver type to default
mmc: core: Allow card drive strength to be different to host
mmc: core: Simplify card drive strength mask
mmc: core: Add 'card' to drive strength selection callback
mmc: core: Factor out common code in drive strength selection
mmc: core: Record card drive strength
mmc: mmc: Read card's valid driver strength mask
mmc: mmc: Add driver strength selection
mmc: sdhci: Add a callback to select drive strength
mmc: sdhci-pci: Add support for drive strength selection for SPT
mmc: sdhci-pci: Enable HS400 for some Intel host controllers
drivers/mmc/core/core.c | 39 ++++++++++++++++++
drivers/mmc/core/core.h | 2 +
drivers/mmc/core/mmc.c | 46 +++++++++++++++++----
drivers/mmc/core/sd.c | 69 ++++++++-----------------------
drivers/mmc/core/sdio.c | 77 +++++++++++-----------------------
drivers/mmc/host/sdhci-pci-data.c | 3 ++
drivers/mmc/host/sdhci-pci.c | 84 ++++++++++++++++++++++++++++++++++++++
drivers/mmc/host/sdhci-pci.h | 4 ++
drivers/mmc/host/sdhci.c | 13 ++++++
drivers/mmc/host/sdhci.h | 4 ++
include/linux/mmc/card.h | 2 +
include/linux/mmc/host.h | 4 +-
include/linux/mmc/mmc.h | 4 ++
include/linux/mmc/sdhci-pci-data.h | 2 +
14 files changed, 240 insertions(+), 113 deletions(-)
Regards
Adrian
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH V2 01/11] mmc: core: Reset driver type to default
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
@ 2015-02-06 12:12 ` Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 02/11] mmc: core: Allow card drive strength to be different to host Adrian Hunter
` (10 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Adrian Hunter @ 2015-02-06 12:12 UTC (permalink / raw)
To: Ulf Hansson, Chris Ball; +Cc: linux-mmc, Philip Rakity, Adrian Hunter
IO state variable drv_type could be set during card
initialization. Consequently, it must be reset to the
default value when setting the initial state.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/core/core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index cd46c0e..dbc40c5 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1179,6 +1179,7 @@ void mmc_set_initial_state(struct mmc_host *host)
host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
host->ios.bus_width = MMC_BUS_WIDTH_1;
host->ios.timing = MMC_TIMING_LEGACY;
+ host->ios.drv_type = 0;
mmc_set_ios(host);
}
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V2 02/11] mmc: core: Allow card drive strength to be different to host
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 01/11] mmc: core: Reset driver type to default Adrian Hunter
@ 2015-02-06 12:12 ` Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 03/11] mmc: core: Simplify card drive strength mask Adrian Hunter
` (9 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Adrian Hunter @ 2015-02-06 12:12 UTC (permalink / raw)
To: Ulf Hansson, Chris Ball; +Cc: linux-mmc, Philip Rakity, Adrian Hunter
Initialization of UHS-I modes for SD and SDIO cards
employs a callback to allow the host driver to
choose a drive strength value. Currently that
assumes the card drive strength and host driver
type must be the same value. Change to let the
callback make that decision and return both the
card drive strength and host driver type.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/core/sd.c | 33 +++++++++++++--------------------
drivers/mmc/core/sdio.c | 43 ++++++++++++++++++-------------------------
include/linux/mmc/host.h | 3 ++-
3 files changed, 33 insertions(+), 46 deletions(-)
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index ad4d43e..cbee29a 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -388,18 +388,9 @@ 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 drive_strength, drv_type;
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;
@@ -430,20 +421,22 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
mmc_host_clk_hold(card->host);
drive_strength = card->host->ops->select_drive_strength(
card->sw_caps.uhs_max_dtr,
- host_drv_type, card_drv_type);
+ host_drv_type, card_drv_type, &drv_type);
mmc_host_clk_release(card->host);
- err = mmc_sd_switch(card, 1, 2, drive_strength, status);
- if (err)
- return err;
-
- if ((status[15] & 0xF) != drive_strength) {
- pr_warn("%s: Problem setting drive strength!\n",
- mmc_hostname(card->host));
- return 0;
+ if (drive_strength) {
+ err = mmc_sd_switch(card, 1, 2, drive_strength, status);
+ if (err)
+ return err;
+ if ((status[15] & 0xF) != drive_strength) {
+ pr_warn("%s: Problem setting drive strength!\n",
+ mmc_hostname(card->host));
+ return 0;
+ }
}
- mmc_set_driver_type(card->host, drive_strength);
+ if (drv_type)
+ mmc_set_driver_type(card->host, drv_type);
return 0;
}
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index ce6cc47..d7309ab 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -401,21 +401,10 @@ static void sdio_select_driver_type(struct mmc_card *card)
{
int host_drv_type = SD_DRIVER_TYPE_B;
int card_drv_type = SD_DRIVER_TYPE_B;
- int drive_strength;
+ int drive_strength, drv_type;
unsigned char card_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;
-
if (!card->host->ops->select_drive_strength)
return;
@@ -445,23 +434,27 @@ static void sdio_select_driver_type(struct mmc_card *card)
*/
drive_strength = card->host->ops->select_drive_strength(
card->sw_caps.uhs_max_dtr,
- host_drv_type, card_drv_type);
+ host_drv_type, card_drv_type, &drv_type);
- /* if error just use default for drive strength B */
- err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_DRIVE_STRENGTH, 0,
- &card_strength);
- if (err)
- return;
+ if (drive_strength) {
+ /* if error just use default for drive strength B */
+ err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_DRIVE_STRENGTH, 0,
+ &card_strength);
+ if (err)
+ return;
- card_strength &= ~(SDIO_DRIVE_DTSx_MASK<<SDIO_DRIVE_DTSx_SHIFT);
- card_strength |= host_drive_to_sdio_drive(drive_strength);
+ card_strength &= ~(SDIO_DRIVE_DTSx_MASK<<SDIO_DRIVE_DTSx_SHIFT);
+ card_strength |= host_drive_to_sdio_drive(drive_strength);
- err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_DRIVE_STRENGTH,
- card_strength, NULL);
+ /* if error default to drive strength B */
+ err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_DRIVE_STRENGTH,
+ card_strength, NULL);
+ if (err)
+ return;
+ }
- /* if error default to drive strength B */
- if (!err)
- mmc_set_driver_type(card->host, drive_strength);
+ if (drv_type)
+ mmc_set_driver_type(card->host, drv_type);
}
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index e9a7470..d984c55 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -138,7 +138,8 @@ struct mmc_host_ops {
/* Prepare HS400 target operating frequency depending host driver */
int (*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
- int (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
+ int (*select_drive_strength)(unsigned int max_dtr, int host_drv,
+ int card_drv, int *drv_type);
void (*hw_reset)(struct mmc_host *host);
void (*card_event)(struct mmc_host *host);
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V2 03/11] mmc: core: Simplify card drive strength mask
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 01/11] mmc: core: Reset driver type to default Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 02/11] mmc: core: Allow card drive strength to be different to host Adrian Hunter
@ 2015-02-06 12:12 ` Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 04/11] mmc: core: Add 'card' to drive strength selection callback Adrian Hunter
` (8 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Adrian Hunter @ 2015-02-06 12:12 UTC (permalink / raw)
To: Ulf Hansson, Chris Ball; +Cc: linux-mmc, Philip Rakity, Adrian Hunter
Card drive strength selection uses a callback to
which a mask of supported drive strengths is passed.
Currently, the bits are checked against the values
in the SD specifications. That is not necessary
because the callback will anyway match the mask
against a valid value. Simplify by taking the mask
as is but still ensuring that the default mandatory
value (type B) is always supported.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/core/sd.c | 12 ++----------
drivers/mmc/core/sdio.c | 12 ++----------
2 files changed, 4 insertions(+), 20 deletions(-)
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index cbee29a..fab83e8 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -387,8 +387,7 @@ out:
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, drv_type;
+ int card_drv_type, drive_strength, drv_type;
int err;
if (!card->host->ops->select_drive_strength)
@@ -403,14 +402,7 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
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;
+ card_drv_type = card->sw_caps.sd3_drv_type | SD_DRIVER_TYPE_B;
/*
* The drive strength that the hardware can support
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index d7309ab..76e4dde 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -400,8 +400,7 @@ static unsigned char host_drive_to_sdio_drive(int host_strength)
static void sdio_select_driver_type(struct mmc_card *card)
{
int host_drv_type = SD_DRIVER_TYPE_B;
- int card_drv_type = SD_DRIVER_TYPE_B;
- int drive_strength, drv_type;
+ int card_drv_type, drive_strength, drv_type;
unsigned char card_strength;
int err;
@@ -417,14 +416,7 @@ static void sdio_select_driver_type(struct mmc_card *card)
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;
+ card_drv_type = card->sw_caps.sd3_drv_type | SD_DRIVER_TYPE_B;
/*
* The drive strength that the hardware can support
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V2 04/11] mmc: core: Add 'card' to drive strength selection callback
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
` (2 preceding siblings ...)
2015-02-06 12:12 ` [PATCH V2 03/11] mmc: core: Simplify card drive strength mask Adrian Hunter
@ 2015-02-06 12:12 ` Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 05/11] mmc: core: Factor out common code in drive strength selection Adrian Hunter
` (7 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Adrian Hunter @ 2015-02-06 12:12 UTC (permalink / raw)
To: Ulf Hansson, Chris Ball; +Cc: linux-mmc, Philip Rakity, Adrian Hunter
In preparation for supporting also eMMC drive strength,
add the 'card' as a parameter so that the callback can
distinguish different types of cards if necessary.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/core/sd.c | 2 +-
drivers/mmc/core/sdio.c | 2 +-
include/linux/mmc/host.h | 3 ++-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index fab83e8..dba1acf 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -411,7 +411,7 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
* return what is possible given the options
*/
mmc_host_clk_hold(card->host);
- drive_strength = card->host->ops->select_drive_strength(
+ drive_strength = card->host->ops->select_drive_strength(card,
card->sw_caps.uhs_max_dtr,
host_drv_type, card_drv_type, &drv_type);
mmc_host_clk_release(card->host);
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 76e4dde..de92ffe 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -424,7 +424,7 @@ static void sdio_select_driver_type(struct mmc_card *card)
* information and let the hardware specific code
* return what is possible given the options
*/
- drive_strength = card->host->ops->select_drive_strength(
+ drive_strength = card->host->ops->select_drive_strength(card,
card->sw_caps.uhs_max_dtr,
host_drv_type, card_drv_type, &drv_type);
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index d984c55..967e7db 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -138,7 +138,8 @@ struct mmc_host_ops {
/* Prepare HS400 target operating frequency depending host driver */
int (*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
- int (*select_drive_strength)(unsigned int max_dtr, int host_drv,
+ int (*select_drive_strength)(struct mmc_card *card,
+ unsigned int max_dtr, int host_drv,
int card_drv, int *drv_type);
void (*hw_reset)(struct mmc_host *host);
void (*card_event)(struct mmc_host *host);
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V2 05/11] mmc: core: Factor out common code in drive strength selection
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
` (3 preceding siblings ...)
2015-02-06 12:12 ` [PATCH V2 04/11] mmc: core: Add 'card' to drive strength selection callback Adrian Hunter
@ 2015-02-06 12:12 ` Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 06/11] mmc: core: Record card drive strength Adrian Hunter
` (6 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Adrian Hunter @ 2015-02-06 12:12 UTC (permalink / raw)
To: Ulf Hansson, Chris Ball; +Cc: linux-mmc, Philip Rakity, Adrian Hunter
Make a new function out of common code used for drive
strength selection.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/core/core.c | 38 ++++++++++++++++++++++++++++++++++++++
drivers/mmc/core/core.h | 2 ++
drivers/mmc/core/sd.c | 27 +++------------------------
drivers/mmc/core/sdio.c | 25 +++----------------------
4 files changed, 46 insertions(+), 46 deletions(-)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index dbc40c5..373a1cf 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1634,6 +1634,44 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
mmc_host_clk_release(host);
}
+int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr,
+ int card_drv_type, int *drv_type)
+{
+ struct mmc_host *host = card->host;
+ int host_drv_type = SD_DRIVER_TYPE_B;
+ int drive_strength;
+
+ *drv_type = 0;
+
+ if (!host->ops->select_drive_strength)
+ return 0;
+
+ /* Use SD definition of driver strength for hosts */
+ if (host->caps & MMC_CAP_DRIVER_TYPE_A)
+ host_drv_type |= SD_DRIVER_TYPE_A;
+
+ if (host->caps & MMC_CAP_DRIVER_TYPE_C)
+ host_drv_type |= SD_DRIVER_TYPE_C;
+
+ if (host->caps & MMC_CAP_DRIVER_TYPE_D)
+ host_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
+ */
+ mmc_host_clk_hold(host);
+ drive_strength = host->ops->select_drive_strength(card, max_dtr,
+ host_drv_type,
+ card_drv_type,
+ drv_type);
+ mmc_host_clk_release(host);
+
+ return drive_strength;
+}
+
/*
* Apply power to the MMC stack. This is a two-stage process.
* First, we enable power to the card without the clock running.
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index e6f2de7..1a22a82 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -50,6 +50,8 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr);
int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage);
void mmc_set_timing(struct mmc_host *host, unsigned int timing);
void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type);
+int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr,
+ int card_drv_type, int *drv_type);
void mmc_power_up(struct mmc_host *host, u32 ocr);
void mmc_power_off(struct mmc_host *host);
void mmc_power_cycle(struct mmc_host *host, u32 ocr);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index dba1acf..e1a98b1 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -386,35 +386,14 @@ out:
static int sd_select_driver_type(struct mmc_card *card, u8 *status)
{
- int host_drv_type = SD_DRIVER_TYPE_B;
int card_drv_type, drive_strength, drv_type;
int err;
- 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;
-
card_drv_type = card->sw_caps.sd3_drv_type | SD_DRIVER_TYPE_B;
- /*
- * 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
- */
- mmc_host_clk_hold(card->host);
- drive_strength = card->host->ops->select_drive_strength(card,
- card->sw_caps.uhs_max_dtr,
- host_drv_type, card_drv_type, &drv_type);
- mmc_host_clk_release(card->host);
+ drive_strength = mmc_select_drive_strength(card,
+ card->sw_caps.uhs_max_dtr,
+ card_drv_type, &drv_type);
if (drive_strength) {
err = mmc_sd_switch(card, 1, 2, drive_strength, status);
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index de92ffe..8cc1793 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -399,34 +399,15 @@ static unsigned char host_drive_to_sdio_drive(int host_strength)
static void sdio_select_driver_type(struct mmc_card *card)
{
- int host_drv_type = SD_DRIVER_TYPE_B;
int card_drv_type, drive_strength, drv_type;
unsigned char card_strength;
int err;
- if (!card->host->ops->select_drive_strength)
- return;
-
- 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;
-
card_drv_type = card->sw_caps.sd3_drv_type | SD_DRIVER_TYPE_B;
- /*
- * 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,
- card->sw_caps.uhs_max_dtr,
- host_drv_type, card_drv_type, &drv_type);
+ drive_strength = mmc_select_drive_strength(card,
+ card->sw_caps.uhs_max_dtr,
+ card_drv_type, &drv_type);
if (drive_strength) {
/* if error just use default for drive strength B */
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V2 06/11] mmc: core: Record card drive strength
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
` (4 preceding siblings ...)
2015-02-06 12:12 ` [PATCH V2 05/11] mmc: core: Factor out common code in drive strength selection Adrian Hunter
@ 2015-02-06 12:12 ` Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 07/11] mmc: mmc: Read card's valid driver strength mask Adrian Hunter
` (5 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Adrian Hunter @ 2015-02-06 12:12 UTC (permalink / raw)
To: Ulf Hansson, Chris Ball; +Cc: linux-mmc, Philip Rakity, Adrian Hunter
In preparation for adding drive strength support
for eMMC, add drive_strength to struct mmc_card
to record the card drive strength for UHS-I modes
and HS200 / HS400. For eMMC this will be needed
when switching between HS200 and HS400.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/core/sd.c | 3 +++
drivers/mmc/core/sdio.c | 3 +++
include/linux/mmc/card.h | 1 +
3 files changed, 7 insertions(+)
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index e1a98b1..2fdb41b 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -389,6 +389,8 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
int card_drv_type, drive_strength, drv_type;
int err;
+ card->drive_strength = 0;
+
card_drv_type = card->sw_caps.sd3_drv_type | SD_DRIVER_TYPE_B;
drive_strength = mmc_select_drive_strength(card,
@@ -404,6 +406,7 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
mmc_hostname(card->host));
return 0;
}
+ card->drive_strength = drive_strength;
}
if (drv_type)
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 8cc1793..fa81ba53 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -403,6 +403,8 @@ static void sdio_select_driver_type(struct mmc_card *card)
unsigned char card_strength;
int err;
+ card->drive_strength = 0;
+
card_drv_type = card->sw_caps.sd3_drv_type | SD_DRIVER_TYPE_B;
drive_strength = mmc_select_drive_strength(card,
@@ -424,6 +426,7 @@ static void sdio_select_driver_type(struct mmc_card *card)
card_strength, NULL);
if (err)
return;
+ card->drive_strength = drive_strength;
}
if (drv_type)
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index a6cf4c0..ad54861 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -305,6 +305,7 @@ struct mmc_card {
unsigned int sd_bus_speed; /* Bus Speed Mode set for the card */
unsigned int mmc_avail_type; /* supported device type by both host and card */
+ unsigned int drive_strength; /* for UHS-I, HS200 or HS400 */
struct dentry *debugfs_root;
struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V2 07/11] mmc: mmc: Read card's valid driver strength mask
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
` (5 preceding siblings ...)
2015-02-06 12:12 ` [PATCH V2 06/11] mmc: core: Record card drive strength Adrian Hunter
@ 2015-02-06 12:12 ` Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 08/11] mmc: mmc: Add driver strength selection Adrian Hunter
` (4 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Adrian Hunter @ 2015-02-06 12:12 UTC (permalink / raw)
To: Ulf Hansson, Chris Ball; +Cc: linux-mmc, Philip Rakity, Adrian Hunter
In preparation for supporing drive strength selection
for eMMC, read the card's valid driver strengths.
Note that though the SD spec uses the term "drive strength",
the JEDEC eMMC spec uses the term "driver strength".
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/core/mmc.c | 1 +
include/linux/mmc/card.h | 1 +
include/linux/mmc/mmc.h | 1 +
3 files changed, 3 insertions(+)
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 03577be..3222d4a 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -426,6 +426,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
card->ext_csd.raw_trim_mult =
ext_csd[EXT_CSD_TRIM_MULT];
card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
+ card->ext_csd.raw_driver_strength = ext_csd[EXT_CSD_DRIVER_STRENGTH];
if (card->ext_csd.rev >= 4) {
if (ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED] &
EXT_CSD_PART_SETTING_COMPLETED)
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index ad54861..ebfb3c9 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -97,6 +97,7 @@ struct mmc_ext_csd {
u8 raw_erased_mem_count; /* 181 */
u8 raw_ext_csd_structure; /* 194 */
u8 raw_card_type; /* 196 */
+ u8 raw_driver_strength; /* 197 */
u8 out_of_int_time; /* 198 */
u8 raw_pwr_cl_52_195; /* 200 */
u8 raw_pwr_cl_26_195; /* 201 */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 124f562..4819cfb 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -302,6 +302,7 @@ struct _mmc_csd {
#define EXT_CSD_REV 192 /* RO */
#define EXT_CSD_STRUCTURE 194 /* RO */
#define EXT_CSD_CARD_TYPE 196 /* RO */
+#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */
#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */
#define EXT_CSD_PART_SWITCH_TIME 199 /* RO */
#define EXT_CSD_PWR_CL_52_195 200 /* RO */
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V2 08/11] mmc: mmc: Add driver strength selection
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
` (6 preceding siblings ...)
2015-02-06 12:12 ` [PATCH V2 07/11] mmc: mmc: Read card's valid driver strength mask Adrian Hunter
@ 2015-02-06 12:12 ` Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 09/11] mmc: sdhci: Add a callback to select drive strength Adrian Hunter
` (3 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Adrian Hunter @ 2015-02-06 12:12 UTC (permalink / raw)
To: Ulf Hansson, Chris Ball; +Cc: linux-mmc, Philip Rakity, Adrian Hunter
Add the ability to set eMMC driver strength
for HS200 and HS400.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/core/mmc.c | 45 ++++++++++++++++++++++++++++++++++++++-------
include/linux/mmc/mmc.h | 3 +++
2 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 3222d4a..23cc737 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1033,6 +1033,7 @@ static int mmc_select_hs400(struct mmc_card *card)
{
struct mmc_host *host = card->host;
int err = 0;
+ u8 val;
/*
* HS400 mode requires 8-bit bus width
@@ -1048,8 +1049,10 @@ static int mmc_select_hs400(struct mmc_card *card)
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
mmc_set_bus_speed(card);
+ val = EXT_CSD_TIMING_HS |
+ card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
+ EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
true, true, true);
if (err) {
@@ -1068,8 +1071,10 @@ static int mmc_select_hs400(struct mmc_card *card)
return err;
}
+ val = EXT_CSD_TIMING_HS400 |
+ card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400,
+ EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
true, true, true);
if (err) {
@@ -1108,6 +1113,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
bool send_status = true;
unsigned int max_dtr;
int err;
+ u8 val;
if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
send_status = false;
@@ -1117,8 +1123,10 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
mmc_set_clock(host, max_dtr);
/* Switch HS400 to HS DDR */
+ val = EXT_CSD_TIMING_HS |
+ card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
- EXT_CSD_TIMING_HS, card->ext_csd.generic_cmd6_time,
+ val, card->ext_csd.generic_cmd6_time,
true, send_status, true);
if (err)
goto out_err;
@@ -1147,10 +1155,11 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
}
/* Switch HS to HS200 */
+ val = EXT_CSD_TIMING_HS200 |
+ card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
- EXT_CSD_TIMING_HS200,
- card->ext_csd.generic_cmd6_time, true, send_status,
- true);
+ val, card->ext_csd.generic_cmd6_time, true,
+ send_status, true);
if (err)
goto out_err;
@@ -1172,6 +1181,23 @@ out_err:
return err;
}
+static void mmc_select_driver_type(struct mmc_card *card)
+{
+ int card_drv_type, drive_strength, drv_type;
+
+ card_drv_type = card->ext_csd.raw_driver_strength |
+ mmc_driver_type_mask(0);
+
+ drive_strength = mmc_select_drive_strength(card,
+ card->ext_csd.hs200_max_dtr,
+ card_drv_type, &drv_type);
+
+ card->drive_strength = drive_strength;
+
+ if (drv_type)
+ mmc_set_driver_type(card->host, drv_type);
+}
+
/*
* For device supporting HS200 mode, the following sequence
* should be done before executing the tuning process.
@@ -1183,6 +1209,7 @@ static int mmc_select_hs200(struct mmc_card *card)
{
struct mmc_host *host = card->host;
int err = -EINVAL;
+ u8 val;
if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
@@ -1194,14 +1221,18 @@ static int mmc_select_hs200(struct mmc_card *card)
if (err)
goto err;
+ mmc_select_driver_type(card);
+
/*
* Set the bus width(4 or 8) with host's support and
* switch to HS200 mode if bus width is set successfully.
*/
err = mmc_select_bus_width(card);
if (!IS_ERR_VALUE(err)) {
+ val = EXT_CSD_TIMING_HS200 |
+ card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200,
+ EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
true, true, true);
if (!err)
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 4819cfb..15f2c4a 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -391,6 +391,7 @@ struct _mmc_csd {
#define EXT_CSD_TIMING_HS 1 /* High speed */
#define EXT_CSD_TIMING_HS200 2 /* HS200 */
#define EXT_CSD_TIMING_HS400 3 /* HS400 */
+#define EXT_CSD_DRV_STR_SHIFT 4 /* Driver Strength shift */
#define EXT_CSD_SEC_ER_EN BIT(0)
#define EXT_CSD_SEC_BD_BLK_EN BIT(2)
@@ -442,4 +443,6 @@ struct _mmc_csd {
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
+#define mmc_driver_type_mask(n) (1 << (n))
+
#endif /* LINUX_MMC_MMC_H */
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V2 09/11] mmc: sdhci: Add a callback to select drive strength
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
` (7 preceding siblings ...)
2015-02-06 12:12 ` [PATCH V2 08/11] mmc: mmc: Add driver strength selection Adrian Hunter
@ 2015-02-06 12:12 ` Adrian Hunter
2015-02-06 12:13 ` [PATCH V2 10/11] mmc: sdhci-pci: Add support for drive strength selection for SPT Adrian Hunter
` (2 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Adrian Hunter @ 2015-02-06 12:12 UTC (permalink / raw)
To: Ulf Hansson, Chris Ball; +Cc: linux-mmc, Philip Rakity, Adrian Hunter
Add a callbak to let host drivers select drive
strength.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/host/sdhci.c | 13 +++++++++++++
drivers/mmc/host/sdhci.h | 4 ++++
2 files changed, 17 insertions(+)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 8848e06..fe1b00d 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2054,6 +2054,18 @@ out_unlock:
return err;
}
+static int sdhci_select_drive_strength(struct mmc_card *card,
+ unsigned int max_dtr, int host_drv,
+ int card_drv, int *drv_type)
+{
+ struct sdhci_host *host = mmc_priv(card->host);
+
+ if (!host->ops->select_drive_strength)
+ return 0;
+
+ return host->ops->select_drive_strength(host, card, max_dtr, host_drv,
+ card_drv, drv_type);
+}
static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
{
@@ -2198,6 +2210,7 @@ static const struct mmc_host_ops sdhci_ops = {
.start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
.prepare_hs400_tuning = sdhci_prepare_hs400_tuning,
.execute_tuning = sdhci_execute_tuning,
+ .select_drive_strength = sdhci_select_drive_strength,
.card_event = sdhci_card_event,
.card_busy = sdhci_card_busy,
};
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 0315e18..57e7bad 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -340,6 +340,10 @@ struct sdhci_ops {
void (*platform_init)(struct sdhci_host *host);
void (*card_event)(struct sdhci_host *host);
void (*voltage_switch)(struct sdhci_host *host);
+ int (*select_drive_strength)(struct sdhci_host *host,
+ struct mmc_card *card,
+ unsigned int max_dtr, int host_drv,
+ int card_drv, int *drv_type);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V2 10/11] mmc: sdhci-pci: Add support for drive strength selection for SPT
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
` (8 preceding siblings ...)
2015-02-06 12:12 ` [PATCH V2 09/11] mmc: sdhci: Add a callback to select drive strength Adrian Hunter
@ 2015-02-06 12:13 ` Adrian Hunter
2015-02-06 12:13 ` [PATCH V2 11/11] mmc: sdhci-pci: Enable HS400 for some Intel host controllers Adrian Hunter
2015-05-11 9:29 ` [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
11 siblings, 0 replies; 16+ messages in thread
From: Adrian Hunter @ 2015-02-06 12:13 UTC (permalink / raw)
To: Ulf Hansson, Chris Ball; +Cc: linux-mmc, Philip Rakity, Adrian Hunter
Implement the select_drive_strength callback to provide
drive strength selection for Intel SPT.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/host/sdhci-pci-data.c | 3 ++
drivers/mmc/host/sdhci-pci.c | 83 ++++++++++++++++++++++++++++++++++++++
drivers/mmc/host/sdhci-pci.h | 4 ++
include/linux/mmc/sdhci-pci-data.h | 2 +
4 files changed, 92 insertions(+)
diff --git a/drivers/mmc/host/sdhci-pci-data.c b/drivers/mmc/host/sdhci-pci-data.c
index a611217..56fddc6 100644
--- a/drivers/mmc/host/sdhci-pci-data.c
+++ b/drivers/mmc/host/sdhci-pci-data.c
@@ -3,3 +3,6 @@
struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno);
EXPORT_SYMBOL_GPL(sdhci_pci_get_data);
+
+int sdhci_pci_spt_drive_strength;
+EXPORT_SYMBOL_GPL(sdhci_pci_spt_drive_strength);
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 29eaff7..d778a81 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
#include <linux/scatterlist.h>
#include <linux/io.h>
#include <linux/gpio.h>
@@ -266,6 +267,69 @@ static void sdhci_pci_int_hw_reset(struct sdhci_host *host)
usleep_range(300, 1000);
}
+static int spt_select_drive_strength(struct sdhci_host *host,
+ struct mmc_card *card,
+ unsigned int max_dtr,
+ int host_drv, int card_drv, int *drv_type)
+{
+ int drive_strength;
+
+ if (sdhci_pci_spt_drive_strength > 0)
+ drive_strength = sdhci_pci_spt_drive_strength & 0xf;
+ else
+ drive_strength = 1; /* 33-ohm */
+
+ if ((mmc_driver_type_mask(drive_strength) & card_drv) == 0)
+ drive_strength = 0; /* Default 50-ohm */
+
+ return drive_strength;
+}
+
+/* Try to read the drive strength from the card */
+static void spt_read_drive_strength(struct sdhci_host *host)
+{
+ u32 val, i, t;
+ u16 m;
+
+ if (sdhci_pci_spt_drive_strength)
+ return;
+
+ sdhci_pci_spt_drive_strength = -1;
+
+ m = sdhci_readw(host, SDHCI_HOST_CONTROL2) & 0x7;
+ if (m != 3 && m != 5)
+ return;
+ val = sdhci_readl(host, SDHCI_PRESENT_STATE);
+ if (val & 0x3)
+ return;
+ sdhci_writel(host, 0x007f0023, SDHCI_INT_ENABLE);
+ sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
+ sdhci_writew(host, 0x10, SDHCI_TRANSFER_MODE);
+ sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL);
+ sdhci_writew(host, 512, SDHCI_BLOCK_SIZE);
+ sdhci_writew(host, 1, SDHCI_BLOCK_COUNT);
+ sdhci_writel(host, 0, SDHCI_ARGUMENT);
+ sdhci_writew(host, 0x83b, SDHCI_COMMAND);
+ for (i = 0; i < 1000; i++) {
+ val = sdhci_readl(host, SDHCI_INT_STATUS);
+ if (val & 0xffff8000)
+ return;
+ if (val & 0x20)
+ break;
+ udelay(1);
+ }
+ val = sdhci_readl(host, SDHCI_PRESENT_STATE);
+ if (!(val & 0x800))
+ return;
+ for (i = 0; i < 47; i++)
+ val = sdhci_readl(host, SDHCI_BUFFER);
+ t = val & 0xf00;
+ if (t != 0x200 && t != 0x300)
+ return;
+
+ sdhci_pci_spt_drive_strength = 0x10 | ((val >> 12) & 0xf);
+}
+
static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
{
slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
@@ -276,6 +340,10 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
slot->hw_reset = sdhci_pci_int_hw_reset;
if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BSW_EMMC)
slot->host->timeout_clk = 1000; /* 1000 kHz i.e. 1 MHz */
+ if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_SPT_EMMC) {
+ spt_read_drive_strength(slot->host);
+ slot->select_drive_strength = spt_select_drive_strength;
+ }
return 0;
}
@@ -1202,6 +1270,20 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host)
slot->hw_reset(host);
}
+static int sdhci_pci_select_drive_strength(struct sdhci_host *host,
+ struct mmc_card *card,
+ unsigned int max_dtr, int host_drv,
+ int card_drv, int *drv_type)
+{
+ struct sdhci_pci_slot *slot = sdhci_priv(host);
+
+ if (!slot->select_drive_strength)
+ return 0;
+
+ return slot->select_drive_strength(host, card, max_dtr, host_drv,
+ card_drv, drv_type);
+}
+
static const struct sdhci_ops sdhci_pci_ops = {
.set_clock = sdhci_set_clock,
.enable_dma = sdhci_pci_enable_dma,
@@ -1209,6 +1291,7 @@ static const struct sdhci_ops sdhci_pci_ops = {
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
.hw_reset = sdhci_pci_hw_reset,
+ .select_drive_strength = sdhci_pci_select_drive_strength,
};
/*****************************************************************************\
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
index 1ec684d..541f1ca 100644
--- a/drivers/mmc/host/sdhci-pci.h
+++ b/drivers/mmc/host/sdhci-pci.h
@@ -72,6 +72,10 @@ struct sdhci_pci_slot {
bool cd_override_level;
void (*hw_reset)(struct sdhci_host *host);
+ int (*select_drive_strength)(struct sdhci_host *host,
+ struct mmc_card *card,
+ unsigned int max_dtr, int host_drv,
+ int card_drv, int *drv_type);
};
struct sdhci_pci_chip {
diff --git a/include/linux/mmc/sdhci-pci-data.h b/include/linux/mmc/sdhci-pci-data.h
index 8959604..fda15b6 100644
--- a/include/linux/mmc/sdhci-pci-data.h
+++ b/include/linux/mmc/sdhci-pci-data.h
@@ -15,4 +15,6 @@ struct sdhci_pci_data {
extern struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev,
int slotno);
+extern int sdhci_pci_spt_drive_strength;
+
#endif
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V2 11/11] mmc: sdhci-pci: Enable HS400 for some Intel host controllers
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
` (9 preceding siblings ...)
2015-02-06 12:13 ` [PATCH V2 10/11] mmc: sdhci-pci: Add support for drive strength selection for SPT Adrian Hunter
@ 2015-02-06 12:13 ` Adrian Hunter
2015-05-11 9:29 ` [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
11 siblings, 0 replies; 16+ messages in thread
From: Adrian Hunter @ 2015-02-06 12:13 UTC (permalink / raw)
To: Ulf Hansson, Chris Ball; +Cc: linux-mmc, Philip Rakity, Adrian Hunter
Enable detection of HS400 support via capability bit-63
for some Intel host controllers.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/host/sdhci-pci.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index d778a81..5a5b5e9 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -370,6 +370,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
.probe_slot = byt_emmc_probe_slot,
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
+ SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 |
SDHCI_QUIRK2_STOP_WITH_TC,
};
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
` (10 preceding siblings ...)
2015-02-06 12:13 ` [PATCH V2 11/11] mmc: sdhci-pci: Enable HS400 for some Intel host controllers Adrian Hunter
@ 2015-05-11 9:29 ` Adrian Hunter
2015-05-11 10:23 ` Ulf Hansson
11 siblings, 1 reply; 16+ messages in thread
From: Adrian Hunter @ 2015-05-11 9:29 UTC (permalink / raw)
To: Ulf Hansson; +Cc: linux-mmc, Philip Rakity
On 06/02/15 14:12, Adrian Hunter wrote:
> Hi
>
> Here is V2 of some patches to enable a host controller to select
> driver strength for eMMCs using HS200 or HS400. These are based
> on top of the re-tuning series.
>
> There can be some confusion over the term "driver strength".
> SD calls it "drive strength" for the card but "driver type"
> for the host. Whereas JEDEC calls it both "driver strength"
> and "driver type". The values are the same for both SD
> and eMMC:
>
> Value Driver Type Relative strength
> 0 B x1 default and mandatory support
> 1 A x1.5
> 2 C x0.75
> 3 D x0.5
>
> Except eMMC also defines value 4:
>
> Value Driver Type Relative strength
> 4 x1.2
>
>
> Changes in V2:
>
> mmc: core: Add function to read driver-strength device property
> Dropped because there are still questions over how to use
> device properties.
>
> mmc: sdhci-pci: Add support for drive strength selection for SPT
> Amended to reflect the change above.
>
>
> Adrian Hunter (11):
> mmc: core: Reset driver type to default
> mmc: core: Allow card drive strength to be different to host
> mmc: core: Simplify card drive strength mask
> mmc: core: Add 'card' to drive strength selection callback
> mmc: core: Factor out common code in drive strength selection
> mmc: core: Record card drive strength
> mmc: mmc: Read card's valid driver strength mask
> mmc: mmc: Add driver strength selection
> mmc: sdhci: Add a callback to select drive strength
> mmc: sdhci-pci: Add support for drive strength selection for SPT
> mmc: sdhci-pci: Enable HS400 for some Intel host controllers
>
> drivers/mmc/core/core.c | 39 ++++++++++++++++++
> drivers/mmc/core/core.h | 2 +
> drivers/mmc/core/mmc.c | 46 +++++++++++++++++----
> drivers/mmc/core/sd.c | 69 ++++++++-----------------------
> drivers/mmc/core/sdio.c | 77 +++++++++++-----------------------
> drivers/mmc/host/sdhci-pci-data.c | 3 ++
> drivers/mmc/host/sdhci-pci.c | 84 ++++++++++++++++++++++++++++++++++++++
> drivers/mmc/host/sdhci-pci.h | 4 ++
> drivers/mmc/host/sdhci.c | 13 ++++++
> drivers/mmc/host/sdhci.h | 4 ++
> include/linux/mmc/card.h | 2 +
> include/linux/mmc/host.h | 4 +-
> include/linux/mmc/mmc.h | 4 ++
> include/linux/mmc/sdhci-pci-data.h | 2 +
> 14 files changed, 240 insertions(+), 113 deletions(-)
Hi Ulf
These patches still apply. Would have time to look at them?
Regards
Adrian
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs
2015-05-11 9:29 ` [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
@ 2015-05-11 10:23 ` Ulf Hansson
2015-05-25 7:01 ` Adrian Hunter
0 siblings, 1 reply; 16+ messages in thread
From: Ulf Hansson @ 2015-05-11 10:23 UTC (permalink / raw)
To: Adrian Hunter; +Cc: linux-mmc, Philip Rakity
On 11 May 2015 at 11:29, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 06/02/15 14:12, Adrian Hunter wrote:
>> Hi
>>
>> Here is V2 of some patches to enable a host controller to select
>> driver strength for eMMCs using HS200 or HS400. These are based
>> on top of the re-tuning series.
>>
>> There can be some confusion over the term "driver strength".
>> SD calls it "drive strength" for the card but "driver type"
>> for the host. Whereas JEDEC calls it both "driver strength"
>> and "driver type". The values are the same for both SD
>> and eMMC:
>>
>> Value Driver Type Relative strength
>> 0 B x1 default and mandatory support
>> 1 A x1.5
>> 2 C x0.75
>> 3 D x0.5
>>
>> Except eMMC also defines value 4:
>>
>> Value Driver Type Relative strength
>> 4 x1.2
>>
>>
>> Changes in V2:
>>
>> mmc: core: Add function to read driver-strength device property
>> Dropped because there are still questions over how to use
>> device properties.
>>
>> mmc: sdhci-pci: Add support for drive strength selection for SPT
>> Amended to reflect the change above.
>>
>>
>> Adrian Hunter (11):
>> mmc: core: Reset driver type to default
>> mmc: core: Allow card drive strength to be different to host
>> mmc: core: Simplify card drive strength mask
>> mmc: core: Add 'card' to drive strength selection callback
>> mmc: core: Factor out common code in drive strength selection
>> mmc: core: Record card drive strength
>> mmc: mmc: Read card's valid driver strength mask
>> mmc: mmc: Add driver strength selection
>> mmc: sdhci: Add a callback to select drive strength
>> mmc: sdhci-pci: Add support for drive strength selection for SPT
>> mmc: sdhci-pci: Enable HS400 for some Intel host controllers
>>
>> drivers/mmc/core/core.c | 39 ++++++++++++++++++
>> drivers/mmc/core/core.h | 2 +
>> drivers/mmc/core/mmc.c | 46 +++++++++++++++++----
>> drivers/mmc/core/sd.c | 69 ++++++++-----------------------
>> drivers/mmc/core/sdio.c | 77 +++++++++++-----------------------
>> drivers/mmc/host/sdhci-pci-data.c | 3 ++
>> drivers/mmc/host/sdhci-pci.c | 84 ++++++++++++++++++++++++++++++++++++++
>> drivers/mmc/host/sdhci-pci.h | 4 ++
>> drivers/mmc/host/sdhci.c | 13 ++++++
>> drivers/mmc/host/sdhci.h | 4 ++
>> include/linux/mmc/card.h | 2 +
>> include/linux/mmc/host.h | 4 +-
>> include/linux/mmc/mmc.h | 4 ++
>> include/linux/mmc/sdhci-pci-data.h | 2 +
>> 14 files changed, 240 insertions(+), 113 deletions(-)
>
> Hi Ulf
>
> These patches still apply. Would have time to look at them?
Thanks for the reminder!
I am walking through my backlog, but I don't want to give you any
promises about when, since I never seems to be able to keep them. :-)
Kind regards
Uffe
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs
2015-05-11 10:23 ` Ulf Hansson
@ 2015-05-25 7:01 ` Adrian Hunter
2015-05-25 8:44 ` Ulf Hansson
0 siblings, 1 reply; 16+ messages in thread
From: Adrian Hunter @ 2015-05-25 7:01 UTC (permalink / raw)
To: Ulf Hansson; +Cc: linux-mmc, Philip Rakity
On 11/05/15 13:23, Ulf Hansson wrote:
> On 11 May 2015 at 11:29, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> On 06/02/15 14:12, Adrian Hunter wrote:
>>> Hi
>>>
>>> Here is V2 of some patches to enable a host controller to select
>>> driver strength for eMMCs using HS200 or HS400. These are based
>>> on top of the re-tuning series.
>>>
>>> There can be some confusion over the term "driver strength".
>>> SD calls it "drive strength" for the card but "driver type"
>>> for the host. Whereas JEDEC calls it both "driver strength"
>>> and "driver type". The values are the same for both SD
>>> and eMMC:
>>>
>>> Value Driver Type Relative strength
>>> 0 B x1 default and mandatory support
>>> 1 A x1.5
>>> 2 C x0.75
>>> 3 D x0.5
>>>
>>> Except eMMC also defines value 4:
>>>
>>> Value Driver Type Relative strength
>>> 4 x1.2
>>>
>>>
>>> Changes in V2:
>>>
>>> mmc: core: Add function to read driver-strength device property
>>> Dropped because there are still questions over how to use
>>> device properties.
>>>
>>> mmc: sdhci-pci: Add support for drive strength selection for SPT
>>> Amended to reflect the change above.
>>>
>>>
>>> Adrian Hunter (11):
>>> mmc: core: Reset driver type to default
>>> mmc: core: Allow card drive strength to be different to host
>>> mmc: core: Simplify card drive strength mask
>>> mmc: core: Add 'card' to drive strength selection callback
>>> mmc: core: Factor out common code in drive strength selection
>>> mmc: core: Record card drive strength
>>> mmc: mmc: Read card's valid driver strength mask
>>> mmc: mmc: Add driver strength selection
>>> mmc: sdhci: Add a callback to select drive strength
>>> mmc: sdhci-pci: Add support for drive strength selection for SPT
>>> mmc: sdhci-pci: Enable HS400 for some Intel host controllers
>>>
>>> drivers/mmc/core/core.c | 39 ++++++++++++++++++
>>> drivers/mmc/core/core.h | 2 +
>>> drivers/mmc/core/mmc.c | 46 +++++++++++++++++----
>>> drivers/mmc/core/sd.c | 69 ++++++++-----------------------
>>> drivers/mmc/core/sdio.c | 77 +++++++++++-----------------------
>>> drivers/mmc/host/sdhci-pci-data.c | 3 ++
>>> drivers/mmc/host/sdhci-pci.c | 84 ++++++++++++++++++++++++++++++++++++++
>>> drivers/mmc/host/sdhci-pci.h | 4 ++
>>> drivers/mmc/host/sdhci.c | 13 ++++++
>>> drivers/mmc/host/sdhci.h | 4 ++
>>> include/linux/mmc/card.h | 2 +
>>> include/linux/mmc/host.h | 4 +-
>>> include/linux/mmc/mmc.h | 4 ++
>>> include/linux/mmc/sdhci-pci-data.h | 2 +
>>> 14 files changed, 240 insertions(+), 113 deletions(-)
>>
>> Hi Ulf
>>
>> These patches still apply. Would have time to look at them?
>
> Thanks for the reminder!
>
> I am walking through my backlog, but I don't want to give you any
> promises about when, since I never seems to be able to keep them. :-)
Hi
Here's another reminder :-)
I would really like these patches and there is really not much to review.
Patch 1 is quite trivial - only 1 line changed.
Patch 2 is a change the select_drive_strength() host op to allow card driver
strength to be different from host driver strength. It has no effect on
current drivers.
Patch 3 is just tidying up.
Patch 4 is another change to the select_drive_strength() host op (to add
'card' as a parameter) and also has no effect on current drivers.
Patch 5 is another tidy up.
Patch 6 is a very small patch to add drive_strength to struct mmc_card.
Patch 7 is a very small change to read eMMC supported driver strengths from
EXT-CSD.
Patch 8 adds driver strength selection for eMMC
Patch 9, 10 implement the select_drive_strength() for Intel SPT with the
sdhci-pci driver.
Patch 11 finally just enables HS400 for Intel
This shouldn't really take that long to review ;-)
Regards
Adrian
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs
2015-05-25 7:01 ` Adrian Hunter
@ 2015-05-25 8:44 ` Ulf Hansson
0 siblings, 0 replies; 16+ messages in thread
From: Ulf Hansson @ 2015-05-25 8:44 UTC (permalink / raw)
To: Adrian Hunter; +Cc: linux-mmc, Philip Rakity
On 25 May 2015 at 09:01, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 11/05/15 13:23, Ulf Hansson wrote:
>> On 11 May 2015 at 11:29, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>> On 06/02/15 14:12, Adrian Hunter wrote:
>>>> Hi
>>>>
>>>> Here is V2 of some patches to enable a host controller to select
>>>> driver strength for eMMCs using HS200 or HS400. These are based
>>>> on top of the re-tuning series.
>>>>
>>>> There can be some confusion over the term "driver strength".
>>>> SD calls it "drive strength" for the card but "driver type"
>>>> for the host. Whereas JEDEC calls it both "driver strength"
>>>> and "driver type". The values are the same for both SD
>>>> and eMMC:
>>>>
>>>> Value Driver Type Relative strength
>>>> 0 B x1 default and mandatory support
>>>> 1 A x1.5
>>>> 2 C x0.75
>>>> 3 D x0.5
>>>>
>>>> Except eMMC also defines value 4:
>>>>
>>>> Value Driver Type Relative strength
>>>> 4 x1.2
>>>>
>>>>
>>>> Changes in V2:
>>>>
>>>> mmc: core: Add function to read driver-strength device property
>>>> Dropped because there are still questions over how to use
>>>> device properties.
>>>>
>>>> mmc: sdhci-pci: Add support for drive strength selection for SPT
>>>> Amended to reflect the change above.
>>>>
>>>>
>>>> Adrian Hunter (11):
>>>> mmc: core: Reset driver type to default
>>>> mmc: core: Allow card drive strength to be different to host
>>>> mmc: core: Simplify card drive strength mask
>>>> mmc: core: Add 'card' to drive strength selection callback
>>>> mmc: core: Factor out common code in drive strength selection
>>>> mmc: core: Record card drive strength
>>>> mmc: mmc: Read card's valid driver strength mask
>>>> mmc: mmc: Add driver strength selection
>>>> mmc: sdhci: Add a callback to select drive strength
>>>> mmc: sdhci-pci: Add support for drive strength selection for SPT
>>>> mmc: sdhci-pci: Enable HS400 for some Intel host controllers
>>>>
>>>> drivers/mmc/core/core.c | 39 ++++++++++++++++++
>>>> drivers/mmc/core/core.h | 2 +
>>>> drivers/mmc/core/mmc.c | 46 +++++++++++++++++----
>>>> drivers/mmc/core/sd.c | 69 ++++++++-----------------------
>>>> drivers/mmc/core/sdio.c | 77 +++++++++++-----------------------
>>>> drivers/mmc/host/sdhci-pci-data.c | 3 ++
>>>> drivers/mmc/host/sdhci-pci.c | 84 ++++++++++++++++++++++++++++++++++++++
>>>> drivers/mmc/host/sdhci-pci.h | 4 ++
>>>> drivers/mmc/host/sdhci.c | 13 ++++++
>>>> drivers/mmc/host/sdhci.h | 4 ++
>>>> include/linux/mmc/card.h | 2 +
>>>> include/linux/mmc/host.h | 4 +-
>>>> include/linux/mmc/mmc.h | 4 ++
>>>> include/linux/mmc/sdhci-pci-data.h | 2 +
>>>> 14 files changed, 240 insertions(+), 113 deletions(-)
>>>
>>> Hi Ulf
>>>
>>> These patches still apply. Would have time to look at them?
>>
>> Thanks for the reminder!
>>
>> I am walking through my backlog, but I don't want to give you any
>> promises about when, since I never seems to be able to keep them. :-)
>
> Hi
>
> Here's another reminder :-)
Thanks! :-)
>
> I would really like these patches and there is really not much to review.
>
> Patch 1 is quite trivial - only 1 line changed.
>
> Patch 2 is a change the select_drive_strength() host op to allow card driver
> strength to be different from host driver strength. It has no effect on
> current drivers.
>
> Patch 3 is just tidying up.
>
> Patch 4 is another change to the select_drive_strength() host op (to add
> 'card' as a parameter) and also has no effect on current drivers.
>
> Patch 5 is another tidy up.
>
> Patch 6 is a very small patch to add drive_strength to struct mmc_card.
>
> Patch 7 is a very small change to read eMMC supported driver strengths from
> EXT-CSD.
>
> Patch 8 adds driver strength selection for eMMC
>
> Patch 9, 10 implement the select_drive_strength() for Intel SPT with the
> sdhci-pci driver.
>
> Patch 11 finally just enables HS400 for Intel
>
> This shouldn't really take that long to review ;-)
No it didn't and it looks nice! Applied for next!
Thanks!
Kind regards
Uffe
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2015-05-25 8:44 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-06 12:12 [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 01/11] mmc: core: Reset driver type to default Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 02/11] mmc: core: Allow card drive strength to be different to host Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 03/11] mmc: core: Simplify card drive strength mask Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 04/11] mmc: core: Add 'card' to drive strength selection callback Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 05/11] mmc: core: Factor out common code in drive strength selection Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 06/11] mmc: core: Record card drive strength Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 07/11] mmc: mmc: Read card's valid driver strength mask Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 08/11] mmc: mmc: Add driver strength selection Adrian Hunter
2015-02-06 12:12 ` [PATCH V2 09/11] mmc: sdhci: Add a callback to select drive strength Adrian Hunter
2015-02-06 12:13 ` [PATCH V2 10/11] mmc: sdhci-pci: Add support for drive strength selection for SPT Adrian Hunter
2015-02-06 12:13 ` [PATCH V2 11/11] mmc: sdhci-pci: Enable HS400 for some Intel host controllers Adrian Hunter
2015-05-11 9:29 ` [PATCH V2 00/11] mmc: Add support for drive strength for eMMCs Adrian Hunter
2015-05-11 10:23 ` Ulf Hansson
2015-05-25 7:01 ` Adrian Hunter
2015-05-25 8:44 ` Ulf Hansson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox