* [PATCH v3] mmc: implement Driver Stage Register handling
@ 2014-08-13 15:44 ` Uwe Kleine-König
0 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2014-08-13 15:44 UTC (permalink / raw)
To: Chris Ball, Ulf Hansson
Cc: linux-mmc, kernel, Markus Niebel, linux-arm-kernel, devicetree,
Sascha Hauer
From: Sascha Hauer <s.hauer@pengutronix.de>
Some (e)MMC and SD cards implement a DSR register that allows to tune
raise/fall times and drive strength of the CMD and DATA outputs.
The values to use depend on the card in use and the host.
It might be needed to reduce the drive strength to prevent voltage peaks
above the host's specification.
Implement a 'dsr' devicetree property that allows to specify the value
to set the DSR to. For non-dt setups the new members of mmc_host can be
set by board code.
This patch was initially authored by Sascha Hauer. It contains
improvements authored by Markus Niebel and Uwe Kleine-König.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Markus Niebel <Markus.Niebel@tq-group.com>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
Hello,
earlier incarnations of this patch can be found at
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/272983.html
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/259281.html
I need this functionallity on a machine where the default driver strength of
the eMMC chip is too big for the SoC. It seems to work without adapting the
drive strength, but the vendor reports that the DSR should be set to a certain
value to prevent poor signal integrity and increased wearout.
Best regards
Uwe
Documentation/devicetree/bindings/mmc/mmc.txt | 2 ++
drivers/mmc/core/host.c | 8 ++++++++
drivers/mmc/core/mmc.c | 8 ++++++++
drivers/mmc/core/mmc_ops.c | 21 +++++++++++++++++++++
drivers/mmc/core/mmc_ops.h | 1 +
drivers/mmc/core/sd.c | 8 ++++++++
include/linux/mmc/card.h | 3 ++-
include/linux/mmc/host.h | 3 +++
8 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
index 3c18001dfd5d..05bac770b4d0 100644
--- a/Documentation/devicetree/bindings/mmc/mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc.txt
@@ -40,6 +40,8 @@ Optional properties:
- mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
- mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
- mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
+- dsr: Value the card's (optional) Driver Stage Register (DSR) should be
+ programmed with.
*NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
polarity properties, we have to fix the meaning of the "normal" and "inverted"
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 95cceae96944..52e83f389428 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -452,6 +452,14 @@ int mmc_of_parse(struct mmc_host *host)
if (of_find_property(np, "mmc-hs400-1_2v", &len))
host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
+ if (of_find_property(np, "dsr", &len)) {
+ u32 tmp;
+
+ of_property_read_u32(np, "dsr", &tmp);
+ host->dsr_req = 1;
+ host->dsr = (u16)tmp;
+ }
+
return 0;
out:
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 793c6f7ddb04..fdc1ac1360c4 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -162,6 +162,7 @@ static int mmc_decode_csd(struct mmc_card *card)
csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1);
csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
@@ -1273,6 +1274,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
}
/*
+ * handling only for cards supporting DSR and hosts requesting
+ * DSR configuration
+ */
+ if (card->csd.dsr_imp && host->dsr_req)
+ mmc_set_dsr(host);
+
+ /*
* Select card, as all following commands rely on that.
*/
if (!mmc_host_is_spi(host)) {
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index f51b5ba3bbea..37ed493d8030 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -93,6 +93,27 @@ int mmc_deselect_cards(struct mmc_host *host)
return _mmc_select_card(host, NULL);
}
+/*
+ * Write the value specified in the device tree or board code into the optional
+ * 16 bit Driver Stage Register. This can be used to tune raise/fall times and
+ * drive strength of the DAT and CMD outputs. The actual meaning of a given
+ * value is hardware dependant.
+ * The presence of the DSR register can be determined from the CSD register,
+ * bit 76.
+ */
+int mmc_set_dsr(struct mmc_host *host)
+{
+ int err;
+ struct mmc_command cmd = {0};
+
+ cmd.opcode = MMC_SET_DSR;
+
+ cmd.arg = ((u32)host->dsr << 16) | 0xffff;
+ cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
+
+ return mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+}
+
int mmc_go_idle(struct mmc_host *host)
{
int err;
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index 80ae9f4e0293..390dac665b2a 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -14,6 +14,7 @@
int mmc_select_card(struct mmc_card *card);
int mmc_deselect_cards(struct mmc_host *host);
+int mmc_set_dsr(struct mmc_host *host);
int mmc_go_idle(struct mmc_host *host);
int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
int mmc_all_send_cid(struct mmc_host *host, u32 *cid);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 0c44510bf717..25913889cbaa 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -127,6 +127,7 @@ static int mmc_decode_csd(struct mmc_card *card)
csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1);
csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
@@ -954,6 +955,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
}
/*
+ * handling only for cards supporting DSR and hosts requesting
+ * DSR configuration
+ */
+ if (card->csd.dsr_imp && host->dsr_req)
+ mmc_set_dsr(host);
+
+ /*
* Select card, as all following commands rely on that.
*/
if (!mmc_host_is_spi(host)) {
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index d424b9de3aff..680a7f0188bb 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -42,7 +42,8 @@ struct mmc_csd {
unsigned int read_partial:1,
read_misalign:1,
write_partial:1,
- write_misalign:1;
+ write_misalign:1,
+ dsr_imp:1;
};
struct mmc_ext_csd {
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 7960424d0bc0..9e9ad7b31bb9 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -319,6 +319,7 @@ struct mmc_host {
#ifdef CONFIG_MMC_DEBUG
unsigned int removed:1; /* host is being removed */
#endif
+ unsigned int dsr_req:1; /* DSR is requested for Host */
int rescan_disable; /* disable card detection */
int rescan_entered; /* used with nonremovable devices */
@@ -365,6 +366,8 @@ struct mmc_host {
unsigned int slotno; /* used for sdio acpi binding */
+ u16 dsr; /* optional driver stage (dsr) value */
+
unsigned long private[0] ____cacheline_aligned;
};
--
2.0.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3] mmc: implement Driver Stage Register handling
@ 2014-08-13 15:44 ` Uwe Kleine-König
0 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2014-08-13 15:44 UTC (permalink / raw)
To: linux-arm-kernel
From: Sascha Hauer <s.hauer@pengutronix.de>
Some (e)MMC and SD cards implement a DSR register that allows to tune
raise/fall times and drive strength of the CMD and DATA outputs.
The values to use depend on the card in use and the host.
It might be needed to reduce the drive strength to prevent voltage peaks
above the host's specification.
Implement a 'dsr' devicetree property that allows to specify the value
to set the DSR to. For non-dt setups the new members of mmc_host can be
set by board code.
This patch was initially authored by Sascha Hauer. It contains
improvements authored by Markus Niebel and Uwe Kleine-K?nig.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Markus Niebel <Markus.Niebel@tq-group.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
Hello,
earlier incarnations of this patch can be found at
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/272983.html
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/259281.html
I need this functionallity on a machine where the default driver strength of
the eMMC chip is too big for the SoC. It seems to work without adapting the
drive strength, but the vendor reports that the DSR should be set to a certain
value to prevent poor signal integrity and increased wearout.
Best regards
Uwe
Documentation/devicetree/bindings/mmc/mmc.txt | 2 ++
drivers/mmc/core/host.c | 8 ++++++++
drivers/mmc/core/mmc.c | 8 ++++++++
drivers/mmc/core/mmc_ops.c | 21 +++++++++++++++++++++
drivers/mmc/core/mmc_ops.h | 1 +
drivers/mmc/core/sd.c | 8 ++++++++
include/linux/mmc/card.h | 3 ++-
include/linux/mmc/host.h | 3 +++
8 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
index 3c18001dfd5d..05bac770b4d0 100644
--- a/Documentation/devicetree/bindings/mmc/mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc.txt
@@ -40,6 +40,8 @@ Optional properties:
- mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
- mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
- mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
+- dsr: Value the card's (optional) Driver Stage Register (DSR) should be
+ programmed with.
*NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
polarity properties, we have to fix the meaning of the "normal" and "inverted"
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 95cceae96944..52e83f389428 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -452,6 +452,14 @@ int mmc_of_parse(struct mmc_host *host)
if (of_find_property(np, "mmc-hs400-1_2v", &len))
host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
+ if (of_find_property(np, "dsr", &len)) {
+ u32 tmp;
+
+ of_property_read_u32(np, "dsr", &tmp);
+ host->dsr_req = 1;
+ host->dsr = (u16)tmp;
+ }
+
return 0;
out:
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 793c6f7ddb04..fdc1ac1360c4 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -162,6 +162,7 @@ static int mmc_decode_csd(struct mmc_card *card)
csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1);
csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
@@ -1273,6 +1274,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
}
/*
+ * handling only for cards supporting DSR and hosts requesting
+ * DSR configuration
+ */
+ if (card->csd.dsr_imp && host->dsr_req)
+ mmc_set_dsr(host);
+
+ /*
* Select card, as all following commands rely on that.
*/
if (!mmc_host_is_spi(host)) {
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index f51b5ba3bbea..37ed493d8030 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -93,6 +93,27 @@ int mmc_deselect_cards(struct mmc_host *host)
return _mmc_select_card(host, NULL);
}
+/*
+ * Write the value specified in the device tree or board code into the optional
+ * 16 bit Driver Stage Register. This can be used to tune raise/fall times and
+ * drive strength of the DAT and CMD outputs. The actual meaning of a given
+ * value is hardware dependant.
+ * The presence of the DSR register can be determined from the CSD register,
+ * bit 76.
+ */
+int mmc_set_dsr(struct mmc_host *host)
+{
+ int err;
+ struct mmc_command cmd = {0};
+
+ cmd.opcode = MMC_SET_DSR;
+
+ cmd.arg = ((u32)host->dsr << 16) | 0xffff;
+ cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
+
+ return mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+}
+
int mmc_go_idle(struct mmc_host *host)
{
int err;
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index 80ae9f4e0293..390dac665b2a 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -14,6 +14,7 @@
int mmc_select_card(struct mmc_card *card);
int mmc_deselect_cards(struct mmc_host *host);
+int mmc_set_dsr(struct mmc_host *host);
int mmc_go_idle(struct mmc_host *host);
int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
int mmc_all_send_cid(struct mmc_host *host, u32 *cid);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 0c44510bf717..25913889cbaa 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -127,6 +127,7 @@ static int mmc_decode_csd(struct mmc_card *card)
csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1);
csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
@@ -954,6 +955,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
}
/*
+ * handling only for cards supporting DSR and hosts requesting
+ * DSR configuration
+ */
+ if (card->csd.dsr_imp && host->dsr_req)
+ mmc_set_dsr(host);
+
+ /*
* Select card, as all following commands rely on that.
*/
if (!mmc_host_is_spi(host)) {
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index d424b9de3aff..680a7f0188bb 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -42,7 +42,8 @@ struct mmc_csd {
unsigned int read_partial:1,
read_misalign:1,
write_partial:1,
- write_misalign:1;
+ write_misalign:1,
+ dsr_imp:1;
};
struct mmc_ext_csd {
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 7960424d0bc0..9e9ad7b31bb9 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -319,6 +319,7 @@ struct mmc_host {
#ifdef CONFIG_MMC_DEBUG
unsigned int removed:1; /* host is being removed */
#endif
+ unsigned int dsr_req:1; /* DSR is requested for Host */
int rescan_disable; /* disable card detection */
int rescan_entered; /* used with nonremovable devices */
@@ -365,6 +366,8 @@ struct mmc_host {
unsigned int slotno; /* used for sdio acpi binding */
+ u16 dsr; /* optional driver stage (dsr) value */
+
unsigned long private[0] ____cacheline_aligned;
};
--
2.0.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v3] mmc: implement Driver Stage Register handling
2014-08-13 15:44 ` Uwe Kleine-König
@ 2014-08-13 15:57 ` Uwe Kleine-König
-1 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2014-08-13 15:57 UTC (permalink / raw)
To: Chris Ball, Ulf Hansson
Cc: linux-mmc, kernel, Markus Niebel, linux-arm-kernel, devicetree,
Sascha Hauer
Hello,
On Wed, Aug 13, 2014 at 05:44:16PM +0200, Uwe Kleine-König wrote:
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index f51b5ba3bbea..37ed493d8030 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -93,6 +93,27 @@ int mmc_deselect_cards(struct mmc_host *host)
> return _mmc_select_card(host, NULL);
> }
>
> +/*
> + * Write the value specified in the device tree or board code into the optional
> + * 16 bit Driver Stage Register. This can be used to tune raise/fall times and
> + * drive strength of the DAT and CMD outputs. The actual meaning of a given
> + * value is hardware dependant.
> + * The presence of the DSR register can be determined from the CSD register,
> + * bit 76.
> + */
> +int mmc_set_dsr(struct mmc_host *host)
> +{
> + int err;
The line declaring err can and should be dropped. I found that during my
tests, but failed to change this in the patch before sending it out.
If you consider applying my patch, please fix this up. If not I will
take this as an opportunity to remind you in a few days with a v4 :-)
Uwe
> + struct mmc_command cmd = {0};
> +
> + cmd.opcode = MMC_SET_DSR;
> +
> + cmd.arg = ((u32)host->dsr << 16) | 0xffff;
> + cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
> +
> + return mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
> +}
> +
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3] mmc: implement Driver Stage Register handling
@ 2014-08-13 15:57 ` Uwe Kleine-König
0 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2014-08-13 15:57 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
On Wed, Aug 13, 2014 at 05:44:16PM +0200, Uwe Kleine-K?nig wrote:
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index f51b5ba3bbea..37ed493d8030 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -93,6 +93,27 @@ int mmc_deselect_cards(struct mmc_host *host)
> return _mmc_select_card(host, NULL);
> }
>
> +/*
> + * Write the value specified in the device tree or board code into the optional
> + * 16 bit Driver Stage Register. This can be used to tune raise/fall times and
> + * drive strength of the DAT and CMD outputs. The actual meaning of a given
> + * value is hardware dependant.
> + * The presence of the DSR register can be determined from the CSD register,
> + * bit 76.
> + */
> +int mmc_set_dsr(struct mmc_host *host)
> +{
> + int err;
The line declaring err can and should be dropped. I found that during my
tests, but failed to change this in the patch before sending it out.
If you consider applying my patch, please fix this up. If not I will
take this as an opportunity to remind you in a few days with a v4 :-)
Uwe
> + struct mmc_command cmd = {0};
> +
> + cmd.opcode = MMC_SET_DSR;
> +
> + cmd.arg = ((u32)host->dsr << 16) | 0xffff;
> + cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
> +
> + return mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
> +}
> +
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3] mmc: implement Driver Stage Register handling
2014-08-13 15:44 ` Uwe Kleine-König
@ 2014-08-14 9:26 ` Ulf Hansson
-1 siblings, 0 replies; 12+ messages in thread
From: Ulf Hansson @ 2014-08-14 9:26 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Chris Ball, linux-mmc, Sascha Hauer, Markus Niebel,
linux-arm-kernel, devicetree, Sascha Hauer
On 13 August 2014 17:44, Uwe Kleine-König
<u.kleine-koenig@pengutronix.de> wrote:
> From: Sascha Hauer <s.hauer@pengutronix.de>
>
> Some (e)MMC and SD cards implement a DSR register that allows to tune
> raise/fall times and drive strength of the CMD and DATA outputs.
> The values to use depend on the card in use and the host.
> It might be needed to reduce the drive strength to prevent voltage peaks
> above the host's specification.
>
> Implement a 'dsr' devicetree property that allows to specify the value
> to set the DSR to. For non-dt setups the new members of mmc_host can be
> set by board code.
>
> This patch was initially authored by Sascha Hauer. It contains
> improvements authored by Markus Niebel and Uwe Kleine-König.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Signed-off-by: Markus Niebel <Markus.Niebel@tq-group.com>
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
> Hello,
>
> earlier incarnations of this patch can be found at
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/272983.html
> http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/259281.html
>
> I need this functionallity on a machine where the default driver strength of
> the eMMC chip is too big for the SoC. It seems to work without adapting the
> drive strength, but the vendor reports that the DSR should be set to a certain
> value to prevent poor signal integrity and increased wearout.
>
> Best regards
> Uwe
>
> Documentation/devicetree/bindings/mmc/mmc.txt | 2 ++
> drivers/mmc/core/host.c | 8 ++++++++
> drivers/mmc/core/mmc.c | 8 ++++++++
> drivers/mmc/core/mmc_ops.c | 21 +++++++++++++++++++++
> drivers/mmc/core/mmc_ops.h | 1 +
> drivers/mmc/core/sd.c | 8 ++++++++
> include/linux/mmc/card.h | 3 ++-
> include/linux/mmc/host.h | 3 +++
> 8 files changed, 53 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
> index 3c18001dfd5d..05bac770b4d0 100644
> --- a/Documentation/devicetree/bindings/mmc/mmc.txt
> +++ b/Documentation/devicetree/bindings/mmc/mmc.txt
> @@ -40,6 +40,8 @@ Optional properties:
> - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
> - mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
> - mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
> +- dsr: Value the card's (optional) Driver Stage Register (DSR) should be
> + programmed with.
Let's clarify that this is a 16 bit value.
>
> *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
> polarity properties, we have to fix the meaning of the "normal" and "inverted"
> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> index 95cceae96944..52e83f389428 100644
> --- a/drivers/mmc/core/host.c
> +++ b/drivers/mmc/core/host.c
> @@ -452,6 +452,14 @@ int mmc_of_parse(struct mmc_host *host)
> if (of_find_property(np, "mmc-hs400-1_2v", &len))
> host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
>
> + if (of_find_property(np, "dsr", &len)) {
> + u32 tmp;
> +
> + of_property_read_u32(np, "dsr", &tmp);
> + host->dsr_req = 1;
> + host->dsr = (u16)tmp;
> + }
> +
Let's simplify the above with just:
of_property_read_u16(np, "dsr", &host->dsr);
> return 0;
>
> out:
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 793c6f7ddb04..fdc1ac1360c4 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -162,6 +162,7 @@ static int mmc_decode_csd(struct mmc_card *card)
> csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
> csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
> csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
> + csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1);
> csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
> csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
> csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
> @@ -1273,6 +1274,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
> }
>
> /*
> + * handling only for cards supporting DSR and hosts requesting
> + * DSR configuration
> + */
> + if (card->csd.dsr_imp && host->dsr_req)
We don't need host->dsr_req. Instead just check host->dsr.
> + mmc_set_dsr(host);
> +
> + /*
> * Select card, as all following commands rely on that.
> */
> if (!mmc_host_is_spi(host)) {
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index f51b5ba3bbea..37ed493d8030 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -93,6 +93,27 @@ int mmc_deselect_cards(struct mmc_host *host)
> return _mmc_select_card(host, NULL);
> }
>
> +/*
> + * Write the value specified in the device tree or board code into the optional
> + * 16 bit Driver Stage Register. This can be used to tune raise/fall times and
> + * drive strength of the DAT and CMD outputs. The actual meaning of a given
> + * value is hardware dependant.
> + * The presence of the DSR register can be determined from the CSD register,
> + * bit 76.
> + */
> +int mmc_set_dsr(struct mmc_host *host)
> +{
> + int err;
> + struct mmc_command cmd = {0};
> +
> + cmd.opcode = MMC_SET_DSR;
> +
> + cmd.arg = ((u32)host->dsr << 16) | 0xffff;
> + cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
> +
> + return mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
> +}
> +
> int mmc_go_idle(struct mmc_host *host)
> {
> int err;
> diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
> index 80ae9f4e0293..390dac665b2a 100644
> --- a/drivers/mmc/core/mmc_ops.h
> +++ b/drivers/mmc/core/mmc_ops.h
> @@ -14,6 +14,7 @@
>
> int mmc_select_card(struct mmc_card *card);
> int mmc_deselect_cards(struct mmc_host *host);
> +int mmc_set_dsr(struct mmc_host *host);
> int mmc_go_idle(struct mmc_host *host);
> int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
> int mmc_all_send_cid(struct mmc_host *host, u32 *cid);
> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
> index 0c44510bf717..25913889cbaa 100644
> --- a/drivers/mmc/core/sd.c
> +++ b/drivers/mmc/core/sd.c
> @@ -127,6 +127,7 @@ static int mmc_decode_csd(struct mmc_card *card)
> csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
> csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
> csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
> + csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1);
> csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
> csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
> csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
> @@ -954,6 +955,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
> }
>
> /*
> + * handling only for cards supporting DSR and hosts requesting
> + * DSR configuration
> + */
> + if (card->csd.dsr_imp && host->dsr_req)
Check host->dsr instead.
> + mmc_set_dsr(host);
> +
> + /*
> * Select card, as all following commands rely on that.
> */
> if (!mmc_host_is_spi(host)) {
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index d424b9de3aff..680a7f0188bb 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -42,7 +42,8 @@ struct mmc_csd {
> unsigned int read_partial:1,
> read_misalign:1,
> write_partial:1,
> - write_misalign:1;
> + write_misalign:1,
> + dsr_imp:1;
> };
>
> struct mmc_ext_csd {
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index 7960424d0bc0..9e9ad7b31bb9 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -319,6 +319,7 @@ struct mmc_host {
> #ifdef CONFIG_MMC_DEBUG
> unsigned int removed:1; /* host is being removed */
> #endif
> + unsigned int dsr_req:1; /* DSR is requested for Host */
Remove dsr_req.
>
> int rescan_disable; /* disable card detection */
> int rescan_entered; /* used with nonremovable devices */
> @@ -365,6 +366,8 @@ struct mmc_host {
>
> unsigned int slotno; /* used for sdio acpi binding */
>
> + u16 dsr; /* optional driver stage (dsr) value */
> +
> unsigned long private[0] ____cacheline_aligned;
> };
>
> --
> 2.0.1
>
Kind regards
Uffe
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3] mmc: implement Driver Stage Register handling
@ 2014-08-14 9:26 ` Ulf Hansson
0 siblings, 0 replies; 12+ messages in thread
From: Ulf Hansson @ 2014-08-14 9:26 UTC (permalink / raw)
To: linux-arm-kernel
On 13 August 2014 17:44, Uwe Kleine-K?nig
<u.kleine-koenig@pengutronix.de> wrote:
> From: Sascha Hauer <s.hauer@pengutronix.de>
>
> Some (e)MMC and SD cards implement a DSR register that allows to tune
> raise/fall times and drive strength of the CMD and DATA outputs.
> The values to use depend on the card in use and the host.
> It might be needed to reduce the drive strength to prevent voltage peaks
> above the host's specification.
>
> Implement a 'dsr' devicetree property that allows to specify the value
> to set the DSR to. For non-dt setups the new members of mmc_host can be
> set by board code.
>
> This patch was initially authored by Sascha Hauer. It contains
> improvements authored by Markus Niebel and Uwe Kleine-K?nig.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Signed-off-by: Markus Niebel <Markus.Niebel@tq-group.com>
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> ---
> Hello,
>
> earlier incarnations of this patch can be found at
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/272983.html
> http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/259281.html
>
> I need this functionallity on a machine where the default driver strength of
> the eMMC chip is too big for the SoC. It seems to work without adapting the
> drive strength, but the vendor reports that the DSR should be set to a certain
> value to prevent poor signal integrity and increased wearout.
>
> Best regards
> Uwe
>
> Documentation/devicetree/bindings/mmc/mmc.txt | 2 ++
> drivers/mmc/core/host.c | 8 ++++++++
> drivers/mmc/core/mmc.c | 8 ++++++++
> drivers/mmc/core/mmc_ops.c | 21 +++++++++++++++++++++
> drivers/mmc/core/mmc_ops.h | 1 +
> drivers/mmc/core/sd.c | 8 ++++++++
> include/linux/mmc/card.h | 3 ++-
> include/linux/mmc/host.h | 3 +++
> 8 files changed, 53 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
> index 3c18001dfd5d..05bac770b4d0 100644
> --- a/Documentation/devicetree/bindings/mmc/mmc.txt
> +++ b/Documentation/devicetree/bindings/mmc/mmc.txt
> @@ -40,6 +40,8 @@ Optional properties:
> - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
> - mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
> - mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
> +- dsr: Value the card's (optional) Driver Stage Register (DSR) should be
> + programmed with.
Let's clarify that this is a 16 bit value.
>
> *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
> polarity properties, we have to fix the meaning of the "normal" and "inverted"
> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> index 95cceae96944..52e83f389428 100644
> --- a/drivers/mmc/core/host.c
> +++ b/drivers/mmc/core/host.c
> @@ -452,6 +452,14 @@ int mmc_of_parse(struct mmc_host *host)
> if (of_find_property(np, "mmc-hs400-1_2v", &len))
> host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
>
> + if (of_find_property(np, "dsr", &len)) {
> + u32 tmp;
> +
> + of_property_read_u32(np, "dsr", &tmp);
> + host->dsr_req = 1;
> + host->dsr = (u16)tmp;
> + }
> +
Let's simplify the above with just:
of_property_read_u16(np, "dsr", &host->dsr);
> return 0;
>
> out:
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 793c6f7ddb04..fdc1ac1360c4 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -162,6 +162,7 @@ static int mmc_decode_csd(struct mmc_card *card)
> csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
> csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
> csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
> + csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1);
> csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
> csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
> csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
> @@ -1273,6 +1274,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
> }
>
> /*
> + * handling only for cards supporting DSR and hosts requesting
> + * DSR configuration
> + */
> + if (card->csd.dsr_imp && host->dsr_req)
We don't need host->dsr_req. Instead just check host->dsr.
> + mmc_set_dsr(host);
> +
> + /*
> * Select card, as all following commands rely on that.
> */
> if (!mmc_host_is_spi(host)) {
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index f51b5ba3bbea..37ed493d8030 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -93,6 +93,27 @@ int mmc_deselect_cards(struct mmc_host *host)
> return _mmc_select_card(host, NULL);
> }
>
> +/*
> + * Write the value specified in the device tree or board code into the optional
> + * 16 bit Driver Stage Register. This can be used to tune raise/fall times and
> + * drive strength of the DAT and CMD outputs. The actual meaning of a given
> + * value is hardware dependant.
> + * The presence of the DSR register can be determined from the CSD register,
> + * bit 76.
> + */
> +int mmc_set_dsr(struct mmc_host *host)
> +{
> + int err;
> + struct mmc_command cmd = {0};
> +
> + cmd.opcode = MMC_SET_DSR;
> +
> + cmd.arg = ((u32)host->dsr << 16) | 0xffff;
> + cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
> +
> + return mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
> +}
> +
> int mmc_go_idle(struct mmc_host *host)
> {
> int err;
> diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
> index 80ae9f4e0293..390dac665b2a 100644
> --- a/drivers/mmc/core/mmc_ops.h
> +++ b/drivers/mmc/core/mmc_ops.h
> @@ -14,6 +14,7 @@
>
> int mmc_select_card(struct mmc_card *card);
> int mmc_deselect_cards(struct mmc_host *host);
> +int mmc_set_dsr(struct mmc_host *host);
> int mmc_go_idle(struct mmc_host *host);
> int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
> int mmc_all_send_cid(struct mmc_host *host, u32 *cid);
> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
> index 0c44510bf717..25913889cbaa 100644
> --- a/drivers/mmc/core/sd.c
> +++ b/drivers/mmc/core/sd.c
> @@ -127,6 +127,7 @@ static int mmc_decode_csd(struct mmc_card *card)
> csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
> csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
> csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
> + csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1);
> csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
> csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
> csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
> @@ -954,6 +955,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
> }
>
> /*
> + * handling only for cards supporting DSR and hosts requesting
> + * DSR configuration
> + */
> + if (card->csd.dsr_imp && host->dsr_req)
Check host->dsr instead.
> + mmc_set_dsr(host);
> +
> + /*
> * Select card, as all following commands rely on that.
> */
> if (!mmc_host_is_spi(host)) {
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index d424b9de3aff..680a7f0188bb 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -42,7 +42,8 @@ struct mmc_csd {
> unsigned int read_partial:1,
> read_misalign:1,
> write_partial:1,
> - write_misalign:1;
> + write_misalign:1,
> + dsr_imp:1;
> };
>
> struct mmc_ext_csd {
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index 7960424d0bc0..9e9ad7b31bb9 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -319,6 +319,7 @@ struct mmc_host {
> #ifdef CONFIG_MMC_DEBUG
> unsigned int removed:1; /* host is being removed */
> #endif
> + unsigned int dsr_req:1; /* DSR is requested for Host */
Remove dsr_req.
>
> int rescan_disable; /* disable card detection */
> int rescan_entered; /* used with nonremovable devices */
> @@ -365,6 +366,8 @@ struct mmc_host {
>
> unsigned int slotno; /* used for sdio acpi binding */
>
> + u16 dsr; /* optional driver stage (dsr) value */
> +
> unsigned long private[0] ____cacheline_aligned;
> };
>
> --
> 2.0.1
>
Kind regards
Uffe
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3] mmc: implement Driver Stage Register handling
2014-08-14 9:26 ` Ulf Hansson
@ 2014-08-14 9:49 ` Uwe Kleine-König
-1 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2014-08-14 9:49 UTC (permalink / raw)
To: Ulf Hansson
Cc: Chris Ball, linux-mmc, Sascha Hauer, Markus Niebel,
linux-arm-kernel, devicetree, Sascha Hauer
Hello Ulf,
On Thu, Aug 14, 2014 at 11:26:28AM +0200, Ulf Hansson wrote:
> On 13 August 2014 17:44, Uwe Kleine-König
> <u.kleine-koenig@pengutronix.de> wrote:
> > From: Sascha Hauer <s.hauer@pengutronix.de>
> >
> > Some (e)MMC and SD cards implement a DSR register that allows to tune
> > raise/fall times and drive strength of the CMD and DATA outputs.
> > The values to use depend on the card in use and the host.
> > It might be needed to reduce the drive strength to prevent voltage peaks
> > above the host's specification.
> >
> > Implement a 'dsr' devicetree property that allows to specify the value
> > to set the DSR to. For non-dt setups the new members of mmc_host can be
> > set by board code.
> >
> > This patch was initially authored by Sascha Hauer. It contains
> > improvements authored by Markus Niebel and Uwe Kleine-König.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > Signed-off-by: Markus Niebel <Markus.Niebel@tq-group.com>
> > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > ---
> > Hello,
> >
> > earlier incarnations of this patch can be found at
> >
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/272983.html
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/259281.html
> >
> > I need this functionallity on a machine where the default driver strength of
> > the eMMC chip is too big for the SoC. It seems to work without adapting the
> > drive strength, but the vendor reports that the DSR should be set to a certain
> > value to prevent poor signal integrity and increased wearout.
> >
> > Best regards
> > Uwe
> >
> > Documentation/devicetree/bindings/mmc/mmc.txt | 2 ++
> > drivers/mmc/core/host.c | 8 ++++++++
> > drivers/mmc/core/mmc.c | 8 ++++++++
> > drivers/mmc/core/mmc_ops.c | 21 +++++++++++++++++++++
> > drivers/mmc/core/mmc_ops.h | 1 +
> > drivers/mmc/core/sd.c | 8 ++++++++
> > include/linux/mmc/card.h | 3 ++-
> > include/linux/mmc/host.h | 3 +++
> > 8 files changed, 53 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
> > index 3c18001dfd5d..05bac770b4d0 100644
> > --- a/Documentation/devicetree/bindings/mmc/mmc.txt
> > +++ b/Documentation/devicetree/bindings/mmc/mmc.txt
> > @@ -40,6 +40,8 @@ Optional properties:
> > - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
> > - mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
> > - mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
> > +- dsr: Value the card's (optional) Driver Stage Register (DSR) should be
> > + programmed with.
>
> Let's clarify that this is a 16 bit value.
ok.
> > *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
> > polarity properties, we have to fix the meaning of the "normal" and "inverted"
> > diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> > index 95cceae96944..52e83f389428 100644
> > --- a/drivers/mmc/core/host.c
> > +++ b/drivers/mmc/core/host.c
> > @@ -452,6 +452,14 @@ int mmc_of_parse(struct mmc_host *host)
> > if (of_find_property(np, "mmc-hs400-1_2v", &len))
> > host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
> >
> > + if (of_find_property(np, "dsr", &len)) {
> > + u32 tmp;
> > +
> > + of_property_read_u32(np, "dsr", &tmp);
> > + host->dsr_req = 1;
> > + host->dsr = (u16)tmp;
> > + }
> > +
>
> Let's simplify the above with just:
> of_property_read_u16(np, "dsr", &host->dsr);
ok.
> > return 0;
> >
> > out:
> > diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> > index 793c6f7ddb04..fdc1ac1360c4 100644
> > --- a/drivers/mmc/core/mmc.c
> > +++ b/drivers/mmc/core/mmc.c
> > @@ -162,6 +162,7 @@ static int mmc_decode_csd(struct mmc_card *card)
> > csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
> > csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
> > csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
> > + csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1);
> > csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
> > csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
> > csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
> > @@ -1273,6 +1274,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
> > }
> >
> > /*
> > + * handling only for cards supporting DSR and hosts requesting
> > + * DSR configuration
> > + */
> > + if (card->csd.dsr_imp && host->dsr_req)
>
> We don't need host->dsr_req. Instead just check host->dsr.
I think this doesn't work. What is your actual suggestion?
if (card->csd.dsr_imp && host->dsr)
? The intended semantic is that if the device tree has:
dsr = <$somevalue>;
the DSR is written, and if there is no such property, DSR is unhandled.
If you just check for host->dsr being != 0, how to differenciate between
dsr = <0>;
in the device tree and dsr not being specified?
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3] mmc: implement Driver Stage Register handling
@ 2014-08-14 9:49 ` Uwe Kleine-König
0 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2014-08-14 9:49 UTC (permalink / raw)
To: linux-arm-kernel
Hello Ulf,
On Thu, Aug 14, 2014 at 11:26:28AM +0200, Ulf Hansson wrote:
> On 13 August 2014 17:44, Uwe Kleine-K?nig
> <u.kleine-koenig@pengutronix.de> wrote:
> > From: Sascha Hauer <s.hauer@pengutronix.de>
> >
> > Some (e)MMC and SD cards implement a DSR register that allows to tune
> > raise/fall times and drive strength of the CMD and DATA outputs.
> > The values to use depend on the card in use and the host.
> > It might be needed to reduce the drive strength to prevent voltage peaks
> > above the host's specification.
> >
> > Implement a 'dsr' devicetree property that allows to specify the value
> > to set the DSR to. For non-dt setups the new members of mmc_host can be
> > set by board code.
> >
> > This patch was initially authored by Sascha Hauer. It contains
> > improvements authored by Markus Niebel and Uwe Kleine-K?nig.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > Signed-off-by: Markus Niebel <Markus.Niebel@tq-group.com>
> > Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> > ---
> > Hello,
> >
> > earlier incarnations of this patch can be found at
> >
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/272983.html
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/259281.html
> >
> > I need this functionallity on a machine where the default driver strength of
> > the eMMC chip is too big for the SoC. It seems to work without adapting the
> > drive strength, but the vendor reports that the DSR should be set to a certain
> > value to prevent poor signal integrity and increased wearout.
> >
> > Best regards
> > Uwe
> >
> > Documentation/devicetree/bindings/mmc/mmc.txt | 2 ++
> > drivers/mmc/core/host.c | 8 ++++++++
> > drivers/mmc/core/mmc.c | 8 ++++++++
> > drivers/mmc/core/mmc_ops.c | 21 +++++++++++++++++++++
> > drivers/mmc/core/mmc_ops.h | 1 +
> > drivers/mmc/core/sd.c | 8 ++++++++
> > include/linux/mmc/card.h | 3 ++-
> > include/linux/mmc/host.h | 3 +++
> > 8 files changed, 53 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
> > index 3c18001dfd5d..05bac770b4d0 100644
> > --- a/Documentation/devicetree/bindings/mmc/mmc.txt
> > +++ b/Documentation/devicetree/bindings/mmc/mmc.txt
> > @@ -40,6 +40,8 @@ Optional properties:
> > - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
> > - mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
> > - mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
> > +- dsr: Value the card's (optional) Driver Stage Register (DSR) should be
> > + programmed with.
>
> Let's clarify that this is a 16 bit value.
ok.
> > *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
> > polarity properties, we have to fix the meaning of the "normal" and "inverted"
> > diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> > index 95cceae96944..52e83f389428 100644
> > --- a/drivers/mmc/core/host.c
> > +++ b/drivers/mmc/core/host.c
> > @@ -452,6 +452,14 @@ int mmc_of_parse(struct mmc_host *host)
> > if (of_find_property(np, "mmc-hs400-1_2v", &len))
> > host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
> >
> > + if (of_find_property(np, "dsr", &len)) {
> > + u32 tmp;
> > +
> > + of_property_read_u32(np, "dsr", &tmp);
> > + host->dsr_req = 1;
> > + host->dsr = (u16)tmp;
> > + }
> > +
>
> Let's simplify the above with just:
> of_property_read_u16(np, "dsr", &host->dsr);
ok.
> > return 0;
> >
> > out:
> > diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> > index 793c6f7ddb04..fdc1ac1360c4 100644
> > --- a/drivers/mmc/core/mmc.c
> > +++ b/drivers/mmc/core/mmc.c
> > @@ -162,6 +162,7 @@ static int mmc_decode_csd(struct mmc_card *card)
> > csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
> > csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
> > csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
> > + csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1);
> > csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
> > csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
> > csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
> > @@ -1273,6 +1274,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
> > }
> >
> > /*
> > + * handling only for cards supporting DSR and hosts requesting
> > + * DSR configuration
> > + */
> > + if (card->csd.dsr_imp && host->dsr_req)
>
> We don't need host->dsr_req. Instead just check host->dsr.
I think this doesn't work. What is your actual suggestion?
if (card->csd.dsr_imp && host->dsr)
? The intended semantic is that if the device tree has:
dsr = <$somevalue>;
the DSR is written, and if there is no such property, DSR is unhandled.
If you just check for host->dsr being != 0, how to differenciate between
dsr = <0>;
in the device tree and dsr not being specified?
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3] mmc: implement Driver Stage Register handling
2014-08-14 9:49 ` Uwe Kleine-König
@ 2014-08-14 10:29 ` Ulf Hansson
-1 siblings, 0 replies; 12+ messages in thread
From: Ulf Hansson @ 2014-08-14 10:29 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Chris Ball, linux-mmc, Sascha Hauer, Markus Niebel,
linux-arm-kernel, devicetree, Sascha Hauer
On 14 August 2014 11:49, Uwe Kleine-König
<u.kleine-koenig@pengutronix.de> wrote:
> Hello Ulf,
>
> On Thu, Aug 14, 2014 at 11:26:28AM +0200, Ulf Hansson wrote:
>> On 13 August 2014 17:44, Uwe Kleine-König
>> <u.kleine-koenig@pengutronix.de> wrote:
>> > From: Sascha Hauer <s.hauer@pengutronix.de>
>> >
>> > Some (e)MMC and SD cards implement a DSR register that allows to tune
>> > raise/fall times and drive strength of the CMD and DATA outputs.
>> > The values to use depend on the card in use and the host.
>> > It might be needed to reduce the drive strength to prevent voltage peaks
>> > above the host's specification.
>> >
>> > Implement a 'dsr' devicetree property that allows to specify the value
>> > to set the DSR to. For non-dt setups the new members of mmc_host can be
>> > set by board code.
>> >
>> > This patch was initially authored by Sascha Hauer. It contains
>> > improvements authored by Markus Niebel and Uwe Kleine-König.
>> >
>> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
>> > Signed-off-by: Markus Niebel <Markus.Niebel@tq-group.com>
>> > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
>> > ---
>> > Hello,
>> >
>> > earlier incarnations of this patch can be found at
>> >
>> > http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/272983.html
>> > http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/259281.html
>> >
>> > I need this functionallity on a machine where the default driver strength of
>> > the eMMC chip is too big for the SoC. It seems to work without adapting the
>> > drive strength, but the vendor reports that the DSR should be set to a certain
>> > value to prevent poor signal integrity and increased wearout.
>> >
>> > Best regards
>> > Uwe
>> >
>> > Documentation/devicetree/bindings/mmc/mmc.txt | 2 ++
>> > drivers/mmc/core/host.c | 8 ++++++++
>> > drivers/mmc/core/mmc.c | 8 ++++++++
>> > drivers/mmc/core/mmc_ops.c | 21 +++++++++++++++++++++
>> > drivers/mmc/core/mmc_ops.h | 1 +
>> > drivers/mmc/core/sd.c | 8 ++++++++
>> > include/linux/mmc/card.h | 3 ++-
>> > include/linux/mmc/host.h | 3 +++
>> > 8 files changed, 53 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
>> > index 3c18001dfd5d..05bac770b4d0 100644
>> > --- a/Documentation/devicetree/bindings/mmc/mmc.txt
>> > +++ b/Documentation/devicetree/bindings/mmc/mmc.txt
>> > @@ -40,6 +40,8 @@ Optional properties:
>> > - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
>> > - mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
>> > - mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
>> > +- dsr: Value the card's (optional) Driver Stage Register (DSR) should be
>> > + programmed with.
>>
>> Let's clarify that this is a 16 bit value.
> ok.
>
>> > *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
>> > polarity properties, we have to fix the meaning of the "normal" and "inverted"
>> > diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
>> > index 95cceae96944..52e83f389428 100644
>> > --- a/drivers/mmc/core/host.c
>> > +++ b/drivers/mmc/core/host.c
>> > @@ -452,6 +452,14 @@ int mmc_of_parse(struct mmc_host *host)
>> > if (of_find_property(np, "mmc-hs400-1_2v", &len))
>> > host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
>> >
>> > + if (of_find_property(np, "dsr", &len)) {
>> > + u32 tmp;
>> > +
>> > + of_property_read_u32(np, "dsr", &tmp);
>> > + host->dsr_req = 1;
>> > + host->dsr = (u16)tmp;
>> > + }
>> > +
>>
>> Let's simplify the above with just:
>> of_property_read_u16(np, "dsr", &host->dsr);
> ok.
>
>> > return 0;
>> >
>> > out:
>> > diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>> > index 793c6f7ddb04..fdc1ac1360c4 100644
>> > --- a/drivers/mmc/core/mmc.c
>> > +++ b/drivers/mmc/core/mmc.c
>> > @@ -162,6 +162,7 @@ static int mmc_decode_csd(struct mmc_card *card)
>> > csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
>> > csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
>> > csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
>> > + csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1);
>> > csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
>> > csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
>> > csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
>> > @@ -1273,6 +1274,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
>> > }
>> >
>> > /*
>> > + * handling only for cards supporting DSR and hosts requesting
>> > + * DSR configuration
>> > + */
>> > + if (card->csd.dsr_imp && host->dsr_req)
>>
>> We don't need host->dsr_req. Instead just check host->dsr.
> I think this doesn't work. What is your actual suggestion?
>
> if (card->csd.dsr_imp && host->dsr)
>
> ? The intended semantic is that if the device tree has:
>
> dsr = <$somevalue>;
>
> the DSR is written, and if there is no such property, DSR is unhandled.
> If you just check for host->dsr being != 0, how to differenciate between
>
> dsr = <0>;
I didn't think that was a valid mask? If so, you right!
Kind regards
Uffe
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3] mmc: implement Driver Stage Register handling
@ 2014-08-14 10:29 ` Ulf Hansson
0 siblings, 0 replies; 12+ messages in thread
From: Ulf Hansson @ 2014-08-14 10:29 UTC (permalink / raw)
To: linux-arm-kernel
On 14 August 2014 11:49, Uwe Kleine-K?nig
<u.kleine-koenig@pengutronix.de> wrote:
> Hello Ulf,
>
> On Thu, Aug 14, 2014 at 11:26:28AM +0200, Ulf Hansson wrote:
>> On 13 August 2014 17:44, Uwe Kleine-K?nig
>> <u.kleine-koenig@pengutronix.de> wrote:
>> > From: Sascha Hauer <s.hauer@pengutronix.de>
>> >
>> > Some (e)MMC and SD cards implement a DSR register that allows to tune
>> > raise/fall times and drive strength of the CMD and DATA outputs.
>> > The values to use depend on the card in use and the host.
>> > It might be needed to reduce the drive strength to prevent voltage peaks
>> > above the host's specification.
>> >
>> > Implement a 'dsr' devicetree property that allows to specify the value
>> > to set the DSR to. For non-dt setups the new members of mmc_host can be
>> > set by board code.
>> >
>> > This patch was initially authored by Sascha Hauer. It contains
>> > improvements authored by Markus Niebel and Uwe Kleine-K?nig.
>> >
>> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
>> > Signed-off-by: Markus Niebel <Markus.Niebel@tq-group.com>
>> > Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
>> > ---
>> > Hello,
>> >
>> > earlier incarnations of this patch can be found at
>> >
>> > http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/272983.html
>> > http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/259281.html
>> >
>> > I need this functionallity on a machine where the default driver strength of
>> > the eMMC chip is too big for the SoC. It seems to work without adapting the
>> > drive strength, but the vendor reports that the DSR should be set to a certain
>> > value to prevent poor signal integrity and increased wearout.
>> >
>> > Best regards
>> > Uwe
>> >
>> > Documentation/devicetree/bindings/mmc/mmc.txt | 2 ++
>> > drivers/mmc/core/host.c | 8 ++++++++
>> > drivers/mmc/core/mmc.c | 8 ++++++++
>> > drivers/mmc/core/mmc_ops.c | 21 +++++++++++++++++++++
>> > drivers/mmc/core/mmc_ops.h | 1 +
>> > drivers/mmc/core/sd.c | 8 ++++++++
>> > include/linux/mmc/card.h | 3 ++-
>> > include/linux/mmc/host.h | 3 +++
>> > 8 files changed, 53 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
>> > index 3c18001dfd5d..05bac770b4d0 100644
>> > --- a/Documentation/devicetree/bindings/mmc/mmc.txt
>> > +++ b/Documentation/devicetree/bindings/mmc/mmc.txt
>> > @@ -40,6 +40,8 @@ Optional properties:
>> > - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
>> > - mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
>> > - mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
>> > +- dsr: Value the card's (optional) Driver Stage Register (DSR) should be
>> > + programmed with.
>>
>> Let's clarify that this is a 16 bit value.
> ok.
>
>> > *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
>> > polarity properties, we have to fix the meaning of the "normal" and "inverted"
>> > diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
>> > index 95cceae96944..52e83f389428 100644
>> > --- a/drivers/mmc/core/host.c
>> > +++ b/drivers/mmc/core/host.c
>> > @@ -452,6 +452,14 @@ int mmc_of_parse(struct mmc_host *host)
>> > if (of_find_property(np, "mmc-hs400-1_2v", &len))
>> > host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
>> >
>> > + if (of_find_property(np, "dsr", &len)) {
>> > + u32 tmp;
>> > +
>> > + of_property_read_u32(np, "dsr", &tmp);
>> > + host->dsr_req = 1;
>> > + host->dsr = (u16)tmp;
>> > + }
>> > +
>>
>> Let's simplify the above with just:
>> of_property_read_u16(np, "dsr", &host->dsr);
> ok.
>
>> > return 0;
>> >
>> > out:
>> > diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>> > index 793c6f7ddb04..fdc1ac1360c4 100644
>> > --- a/drivers/mmc/core/mmc.c
>> > +++ b/drivers/mmc/core/mmc.c
>> > @@ -162,6 +162,7 @@ static int mmc_decode_csd(struct mmc_card *card)
>> > csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
>> > csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
>> > csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
>> > + csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1);
>> > csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
>> > csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
>> > csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
>> > @@ -1273,6 +1274,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
>> > }
>> >
>> > /*
>> > + * handling only for cards supporting DSR and hosts requesting
>> > + * DSR configuration
>> > + */
>> > + if (card->csd.dsr_imp && host->dsr_req)
>>
>> We don't need host->dsr_req. Instead just check host->dsr.
> I think this doesn't work. What is your actual suggestion?
>
> if (card->csd.dsr_imp && host->dsr)
>
> ? The intended semantic is that if the device tree has:
>
> dsr = <$somevalue>;
>
> the DSR is written, and if there is no such property, DSR is unhandled.
> If you just check for host->dsr being != 0, how to differenciate between
>
> dsr = <0>;
I didn't think that was a valid mask? If so, you right!
Kind regards
Uffe
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3] mmc: implement Driver Stage Register handling
2014-08-14 9:26 ` Ulf Hansson
@ 2014-08-15 8:21 ` Uwe Kleine-König
-1 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2014-08-15 8:21 UTC (permalink / raw)
To: Ulf Hansson
Cc: Chris Ball, linux-mmc, Sascha Hauer, Markus Niebel,
linux-arm-kernel, devicetree, Sascha Hauer
Hello Ulf,
On Thu, Aug 14, 2014 at 11:26:28AM +0200, Ulf Hansson wrote:
> > diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> > index 95cceae96944..52e83f389428 100644
> > --- a/drivers/mmc/core/host.c
> > +++ b/drivers/mmc/core/host.c
> > @@ -452,6 +452,14 @@ int mmc_of_parse(struct mmc_host *host)
> > if (of_find_property(np, "mmc-hs400-1_2v", &len))
> > host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
> >
> > + if (of_find_property(np, "dsr", &len)) {
> > + u32 tmp;
> > +
> > + of_property_read_u32(np, "dsr", &tmp);
> > + host->dsr_req = 1;
> > + host->dsr = (u16)tmp;
> > + }
> > +
>
> Let's simplify the above with just:
> of_property_read_u16(np, "dsr", &host->dsr);
The downside here is that the syntax changes when using
of_property_read_u16. Instead of
dsr = <0x100>
the following must be written then:
dsr = /bits/ 16 <0x100>;
so I'd prefer to stay with of_property_read_u32. The block can still be
simplified. Will fix that in v4.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3] mmc: implement Driver Stage Register handling
@ 2014-08-15 8:21 ` Uwe Kleine-König
0 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2014-08-15 8:21 UTC (permalink / raw)
To: linux-arm-kernel
Hello Ulf,
On Thu, Aug 14, 2014 at 11:26:28AM +0200, Ulf Hansson wrote:
> > diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> > index 95cceae96944..52e83f389428 100644
> > --- a/drivers/mmc/core/host.c
> > +++ b/drivers/mmc/core/host.c
> > @@ -452,6 +452,14 @@ int mmc_of_parse(struct mmc_host *host)
> > if (of_find_property(np, "mmc-hs400-1_2v", &len))
> > host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
> >
> > + if (of_find_property(np, "dsr", &len)) {
> > + u32 tmp;
> > +
> > + of_property_read_u32(np, "dsr", &tmp);
> > + host->dsr_req = 1;
> > + host->dsr = (u16)tmp;
> > + }
> > +
>
> Let's simplify the above with just:
> of_property_read_u16(np, "dsr", &host->dsr);
The downside here is that the syntax changes when using
of_property_read_u16. Instead of
dsr = <0x100>
the following must be written then:
dsr = /bits/ 16 <0x100>;
so I'd prefer to stay with of_property_read_u32. The block can still be
simplified. Will fix that in v4.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2014-08-15 8:21 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-13 15:44 [PATCH v3] mmc: implement Driver Stage Register handling Uwe Kleine-König
2014-08-13 15:44 ` Uwe Kleine-König
2014-08-13 15:57 ` Uwe Kleine-König
2014-08-13 15:57 ` Uwe Kleine-König
2014-08-14 9:26 ` Ulf Hansson
2014-08-14 9:26 ` Ulf Hansson
2014-08-14 9:49 ` Uwe Kleine-König
2014-08-14 9:49 ` Uwe Kleine-König
2014-08-14 10:29 ` Ulf Hansson
2014-08-14 10:29 ` Ulf Hansson
2014-08-15 8:21 ` Uwe Kleine-König
2014-08-15 8:21 ` Uwe Kleine-König
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.