* [PATCH 1/5] mmc: sdhci-esdhc-imx: add support for write protect on custom GPIO
2011-02-10 19:14 [PATCH 0/5] sdhci-esdhc-imx: use gpio for write protection and card detection Wolfram Sang
@ 2011-02-10 19:14 ` Wolfram Sang
2011-02-10 22:24 ` Marc Reilly
2011-02-10 19:14 ` [PATCH 2/5] mmc: sdhci-esdhc: broken card detection is not a default quirk Wolfram Sang
` (3 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Wolfram Sang @ 2011-02-10 19:14 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
arch/arm/plat-mxc/include/mach/esdhc.h | 10 +++++-
drivers/mmc/host/sdhci-esdhc-imx.c | 51 +++++++++++++++++++++++++-------
2 files changed, 49 insertions(+), 12 deletions(-)
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
index a48a9aa..dbf6d56 100644
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -10,7 +10,15 @@
#ifndef __ASM_ARCH_IMX_ESDHC_H
#define __ASM_ARCH_IMX_ESDHC_H
+/**
+ * struct esdhc_platform_data - optional platform data for esdhc on i.MX
+ *
+ * strongly recommended for i.MX25/35, not needed for other variants
+ *
+ * @wp_gpio: gpio for write_protect
+ */
+
struct esdhc_platform_data {
- unsigned int wp_gpio; /* write protect pin */
+ unsigned int wp_gpio;
};
#endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 9b82910..83d178b 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -15,9 +15,11 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/gpio.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdhci-pltfm.h>
#include <mach/hardware.h>
+#include <mach/esdhc.h>
#include "sdhci.h"
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
@@ -100,10 +102,31 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
return clk_get_rate(pltfm_host->clk) / 256 / 16;
}
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+ struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+
+ if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+ return gpio_get_value(boarddata->wp_gpio);
+ else
+ return -ENOSYS;
+}
+
+static struct sdhci_ops sdhci_esdhc_ops = {
+ .read_w = esdhc_readw_le,
+ .write_w = esdhc_writew_le,
+ .write_b = esdhc_writeb_le,
+ .set_clock = esdhc_set_clock,
+ .get_max_clock = esdhc_pltfm_get_max_clock,
+ .get_min_clock = esdhc_pltfm_get_min_clock,
+};
+
static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
struct clk *clk;
+ int err;
clk = clk_get(mmc_dev(host->mmc), NULL);
if (IS_ERR(clk)) {
@@ -116,9 +139,20 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
if (cpu_is_mx35() || cpu_is_mx51())
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
- /* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */
- if (cpu_is_mx25() || cpu_is_mx35())
+ if (cpu_is_mx25() || cpu_is_mx35()) {
+ /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+ /* write_protect can't be routed to controller, use gpio */
+ sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
+ }
+
+ if (boarddata) {
+ err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
+ if (err) {
+ dev_warn(mmc_dev(host->mmc), "can't get wp_pin!\n");
+ boarddata->wp_gpio = err;
+ }
+ }
return 0;
}
@@ -126,20 +160,15 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
static void esdhc_pltfm_exit(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+
+ if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+ gpio_free(boarddata->wp_gpio);
clk_disable(pltfm_host->clk);
clk_put(pltfm_host->clk);
}
-static struct sdhci_ops sdhci_esdhc_ops = {
- .read_w = esdhc_readw_le,
- .write_w = esdhc_writew_le,
- .write_b = esdhc_writeb_le,
- .set_clock = esdhc_set_clock,
- .get_max_clock = esdhc_pltfm_get_max_clock,
- .get_min_clock = esdhc_pltfm_get_min_clock,
-};
-
struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
/* ADMA has issues. Might be fixable */
--
1.7.2.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 1/5] mmc: sdhci-esdhc-imx: add support for write protect on custom GPIO
2011-02-10 19:14 ` [PATCH 1/5] mmc: sdhci-esdhc-imx: add support for write protect on custom GPIO Wolfram Sang
@ 2011-02-10 22:24 ` Marc Reilly
2011-02-11 9:42 ` Wolfram Sang
0 siblings, 1 reply; 12+ messages in thread
From: Marc Reilly @ 2011-02-10 22:24 UTC (permalink / raw)
To: linux-arm-kernel
Hi Wolfram,
First three patches work well on my vpr200 board (mx35).
One comment inline...
I ran some tests of insert/remove card with the card locked and unlocked, and
trying to append a file. It behaved as expected, thus:
Tested-by: Marc Reilly <marc@cpdesign.com.au>
> +static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
> +{
> + struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
> +
> + if (boarddata && gpio_is_valid(boarddata->wp_gpio))
> + return gpio_get_value(boarddata->wp_gpio);
> + else
> + return -ENOSYS;
> +}
> +
..snip..
> @@ -116,9 +139,20 @@ static int esdhc_pltfm_init(struct sdhci_host *host,
> struct sdhci_pltfm_data *pd if (cpu_is_mx35() || cpu_is_mx51())
> host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
>
> - /* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */
> - if (cpu_is_mx25() || cpu_is_mx35())
> + if (cpu_is_mx25() || cpu_is_mx35()) {
> + /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
> host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
> + /* write_protect can't be routed to controller, use gpio */
> + sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
> + }
> +
> + if (boarddata) {
Perhaps (boarddata && gpio_is_valid(boarddata->wp_gpio) as above?
For example what if someone sets up the boarddata for a card detect, but not
write protect.
> + err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
> + if (err) {
> + dev_warn(mmc_dev(host->mmc), "can't get wp_pin!\n");
> + boarddata->wp_gpio = err;
> + }
> + }
>
> return 0;
> }
Cheers,
Marc
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/5] mmc: sdhci-esdhc-imx: add support for write protect on custom GPIO
2011-02-10 22:24 ` Marc Reilly
@ 2011-02-11 9:42 ` Wolfram Sang
0 siblings, 0 replies; 12+ messages in thread
From: Wolfram Sang @ 2011-02-11 9:42 UTC (permalink / raw)
To: linux-arm-kernel
Marc,
On Fri, Feb 11, 2011 at 09:24:38AM +1100, Marc Reilly wrote:
> Tested-by: Marc Reilly <marc@cpdesign.com.au>
Thanks a lot!
> > + if (boarddata) {
>
> Perhaps (boarddata && gpio_is_valid(boarddata->wp_gpio) as above?
>
> For example what if someone sets up the boarddata for a card detect, but not
> write protect.
Well, I couldn't do this here, because later the cd_pin-stuff will also
be added to the if-block. However, I see what you mean and that could
still be added before the gpio_request below. That would add another
level of indentation, though, for a case I'd consider to be more
theoretical (and definately not recommended). Maybe I will adjust the
warning message to be also understandable for the case a GPIO is preset
with an invalid number. I think the warning itself is justified.
>
> > + err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
> > + if (err) {
> > + dev_warn(mmc_dev(host->mmc), "can't get wp_pin!\n");
> > + boarddata->wp_gpio = err;
> > + }
> > + }
Regards,
Wolfram
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/5] mmc: sdhci-esdhc: broken card detection is not a default quirk
2011-02-10 19:14 [PATCH 0/5] sdhci-esdhc-imx: use gpio for write protection and card detection Wolfram Sang
2011-02-10 19:14 ` [PATCH 1/5] mmc: sdhci-esdhc-imx: add support for write protect on custom GPIO Wolfram Sang
@ 2011-02-10 19:14 ` Wolfram Sang
2011-02-10 19:18 ` Wolfram Sang
2011-02-10 19:14 ` [PATCH 3/5] mmc: sdhci-esdhc-imx: add card detect on custom GPIO Wolfram Sang
` (2 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Wolfram Sang @ 2011-02-10 19:14 UTC (permalink / raw)
To: linux-arm-kernel
It can be worked around using a GPIO which will be done for i.MX later.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 3 ++-
drivers/mmc/host/sdhci-esdhc.h | 1 -
drivers/mmc/host/sdhci-of-esdhc.c | 3 ++-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 83d178b..e0fa1f3 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -170,7 +170,8 @@ static void esdhc_pltfm_exit(struct sdhci_host *host)
}
struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
- .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
+ .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
+ | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
/* ADMA has issues. Might be fixable */
.ops = &sdhci_esdhc_ops,
.init = esdhc_pltfm_init,
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index afaf1bc..c55aae8 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -19,7 +19,6 @@
*/
#define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
- SDHCI_QUIRK_BROKEN_CARD_DETECTION | \
SDHCI_QUIRK_NO_BUSY_IRQ | \
SDHCI_QUIRK_NONSTANDARD_CLOCK | \
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index fcd0e1f..08161f6 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -73,7 +73,8 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
}
struct sdhci_of_data sdhci_esdhc = {
- .quirks = ESDHC_DEFAULT_QUIRKS,
+ /* card detection could be handled via GPIO */
+ .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
.ops = {
.read_l = sdhci_be32bs_readl,
.read_w = esdhc_readw,
--
1.7.2.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/5] mmc: sdhci-esdhc: broken card detection is not a default quirk
2011-02-10 19:14 ` [PATCH 2/5] mmc: sdhci-esdhc: broken card detection is not a default quirk Wolfram Sang
@ 2011-02-10 19:18 ` Wolfram Sang
2011-02-11 10:07 ` Anton Vorontsov
0 siblings, 1 reply; 12+ messages in thread
From: Wolfram Sang @ 2011-02-10 19:18 UTC (permalink / raw)
To: linux-arm-kernel
Adding Anton to Cc...
On Thu, Feb 10, 2011 at 08:14:48PM +0100, Wolfram Sang wrote:
> It can be worked around using a GPIO which will be done for i.MX later.
>
> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
> ---
> drivers/mmc/host/sdhci-esdhc-imx.c | 3 ++-
> drivers/mmc/host/sdhci-esdhc.h | 1 -
> drivers/mmc/host/sdhci-of-esdhc.c | 3 ++-
> 3 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 83d178b..e0fa1f3 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -170,7 +170,8 @@ static void esdhc_pltfm_exit(struct sdhci_host *host)
> }
>
> struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
> - .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
> + .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
> + | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
> /* ADMA has issues. Might be fixable */
> .ops = &sdhci_esdhc_ops,
> .init = esdhc_pltfm_init,
> diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
> index afaf1bc..c55aae8 100644
> --- a/drivers/mmc/host/sdhci-esdhc.h
> +++ b/drivers/mmc/host/sdhci-esdhc.h
> @@ -19,7 +19,6 @@
> */
>
> #define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
> - SDHCI_QUIRK_BROKEN_CARD_DETECTION | \
> SDHCI_QUIRK_NO_BUSY_IRQ | \
> SDHCI_QUIRK_NONSTANDARD_CLOCK | \
> SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
> diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
> index fcd0e1f..08161f6 100644
> --- a/drivers/mmc/host/sdhci-of-esdhc.c
> +++ b/drivers/mmc/host/sdhci-of-esdhc.c
> @@ -73,7 +73,8 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
> }
>
> struct sdhci_of_data sdhci_esdhc = {
> - .quirks = ESDHC_DEFAULT_QUIRKS,
> + /* card detection could be handled via GPIO */
> + .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
> .ops = {
> .read_l = sdhci_be32bs_readl,
> .read_w = esdhc_readw,
> --
> 1.7.2.3
>
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110210/398800b4/attachment-0001.sig>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/5] mmc: sdhci-esdhc: broken card detection is not a default quirk
2011-02-10 19:18 ` Wolfram Sang
@ 2011-02-11 10:07 ` Anton Vorontsov
0 siblings, 0 replies; 12+ messages in thread
From: Anton Vorontsov @ 2011-02-11 10:07 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Feb 10, 2011 at 08:18:21PM +0100, Wolfram Sang wrote:
>
> Adding Anton to Cc...
[...]
> > struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
> > - .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
> > + .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
> > + | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
Minor nit: "|" should be on the previous line.
Otherwise,
Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
Thanks!
--
Anton Vorontsov
Email: cbouatmailru at gmail.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 3/5] mmc: sdhci-esdhc-imx: add card detect on custom GPIO
2011-02-10 19:14 [PATCH 0/5] sdhci-esdhc-imx: use gpio for write protection and card detection Wolfram Sang
2011-02-10 19:14 ` [PATCH 1/5] mmc: sdhci-esdhc-imx: add support for write protect on custom GPIO Wolfram Sang
2011-02-10 19:14 ` [PATCH 2/5] mmc: sdhci-esdhc: broken card detection is not a default quirk Wolfram Sang
@ 2011-02-10 19:14 ` Wolfram Sang
2011-02-10 19:14 ` [PATCH 4/5] arm: mach-mx3: pcm043: add write-protect and card-detect for SD1 Wolfram Sang
2011-02-10 19:14 ` [PATCH 5/5] arm: mach-mx3: use IMX_GPIO_NR instead of hard-coded values Wolfram Sang
4 siblings, 0 replies; 12+ messages in thread
From: Wolfram Sang @ 2011-02-10 19:14 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
arch/arm/plat-mxc/include/mach/esdhc.h | 2 +
drivers/mmc/host/sdhci-esdhc-imx.c | 75 ++++++++++++++++++++++++++++++++
2 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
index dbf6d56..7501d4e 100644
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -16,9 +16,11 @@
* strongly recommended for i.MX25/35, not needed for other variants
*
* @wp_gpio: gpio for write_protect
+ * @cd_gpio: gpio for card_detect interrupt
*/
struct esdhc_platform_data {
unsigned int wp_gpio;
+ unsigned int cd_gpio;
};
#endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index e0fa1f3..e9c56b6 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -32,6 +32,39 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i
writel(((readl(base) & ~(mask << shift)) | (val << shift)), base);
}
+static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
+{
+ /* fake CARD_PRESENT flag on mx25/35 */
+ u32 val = readl(host->ioaddr + reg);
+
+ if (unlikely(reg == SDHCI_PRESENT_STATE)) {
+ struct esdhc_platform_data *boarddata =
+ host->mmc->parent->platform_data;
+
+ if (boarddata && gpio_is_valid(boarddata->cd_gpio)
+ && gpio_get_value(boarddata->cd_gpio))
+ /* no card, if a valid gpio says so... */
+ val &= SDHCI_CARD_PRESENT;
+ else
+ /* ... in all other cases assume card is present */
+ val |= SDHCI_CARD_PRESENT;
+ }
+
+ return val;
+}
+
+static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
+{
+ if (unlikely(reg == SDHCI_INT_ENABLE))
+ /*
+ * these interrupts won't work with a custom card_detect gpio
+ * (only applied to mx25/35)
+ */
+ val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
+
+ writel(val, host->ioaddr + reg);
+}
+
static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
{
if (unlikely(reg == SDHCI_HOST_VERSION))
@@ -121,6 +154,14 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.get_min_clock = esdhc_pltfm_get_min_clock,
};
+static irqreturn_t cd_irq(int irq, void *data)
+{
+ struct sdhci_host *sdhost = (struct sdhci_host *)data;
+
+ tasklet_schedule(&sdhost->card_tasklet);
+ return IRQ_HANDLED;
+};
+
static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -142,6 +183,8 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
if (cpu_is_mx25() || cpu_is_mx35()) {
/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+ /* card_detect can't be routed to controller, mark broken */
+ host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
/* write_protect can't be routed to controller, use gpio */
sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
}
@@ -152,9 +195,34 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
dev_warn(mmc_dev(host->mmc), "can't get wp_pin!\n");
boarddata->wp_gpio = err;
}
+
+ err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
+ if (err) {
+ dev_warn(mmc_dev(host->mmc), "can't get cd_pin!\n");
+ goto no_card_detect_pin;
+ }
+
+ err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ mmc_hostname(host->mmc), host);
+ if (err) {
+ dev_warn(mmc_dev(host->mmc), "request irq error\n");
+ goto no_card_detect_irq;
+ }
+
+ sdhci_esdhc_ops.write_l = esdhc_writel_le;
+ sdhci_esdhc_ops.read_l = esdhc_readl_le;
+ /* Now we have a working card_detect again */
+ host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
}
return 0;
+
+ no_card_detect_irq:
+ gpio_free(boarddata->cd_gpio);
+ no_card_detect_pin:
+ boarddata->cd_gpio = err;
+ return 0;
}
static void esdhc_pltfm_exit(struct sdhci_host *host)
@@ -165,6 +233,13 @@ static void esdhc_pltfm_exit(struct sdhci_host *host)
if (boarddata && gpio_is_valid(boarddata->wp_gpio))
gpio_free(boarddata->wp_gpio);
+ if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
+ gpio_free(boarddata->cd_gpio);
+
+ if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
+ free_irq(gpio_to_irq(boarddata->cd_gpio), host);
+ }
+
clk_disable(pltfm_host->clk);
clk_put(pltfm_host->clk);
}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/5] arm: mach-mx3: pcm043: add write-protect and card-detect for SD1
2011-02-10 19:14 [PATCH 0/5] sdhci-esdhc-imx: use gpio for write protection and card detection Wolfram Sang
` (2 preceding siblings ...)
2011-02-10 19:14 ` [PATCH 3/5] mmc: sdhci-esdhc-imx: add card detect on custom GPIO Wolfram Sang
@ 2011-02-10 19:14 ` Wolfram Sang
2011-02-10 19:14 ` [PATCH 5/5] arm: mach-mx3: use IMX_GPIO_NR instead of hard-coded values Wolfram Sang
4 siblings, 0 replies; 12+ messages in thread
From: Wolfram Sang @ 2011-02-10 19:14 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
arch/arm/mach-mx3/mach-pcm043.c | 13 ++++++++++++-
1 files changed, 12 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-mx3/mach-pcm043.c b/arch/arm/mach-mx3/mach-pcm043.c
index bcf83fc..26b686c 100644
--- a/arch/arm/mach-mx3/mach-pcm043.c
+++ b/arch/arm/mach-mx3/mach-pcm043.c
@@ -40,6 +40,7 @@
#include <mach/mx3fb.h>
#include <mach/ulpi.h>
#include <mach/audmux.h>
+#include <mach/esdhc.h>
#include "devices-imx35.h"
#include "devices.h"
@@ -219,12 +220,17 @@ static iomux_v3_cfg_t pcm043_pads[] = {
MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
+ MX35_PAD_ATA_DATA10__GPIO2_23, /* WriteProtect */
+ MX35_PAD_ATA_DATA11__GPIO2_24, /* CardDetect */
};
#define AC97_GPIO_TXFS (1 * 32 + 31)
#define AC97_GPIO_TXD (1 * 32 + 28)
#define AC97_GPIO_RESET (1 * 32 + 0)
+#define SD1_GPIO_WP (1 * 32 + 23)
+#define SD1_GPIO_CD (1 * 32 + 24)
+
static void pcm043_ac97_warm_reset(struct snd_ac97 *ac97)
{
iomux_v3_cfg_t txfs_gpio = MX35_PAD_STXFS4__GPIO2_31;
@@ -307,6 +313,11 @@ pcm037_nand_board_info __initconst = {
.hw_ecc = 1,
};
+static struct esdhc_platform_data sd1_pdata = {
+ .wp_gpio = SD1_GPIO_WP,
+ .cd_gpio = SD1_GPIO_CD,
+};
+
#if defined(CONFIG_USB_ULPI)
static struct mxc_usbh_platform_data otg_pdata __initdata = {
.portsc = MXC_EHCI_MODE_UTMI,
@@ -393,7 +404,7 @@ static void __init mxc_board_init(void)
imx35_add_fsl_usb2_udc(&otg_device_pdata);
imx35_add_flexcan1(NULL);
- imx35_add_sdhci_esdhc_imx(0, NULL);
+ imx35_add_sdhci_esdhc_imx(0, &sd1_pdata);
}
static void __init pcm043_timer_init(void)
--
1.7.2.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 5/5] arm: mach-mx3: use IMX_GPIO_NR instead of hard-coded values
2011-02-10 19:14 [PATCH 0/5] sdhci-esdhc-imx: use gpio for write protection and card detection Wolfram Sang
` (3 preceding siblings ...)
2011-02-10 19:14 ` [PATCH 4/5] arm: mach-mx3: pcm043: add write-protect and card-detect for SD1 Wolfram Sang
@ 2011-02-10 19:14 ` Wolfram Sang
4 siblings, 0 replies; 12+ messages in thread
From: Wolfram Sang @ 2011-02-10 19:14 UTC (permalink / raw)
To: linux-arm-kernel
The latter are error-prone because the bank number is one less than one
would read in the documentation.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Cc: Eric B?nard <eric@eukrea.com>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c | 4 ++--
arch/arm/mach-mx3/mach-cpuimx35.c | 2 +-
arch/arm/mach-mx3/mach-pcm043.c | 10 +++++-----
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
index 14a5ffc..8076147 100644
--- a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
@@ -165,8 +165,8 @@ static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
};
-#define GPIO_LED1 (2 * 32 + 29)
-#define GPIO_SWITCH1 (2 * 32 + 25)
+#define GPIO_LED1 IMX_GPIO_NR(3, 29)
+#define GPIO_SWITCH1 IMX_GPIO_NR(3, 25)
#define GPIO_LCDPWR (4)
static void eukrea_mbimxsd_lcd_power_set(struct plat_lcd_data *pd,
diff --git a/arch/arm/mach-mx3/mach-cpuimx35.c b/arch/arm/mach-mx3/mach-cpuimx35.c
index 26ae90f..892c3a9 100644
--- a/arch/arm/mach-mx3/mach-cpuimx35.c
+++ b/arch/arm/mach-mx3/mach-cpuimx35.c
@@ -60,7 +60,7 @@ static struct tsc2007_platform_data tsc2007_info = {
.x_plate_ohms = 180,
};
-#define TSC2007_IRQGPIO (2 * 32 + 2)
+#define TSC2007_IRQGPIO IMX_GPIO_NR(3, 2)
static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
{
I2C_BOARD_INFO("pcf8563", 0x51),
diff --git a/arch/arm/mach-mx3/mach-pcm043.c b/arch/arm/mach-mx3/mach-pcm043.c
index 26b686c..51542f7 100644
--- a/arch/arm/mach-mx3/mach-pcm043.c
+++ b/arch/arm/mach-mx3/mach-pcm043.c
@@ -224,12 +224,12 @@ static iomux_v3_cfg_t pcm043_pads[] = {
MX35_PAD_ATA_DATA11__GPIO2_24, /* CardDetect */
};
-#define AC97_GPIO_TXFS (1 * 32 + 31)
-#define AC97_GPIO_TXD (1 * 32 + 28)
-#define AC97_GPIO_RESET (1 * 32 + 0)
+#define AC97_GPIO_TXFS IMX_GPIO_NR(2, 31)
+#define AC97_GPIO_TXD IMX_GPIO_NR(2, 28)
+#define AC97_GPIO_RESET IMX_GPIO_NR(2, 0)
-#define SD1_GPIO_WP (1 * 32 + 23)
-#define SD1_GPIO_CD (1 * 32 + 24)
+#define SD1_GPIO_WP IMX_GPIO_NR(2, 23)
+#define SD1_GPIO_CD IMX_GPIO_NR(2, 24)
static void pcm043_ac97_warm_reset(struct snd_ac97 *ac97)
{
--
1.7.2.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 1/5] mmc: sdhci-esdhc-imx: add support for write protect on custom GPIO
2011-02-22 12:58 [PATCH V2 0/5] sdhci-esdhc-imx: use gpio for write protection and card detection Wolfram Sang
@ 2011-02-22 12:58 ` Wolfram Sang
0 siblings, 0 replies; 12+ messages in thread
From: Wolfram Sang @ 2011-02-22 12:58 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Tested-by: Marc Reilly <marc@cpdesign.com.au>
---
Change since last version:
* rewrote the warning message to apply to non-existant wp_gpio
arch/arm/plat-mxc/include/mach/esdhc.h | 10 +++++-
drivers/mmc/host/sdhci-esdhc-imx.c | 52 +++++++++++++++++++++++++-------
2 files changed, 50 insertions(+), 12 deletions(-)
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
index a48a9aa..dbf6d56 100644
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -10,7 +10,15 @@
#ifndef __ASM_ARCH_IMX_ESDHC_H
#define __ASM_ARCH_IMX_ESDHC_H
+/**
+ * struct esdhc_platform_data - optional platform data for esdhc on i.MX
+ *
+ * strongly recommended for i.MX25/35, not needed for other variants
+ *
+ * @wp_gpio: gpio for write_protect
+ */
+
struct esdhc_platform_data {
- unsigned int wp_gpio; /* write protect pin */
+ unsigned int wp_gpio;
};
#endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 9b82910..65df00b 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -15,9 +15,11 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/gpio.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdhci-pltfm.h>
#include <mach/hardware.h>
+#include <mach/esdhc.h>
#include "sdhci.h"
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
@@ -100,10 +102,31 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
return clk_get_rate(pltfm_host->clk) / 256 / 16;
}
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+ struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+
+ if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+ return gpio_get_value(boarddata->wp_gpio);
+ else
+ return -ENOSYS;
+}
+
+static struct sdhci_ops sdhci_esdhc_ops = {
+ .read_w = esdhc_readw_le,
+ .write_w = esdhc_writew_le,
+ .write_b = esdhc_writeb_le,
+ .set_clock = esdhc_set_clock,
+ .get_max_clock = esdhc_pltfm_get_max_clock,
+ .get_min_clock = esdhc_pltfm_get_min_clock,
+};
+
static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
struct clk *clk;
+ int err;
clk = clk_get(mmc_dev(host->mmc), NULL);
if (IS_ERR(clk)) {
@@ -116,9 +139,21 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
if (cpu_is_mx35() || cpu_is_mx51())
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
- /* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */
- if (cpu_is_mx25() || cpu_is_mx35())
+ if (cpu_is_mx25() || cpu_is_mx35()) {
+ /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+ /* write_protect can't be routed to controller, use gpio */
+ sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
+ }
+
+ if (boarddata) {
+ err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
+ if (err) {
+ dev_warn(mmc_dev(host->mmc),
+ "no write-protect pin available!\n");
+ boarddata->wp_gpio = err;
+ }
+ }
return 0;
}
@@ -126,20 +161,15 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
static void esdhc_pltfm_exit(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+
+ if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+ gpio_free(boarddata->wp_gpio);
clk_disable(pltfm_host->clk);
clk_put(pltfm_host->clk);
}
-static struct sdhci_ops sdhci_esdhc_ops = {
- .read_w = esdhc_readw_le,
- .write_w = esdhc_writew_le,
- .write_b = esdhc_writeb_le,
- .set_clock = esdhc_set_clock,
- .get_max_clock = esdhc_pltfm_get_max_clock,
- .get_min_clock = esdhc_pltfm_get_min_clock,
-};
-
struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
/* ADMA has issues. Might be fixable */
--
1.7.2.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 1/5] mmc: sdhci-esdhc-imx: add support for write protect on custom GPIO
2011-02-23 13:51 [PATCH V3 0/5] sdhci-esdhc-imx: use gpio for write protection and card detection Wolfram Sang
@ 2011-02-23 13:51 ` Wolfram Sang
0 siblings, 0 replies; 12+ messages in thread
From: Wolfram Sang @ 2011-02-23 13:51 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Tested-by: Marc Reilly <marc@cpdesign.com.au>
Tested-by: Eric Benard <eric@eukrea.com>
---
change since last version:
* improve kerneldoc
arch/arm/plat-mxc/include/mach/esdhc.h | 10 +++++-
drivers/mmc/host/sdhci-esdhc-imx.c | 52 +++++++++++++++++++++++++-------
2 files changed, 50 insertions(+), 12 deletions(-)
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
index a48a9aa..47da109 100644
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -10,7 +10,15 @@
#ifndef __ASM_ARCH_IMX_ESDHC_H
#define __ASM_ARCH_IMX_ESDHC_H
+/**
+ * struct esdhc_platform_data - optional platform data for esdhc on i.MX
+ *
+ * strongly recommended for i.MX25/35, not needed for other variants
+ *
+ * @wp_gpio: gpio for write_protect (-EINVAL if unused)
+ */
+
struct esdhc_platform_data {
- unsigned int wp_gpio; /* write protect pin */
+ unsigned int wp_gpio;
};
#endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 9b82910..65df00b 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -15,9 +15,11 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/gpio.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdhci-pltfm.h>
#include <mach/hardware.h>
+#include <mach/esdhc.h>
#include "sdhci.h"
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
@@ -100,10 +102,31 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
return clk_get_rate(pltfm_host->clk) / 256 / 16;
}
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+ struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+
+ if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+ return gpio_get_value(boarddata->wp_gpio);
+ else
+ return -ENOSYS;
+}
+
+static struct sdhci_ops sdhci_esdhc_ops = {
+ .read_w = esdhc_readw_le,
+ .write_w = esdhc_writew_le,
+ .write_b = esdhc_writeb_le,
+ .set_clock = esdhc_set_clock,
+ .get_max_clock = esdhc_pltfm_get_max_clock,
+ .get_min_clock = esdhc_pltfm_get_min_clock,
+};
+
static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
struct clk *clk;
+ int err;
clk = clk_get(mmc_dev(host->mmc), NULL);
if (IS_ERR(clk)) {
@@ -116,9 +139,21 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
if (cpu_is_mx35() || cpu_is_mx51())
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
- /* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */
- if (cpu_is_mx25() || cpu_is_mx35())
+ if (cpu_is_mx25() || cpu_is_mx35()) {
+ /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+ /* write_protect can't be routed to controller, use gpio */
+ sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
+ }
+
+ if (boarddata) {
+ err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
+ if (err) {
+ dev_warn(mmc_dev(host->mmc),
+ "no write-protect pin available!\n");
+ boarddata->wp_gpio = err;
+ }
+ }
return 0;
}
@@ -126,20 +161,15 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
static void esdhc_pltfm_exit(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+
+ if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+ gpio_free(boarddata->wp_gpio);
clk_disable(pltfm_host->clk);
clk_put(pltfm_host->clk);
}
-static struct sdhci_ops sdhci_esdhc_ops = {
- .read_w = esdhc_readw_le,
- .write_w = esdhc_writew_le,
- .write_b = esdhc_writeb_le,
- .set_clock = esdhc_set_clock,
- .get_max_clock = esdhc_pltfm_get_max_clock,
- .get_min_clock = esdhc_pltfm_get_min_clock,
-};
-
struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
/* ADMA has issues. Might be fixable */
--
1.7.2.3
^ permalink raw reply related [flat|nested] 12+ messages in thread