* [PATCH v2 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5
@ 2011-06-15 11:15 Shawn Guo
2011-06-15 11:15 ` [PATCH v2 1/4] mmc: sdhci: fix interrupt storm from card detection Shawn Guo
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Shawn Guo @ 2011-06-15 11:15 UTC (permalink / raw)
To: linux-arm-kernel
The card-present polling for sdhci based driver is very expensive
in terms of the impact to system performance. We observe a few
system performance issues from Freescale and Linaro on mx5 platforms,
which have been proved card polling related.
The patch set extends the current sdhci-esdhc-imx card_detect and
write_protect support to cover mx5 platforms, and solves above
performance issues.
Changes since v1:
* Rebase on today's linux-next
* Take the suggestion from Arnaud Patard to add default pdata in
imx_add_sdhci_esdhc_imx(), to avoid touching every single board
file for the platform_data changes
* Add comment for sdhci.c change
* Change ESDHC_CD(WP)_SIGNAL to ESDHC_CD(WP)_CONTROLLER for a more
descriptive name
* Add missing NONE case handling in esdhc_pltfm_get_ro
* Improve a couple comment wording per suggestion from Wolfram Sang
Shawn Guo (4):
mmc: sdhci: fix interrupt storm from card detection
mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared
mmc: sdhci-esdhc-imx: remove "WP" from flag ESDHC_FLAG_GPIO_FOR_CD_WP
mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5
arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c | 3 +-
arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c | 3 +-
arch/arm/mach-imx/mach-mx25_3ds.c | 2 +
arch/arm/mach-imx/mach-pcm043.c | 2 +
arch/arm/mach-mx5/board-mx51_babbage.c | 14 ++-
arch/arm/mach-mx5/board-mx53_loco.c | 4 +
.../plat-mxc/devices/platform-sdhci-esdhc-imx.c | 12 ++
arch/arm/plat-mxc/include/mach/esdhc.h | 25 ++++-
drivers/mmc/host/sdhci-esdhc-imx.c | 123 ++++++++++++--------
drivers/mmc/host/sdhci.c | 23 +++-
10 files changed, 145 insertions(+), 66 deletions(-)
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 1/4] mmc: sdhci: fix interrupt storm from card detection
2011-06-15 11:15 [PATCH v2 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5 Shawn Guo
@ 2011-06-15 11:15 ` Shawn Guo
2011-06-15 11:15 ` [PATCH v2 2/4] mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared Shawn Guo
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Shawn Guo @ 2011-06-15 11:15 UTC (permalink / raw)
To: linux-arm-kernel
The issue was initially found by Eric Benard as below.
http://permalink.gmane.org/gmane.linux.ports.arm.kernel/108031
Not sure about other SDHCI based controller, but on Freescale eSDHC,
the SDHCI_INT_CARD_INSERT bits will be immediately set again when it
gets cleared, if a card is inserted. The driver need to mask the irq
to prevent interrupt storm which will freeze the system. And the
SDHCI_INT_CARD_REMOVE gets the same situation.
The patch fixes the problem based on the initial idea from
Eric Benard.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Eric Benard <eric@eukrea.com>
---
drivers/mmc/host/sdhci.c | 23 ++++++++++++++++++++---
1 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 91d9892..0dd10e4 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2154,13 +2154,30 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
mmc_hostname(host->mmc), intmask);
if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+ u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+ SDHCI_CARD_PRESENT;
+
+ /*
+ * There is a observation on i.mx esdhc. INSERT bit will be
+ * immediately set again when it gets cleared, if a card is
+ * inserted. We have to mask the irq to prevent interrupt
+ * storm which will freeze the system. And the REMOVE gets
+ * the same situation.
+ *
+ * More testing are needed here to ensure it works for other
+ * platforms though.
+ */
+ sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
+ SDHCI_INT_CARD_REMOVE);
+ sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
+ SDHCI_INT_CARD_INSERT);
+
sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
- SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+ SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+ intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
tasklet_schedule(&host->card_tasklet);
}
- intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
-
if (intmask & SDHCI_INT_CMD_MASK) {
sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
SDHCI_INT_STATUS);
--
1.7.4.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 2/4] mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared
2011-06-15 11:15 [PATCH v2 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5 Shawn Guo
2011-06-15 11:15 ` [PATCH v2 1/4] mmc: sdhci: fix interrupt storm from card detection Shawn Guo
@ 2011-06-15 11:15 ` Shawn Guo
2011-06-16 12:01 ` Wolfram Sang
2011-06-15 11:15 ` [PATCH v2 3/4] mmc: sdhci-esdhc-imx: remove "WP" from flag ESDHC_FLAG_GPIO_FOR_CD_WP Shawn Guo
2011-06-15 11:15 ` [PATCH v2 4/4] mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5 Shawn Guo
3 siblings, 1 reply; 8+ messages in thread
From: Shawn Guo @ 2011-06-15 11:15 UTC (permalink / raw)
To: linux-arm-kernel
The function esdhc_readl_le intends to clear bit SDHCI_CARD_PRESENT,
when the card detect gpio tells there is no card. But it does not
clear the bit actually. The patch gives a fix on that.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 248b8e5..94097c0 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -84,7 +84,7 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
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;
+ val &= ~SDHCI_CARD_PRESENT;
else
/* ... in all other cases assume card is present */
val |= SDHCI_CARD_PRESENT;
--
1.7.4.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 3/4] mmc: sdhci-esdhc-imx: remove "WP" from flag ESDHC_FLAG_GPIO_FOR_CD_WP
2011-06-15 11:15 [PATCH v2 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5 Shawn Guo
2011-06-15 11:15 ` [PATCH v2 1/4] mmc: sdhci: fix interrupt storm from card detection Shawn Guo
2011-06-15 11:15 ` [PATCH v2 2/4] mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared Shawn Guo
@ 2011-06-15 11:15 ` Shawn Guo
2011-06-15 11:15 ` [PATCH v2 4/4] mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5 Shawn Guo
3 siblings, 0 replies; 8+ messages in thread
From: Shawn Guo @ 2011-06-15 11:15 UTC (permalink / raw)
To: linux-arm-kernel
The use of flag ESDHC_FLAG_GPIO_FOR_CD_WP is all CD related. It does
not necessarily need to bother WP in the flag name.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 94097c0..79b7a9a 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -29,7 +29,7 @@
#define SDHCI_VENDOR_SPEC 0xC0
#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002
-#define ESDHC_FLAG_GPIO_FOR_CD_WP (1 << 0)
+#define ESDHC_FLAG_GPIO_FOR_CD (1 << 0)
/*
* The CMDTYPE of the CMD register (offset 0xE) should be set to
* "11" when the STOP CMD12 is issued on imx53 to abort one
@@ -77,7 +77,7 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
u32 val = readl(host->ioaddr + reg);
if (unlikely((reg == SDHCI_PRESENT_STATE)
- && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) {
+ && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) {
struct esdhc_platform_data *boarddata =
host->mmc->parent->platform_data;
@@ -99,7 +99,7 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
struct pltfm_imx_data *imx_data = pltfm_host->priv;
if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
- && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP)))
+ && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD)))
/*
* these interrupts won't work with a custom card_detect gpio
* (only applied to mx25/35)
@@ -308,7 +308,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
goto no_card_detect_irq;
}
- imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD_WP;
+ imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD;
/* Now we have a working card_detect again */
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
}
--
1.7.4.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 4/4] mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5
2011-06-15 11:15 [PATCH v2 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5 Shawn Guo
` (2 preceding siblings ...)
2011-06-15 11:15 ` [PATCH v2 3/4] mmc: sdhci-esdhc-imx: remove "WP" from flag ESDHC_FLAG_GPIO_FOR_CD_WP Shawn Guo
@ 2011-06-15 11:15 ` Shawn Guo
2011-06-16 12:10 ` Wolfram Sang
2011-06-17 8:18 ` [PATCH v2 4/4 RESEND] " Shawn Guo
3 siblings, 2 replies; 8+ messages in thread
From: Shawn Guo @ 2011-06-15 11:15 UTC (permalink / raw)
To: linux-arm-kernel
The patch extends card_detect and write_protect support to get mx5
family and more scenarios supported. The changes include:
* Turn platform_data from optional to mandatory
* Add cd_types and wp_types into platform_data to cover more use
cases
* Remove the use of flag ESDHC_FLAG_GPIO_FOR_CD
* Adjust some machine codes to adopt the platform_data changes
With this patch, card_detect and write_protect gets supported on
mx5 based platforms.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c | 3 +-
arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c | 3 +-
arch/arm/mach-imx/mach-mx25_3ds.c | 2 +
arch/arm/mach-imx/mach-pcm043.c | 2 +
arch/arm/mach-mx5/board-mx51_babbage.c | 14 ++-
arch/arm/mach-mx5/board-mx53_loco.c | 4 +
.../plat-mxc/devices/platform-sdhci-esdhc-imx.c | 12 ++
arch/arm/plat-mxc/include/mach/esdhc.h | 25 ++++-
drivers/mmc/host/sdhci-esdhc-imx.c | 121 ++++++++++++--------
9 files changed, 124 insertions(+), 62 deletions(-)
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
index 01ebcb3..66e8726 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
@@ -225,7 +225,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
static struct esdhc_platform_data sd1_pdata = {
.cd_gpio = GPIO_SD1CD,
- .wp_gpio = -EINVAL,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_NONE,
};
/*
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
index 558eb52..0f0af02 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
@@ -236,7 +236,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
static struct esdhc_platform_data sd1_pdata = {
.cd_gpio = GPIO_SD1CD,
- .wp_gpio = -EINVAL,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_NONE,
};
/*
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index 01534bb..7f66a91 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -215,6 +215,8 @@ static const struct imxi2c_platform_data mx25_3ds_i2c0_data __initconst = {
static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {
.wp_gpio = SD1_GPIO_WP,
.cd_gpio = SD1_GPIO_CD,
+ .wp_type = ESDHC_WP_GPIO,
+ .cd_type = ESDHC_CD_GPIO,
};
static void __init mx25pdk_init(void)
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 163cc31..660ec3e 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -349,6 +349,8 @@ __setup("otg_mode=", pcm043_otg_mode);
static struct esdhc_platform_data sd1_pdata = {
.wp_gpio = SD1_GPIO_WP,
.cd_gpio = SD1_GPIO_CD,
+ .wp_type = ESDHC_WP_GPIO,
+ .cd_type = ESDHC_CD_GPIO,
};
/*
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index 15c6000..e400b09 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -41,8 +41,6 @@
#define BABBAGE_POWER_KEY IMX_GPIO_NR(2, 21)
#define BABBAGE_ECSPI1_CS0 IMX_GPIO_NR(4, 24)
#define BABBAGE_ECSPI1_CS1 IMX_GPIO_NR(4, 25)
-#define BABBAGE_SD1_CD IMX_GPIO_NR(1, 0)
-#define BABBAGE_SD1_WP IMX_GPIO_NR(1, 1)
#define BABBAGE_SD2_CD IMX_GPIO_NR(1, 6)
#define BABBAGE_SD2_WP IMX_GPIO_NR(1, 5)
@@ -146,8 +144,9 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
MX51_PAD_SD1_DATA1__SD1_DATA1,
MX51_PAD_SD1_DATA2__SD1_DATA2,
MX51_PAD_SD1_DATA3__SD1_DATA3,
- MX51_PAD_GPIO1_0__GPIO1_0,
- MX51_PAD_GPIO1_1__GPIO1_1,
+ /* CD/WP from controller */
+ MX51_PAD_GPIO1_0__SD1_CD,
+ MX51_PAD_GPIO1_1__SD1_WP,
/* SD 2 */
MX51_PAD_SD2_CMD__SD2_CMD,
@@ -156,6 +155,7 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
MX51_PAD_SD2_DATA1__SD2_DATA1,
MX51_PAD_SD2_DATA2__SD2_DATA2,
MX51_PAD_SD2_DATA3__SD2_DATA3,
+ /* CD/WP gpio */
MX51_PAD_GPIO1_6__GPIO1_6,
MX51_PAD_GPIO1_5__GPIO1_5,
@@ -340,13 +340,15 @@ static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
};
static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
- .cd_gpio = BABBAGE_SD1_CD,
- .wp_gpio = BABBAGE_SD1_WP,
+ .cd_type = ESDHC_CD_CONTROLLER,
+ .wp_type = ESDHC_WP_CONTROLLER,
};
static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
.cd_gpio = BABBAGE_SD2_CD,
.wp_gpio = BABBAGE_SD2_WP,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_GPIO,
};
/*
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 54be525..4e1d51d 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -210,11 +210,15 @@ static const struct gpio_keys_platform_data loco_button_data __initconst = {
static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
.cd_gpio = LOCO_SD1_CD,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_NONE,
};
static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
.cd_gpio = LOCO_SD3_CD,
.wp_gpio = LOCO_SD3_WP,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_GPIO,
};
static inline void mx53_loco_fec_reset(void)
diff --git a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
index 6b2940b..79d6d71 100644
--- a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
+++ b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
@@ -65,6 +65,11 @@ imx53_sdhci_esdhc_imx_data[] __initconst = {
};
#endif /* ifdef CONFIG_SOC_IMX53 */
+static const struct esdhc_platform_data default_esdhc_pdata __initconst = {
+ .wp_type = ESDHC_WP_NONE,
+ .cd_type = ESDHC_CD_NONE,
+};
+
struct platform_device *__init imx_add_sdhci_esdhc_imx(
const struct imx_sdhci_esdhc_imx_data *data,
const struct esdhc_platform_data *pdata)
@@ -81,6 +86,13 @@ struct platform_device *__init imx_add_sdhci_esdhc_imx(
},
};
+ /*
+ * If machine does not provide pdata, use the default one
+ * which means no WP/CD support
+ */
+ if (!pdata)
+ pdata = &default_esdhc_pdata;
+
return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
ARRAY_SIZE(res), pdata, sizeof(*pdata));
}
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
index 86003f4..aaf9748 100644
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -10,17 +10,34 @@
#ifndef __ASM_ARCH_IMX_ESDHC_H
#define __ASM_ARCH_IMX_ESDHC_H
+enum wp_types {
+ ESDHC_WP_NONE, /* no WP, neither controller nor gpio */
+ ESDHC_WP_CONTROLLER, /* mmc controller internal WP */
+ ESDHC_WP_GPIO, /* external gpio pin for WP */
+};
+
+enum cd_types {
+ ESDHC_CD_NONE, /* no CD, neither controller nor gpio */
+ ESDHC_CD_CONTROLLER, /* mmc controller internal CD */
+ ESDHC_CD_GPIO, /* external gpio pin for CD */
+ ESDHC_CD_PERMANENT, /* no CD, card permanently wired to host */
+};
+
/**
- * struct esdhc_platform_data - optional platform data for esdhc on i.MX
+ * struct esdhc_platform_data - platform data for esdhc on i.MX
*
- * strongly recommended for i.MX25/35, not needed for other variants
+ * ESDHC_WP(CD)_CONTROLLER type is not available on i.MX25/35.
*
- * @wp_gpio: gpio for write_protect (-EINVAL if unused)
- * @cd_gpio: gpio for card_detect interrupt (-EINVAL if unused)
+ * @wp_gpio: gpio for write_protect
+ * @cd_gpio: gpio for card_detect interrupt
+ * @wp_type: type of write_protect method (see wp_types enum above)
+ * @cd_type: type of card_detect method (see cd_types enum above)
*/
struct esdhc_platform_data {
unsigned int wp_gpio;
unsigned int cd_gpio;
+ enum wp_types wp_type;
+ enum cd_types cd_type;
};
#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 79b7a9a..416a043 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -29,7 +29,6 @@
#define SDHCI_VENDOR_SPEC 0xC0
#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002
-#define ESDHC_FLAG_GPIO_FOR_CD (1 << 0)
/*
* The CMDTYPE of the CMD register (offset 0xE) should be set to
* "11" when the STOP CMD12 is issued on imx53 to abort one
@@ -70,19 +69,15 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i
static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ struct esdhc_platform_data *boarddata =
+ host->mmc->parent->platform_data;
- /* fake CARD_PRESENT flag on mx25/35 */
+ /* fake CARD_PRESENT flag */
u32 val = readl(host->ioaddr + reg);
if (unlikely((reg == SDHCI_PRESENT_STATE)
- && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) {
- struct esdhc_platform_data *boarddata =
- host->mmc->parent->platform_data;
-
- if (boarddata && gpio_is_valid(boarddata->cd_gpio)
- && gpio_get_value(boarddata->cd_gpio))
+ && gpio_is_valid(boarddata->cd_gpio))) {
+ if (gpio_get_value(boarddata->cd_gpio))
/* no card, if a valid gpio says so... */
val &= ~SDHCI_CARD_PRESENT;
else
@@ -97,12 +92,13 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ struct esdhc_platform_data *boarddata =
+ host->mmc->parent->platform_data;
if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
- && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD)))
+ && (boarddata->cd_type == ESDHC_CD_GPIO)))
/*
* 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);
@@ -201,6 +197,23 @@ 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;
+
+ switch (boarddata->wp_type) {
+ case ESDHC_WP_GPIO:
+ if (gpio_is_valid(boarddata->wp_gpio))
+ return gpio_get_value(boarddata->wp_gpio);
+ case ESDHC_WP_CONTROLLER:
+ return !(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
+ SDHCI_WRITE_PROTECT);
+ case ESDHC_WP_NONE:
+ return -ENOSYS;
+ }
+}
+
static struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl_le,
.read_w = esdhc_readw_le,
@@ -212,6 +225,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.get_min_clock = esdhc_pltfm_get_min_clock,
.get_max_blk_size = esdhc_pltfm_get_max_blk_size,
.get_max_blk_count = esdhc_pltfm_get_max_blk_count,
+ .get_ro = esdhc_pltfm_get_ro,
};
static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
@@ -221,17 +235,6 @@ static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
.ops = &sdhci_esdhc_ops,
};
-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 irqreturn_t cd_irq(int irq, void *data)
{
struct sdhci_host *sdhost = (struct sdhci_host *)data;
@@ -272,23 +275,34 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (!cpu_is_mx25())
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
- if (cpu_is_mx25() || cpu_is_mx35()) {
- /* write_protect can't be routed to controller, use gpio */
- sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
- }
-
if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
boarddata = host->mmc->parent->platform_data;
- if (boarddata) {
+ if (!boarddata) {
+ dev_err(mmc_dev(host->mmc), "no board data!\n");
+ err = -EINVAL;
+ goto no_board_data;
+ }
+
+ /* write_protect */
+ if (boarddata->wp_type == ESDHC_WP_GPIO) {
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;
+ "no write-protect pin available!\n");
+ boarddata->wp_gpio = -EINVAL;
}
+ } else {
+ boarddata->wp_gpio = -EINVAL;
+ }
+ /* card_detect */
+ if (boarddata->cd_type != ESDHC_CD_GPIO)
+ boarddata->cd_gpio = -EINVAL;
+
+ switch (boarddata->cd_type) {
+ case ESDHC_CD_GPIO:
err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
if (err) {
dev_warn(mmc_dev(host->mmc),
@@ -296,10 +310,6 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
goto no_card_detect_pin;
}
- /* i.MX5x has issues to be researched */
- if (!cpu_is_mx25() && !cpu_is_mx35())
- goto not_supported;
-
err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
mmc_hostname(host->mmc), host);
@@ -307,10 +317,19 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
dev_warn(mmc_dev(host->mmc), "request irq error\n");
goto no_card_detect_irq;
}
+ /* fall through */
- imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD;
- /* Now we have a working card_detect again */
+ case ESDHC_CD_CONTROLLER:
+ /* we have a working card_detect back */
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ break;
+
+ case ESDHC_CD_PERMANENT:
+ host->mmc->caps = MMC_CAP_NONREMOVABLE;
+ break;
+
+ case ESDHC_CD_NONE:
+ break;
}
err = sdhci_add_host(host);
@@ -319,16 +338,20 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
return 0;
- no_card_detect_irq:
- gpio_free(boarddata->cd_gpio);
- no_card_detect_pin:
- boarddata->cd_gpio = err;
- not_supported:
- kfree(imx_data);
- err_add_host:
+err_add_host:
+ if (gpio_is_valid(boarddata->cd_gpio))
+ free_irq(gpio_to_irq(boarddata->cd_gpio), host);
+no_card_detect_irq:
+ if (gpio_is_valid(boarddata->cd_gpio))
+ gpio_free(boarddata->cd_gpio);
+ if (gpio_is_valid(boarddata->wp_gpio))
+ gpio_free(boarddata->wp_gpio);
+no_card_detect_pin:
+no_board_data:
clk_disable(pltfm_host->clk);
clk_put(pltfm_host->clk);
- err_clk_get:
+err_clk_get:
+ kfree(imx_data);
sdhci_pltfm_free(pdev);
return err;
}
@@ -343,14 +366,12 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
sdhci_remove_host(host, dead);
- if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+ if (gpio_is_valid(boarddata->wp_gpio))
gpio_free(boarddata->wp_gpio);
- if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
+ if (gpio_is_valid(boarddata->cd_gpio)) {
+ free_irq(gpio_to_irq(boarddata->cd_gpio), host);
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);
--
1.7.4.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 2/4] mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared
2011-06-15 11:15 ` [PATCH v2 2/4] mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared Shawn Guo
@ 2011-06-16 12:01 ` Wolfram Sang
0 siblings, 0 replies; 8+ messages in thread
From: Wolfram Sang @ 2011-06-16 12:01 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Jun 15, 2011 at 07:15:20PM +0800, Shawn Guo wrote:
> The function esdhc_readl_le intends to clear bit SDHCI_CARD_PRESENT,
> when the card detect gpio tells there is no card. But it does not
> clear the bit actually. The patch gives a fix on that.
>
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
Should go to stable...
--
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/20110616/32f4b62b/attachment.sig>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 4/4] mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5
2011-06-15 11:15 ` [PATCH v2 4/4] mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5 Shawn Guo
@ 2011-06-16 12:10 ` Wolfram Sang
2011-06-17 8:18 ` [PATCH v2 4/4 RESEND] " Shawn Guo
1 sibling, 0 replies; 8+ messages in thread
From: Wolfram Sang @ 2011-06-16 12:10 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Jun 15, 2011 at 07:15:22PM +0800, Shawn Guo wrote:
> The patch extends card_detect and write_protect support to get mx5
> family and more scenarios supported. The changes include:
>
> * Turn platform_data from optional to mandatory
> * Add cd_types and wp_types into platform_data to cover more use
> cases
> * Remove the use of flag ESDHC_FLAG_GPIO_FOR_CD
> * Adjust some machine codes to adopt the platform_data changes
>
> With this patch, card_detect and write_protect gets supported on
> mx5 based platforms.
>
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Looks like right direction to me, so far; some testers would be good,
though.
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
--
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/20110616/b8d30372/attachment.sig>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 4/4 RESEND] mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5
2011-06-15 11:15 ` [PATCH v2 4/4] mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5 Shawn Guo
2011-06-16 12:10 ` Wolfram Sang
@ 2011-06-17 8:18 ` Shawn Guo
1 sibling, 0 replies; 8+ messages in thread
From: Shawn Guo @ 2011-06-17 8:18 UTC (permalink / raw)
To: linux-arm-kernel
The patch extends card_detect and write_protect support to get mx5
family and more scenarios supported. The changes include:
* Turn platform_data from optional to mandatory
* Add cd_types and wp_types into platform_data to cover more use
cases
* Remove the use of flag ESDHC_FLAG_GPIO_FOR_CD
* Adjust some machine codes to adopt the platform_data changes
With this patch, card_detect and write_protect gets supported on
mx5 based platforms.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
---
Changes for resend:
* Fix the warning below:
CC drivers/mmc/host/sdhci-esdhc-imx.o
drivers/mmc/host/sdhci-esdhc-imx.c: In function 'esdhc_pltfm_get_ro':
drivers/mmc/host/sdhci-esdhc-imx.c:215:1: warning: control reaches end of non-void function
* Add Wolfram's Acked-by
arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c | 3 +-
arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c | 3 +-
arch/arm/mach-imx/mach-mx25_3ds.c | 2 +
arch/arm/mach-imx/mach-pcm043.c | 2 +
arch/arm/mach-mx5/board-mx51_babbage.c | 14 ++-
arch/arm/mach-mx5/board-mx53_loco.c | 4 +
.../plat-mxc/devices/platform-sdhci-esdhc-imx.c | 12 ++
arch/arm/plat-mxc/include/mach/esdhc.h | 25 ++++-
drivers/mmc/host/sdhci-esdhc-imx.c | 123 ++++++++++++--------
9 files changed, 126 insertions(+), 62 deletions(-)
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
index 01ebcb3..66e8726 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
@@ -225,7 +225,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
static struct esdhc_platform_data sd1_pdata = {
.cd_gpio = GPIO_SD1CD,
- .wp_gpio = -EINVAL,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_NONE,
};
/*
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
index 558eb52..0f0af02 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
@@ -236,7 +236,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
static struct esdhc_platform_data sd1_pdata = {
.cd_gpio = GPIO_SD1CD,
- .wp_gpio = -EINVAL,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_NONE,
};
/*
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index 01534bb..7f66a91 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -215,6 +215,8 @@ static const struct imxi2c_platform_data mx25_3ds_i2c0_data __initconst = {
static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {
.wp_gpio = SD1_GPIO_WP,
.cd_gpio = SD1_GPIO_CD,
+ .wp_type = ESDHC_WP_GPIO,
+ .cd_type = ESDHC_CD_GPIO,
};
static void __init mx25pdk_init(void)
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 163cc31..660ec3e 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -349,6 +349,8 @@ __setup("otg_mode=", pcm043_otg_mode);
static struct esdhc_platform_data sd1_pdata = {
.wp_gpio = SD1_GPIO_WP,
.cd_gpio = SD1_GPIO_CD,
+ .wp_type = ESDHC_WP_GPIO,
+ .cd_type = ESDHC_CD_GPIO,
};
/*
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index 15c6000..e400b09 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -41,8 +41,6 @@
#define BABBAGE_POWER_KEY IMX_GPIO_NR(2, 21)
#define BABBAGE_ECSPI1_CS0 IMX_GPIO_NR(4, 24)
#define BABBAGE_ECSPI1_CS1 IMX_GPIO_NR(4, 25)
-#define BABBAGE_SD1_CD IMX_GPIO_NR(1, 0)
-#define BABBAGE_SD1_WP IMX_GPIO_NR(1, 1)
#define BABBAGE_SD2_CD IMX_GPIO_NR(1, 6)
#define BABBAGE_SD2_WP IMX_GPIO_NR(1, 5)
@@ -146,8 +144,9 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
MX51_PAD_SD1_DATA1__SD1_DATA1,
MX51_PAD_SD1_DATA2__SD1_DATA2,
MX51_PAD_SD1_DATA3__SD1_DATA3,
- MX51_PAD_GPIO1_0__GPIO1_0,
- MX51_PAD_GPIO1_1__GPIO1_1,
+ /* CD/WP from controller */
+ MX51_PAD_GPIO1_0__SD1_CD,
+ MX51_PAD_GPIO1_1__SD1_WP,
/* SD 2 */
MX51_PAD_SD2_CMD__SD2_CMD,
@@ -156,6 +155,7 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
MX51_PAD_SD2_DATA1__SD2_DATA1,
MX51_PAD_SD2_DATA2__SD2_DATA2,
MX51_PAD_SD2_DATA3__SD2_DATA3,
+ /* CD/WP gpio */
MX51_PAD_GPIO1_6__GPIO1_6,
MX51_PAD_GPIO1_5__GPIO1_5,
@@ -340,13 +340,15 @@ static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
};
static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
- .cd_gpio = BABBAGE_SD1_CD,
- .wp_gpio = BABBAGE_SD1_WP,
+ .cd_type = ESDHC_CD_CONTROLLER,
+ .wp_type = ESDHC_WP_CONTROLLER,
};
static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
.cd_gpio = BABBAGE_SD2_CD,
.wp_gpio = BABBAGE_SD2_WP,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_GPIO,
};
/*
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 54be525..4e1d51d 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -210,11 +210,15 @@ static const struct gpio_keys_platform_data loco_button_data __initconst = {
static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
.cd_gpio = LOCO_SD1_CD,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_NONE,
};
static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
.cd_gpio = LOCO_SD3_CD,
.wp_gpio = LOCO_SD3_WP,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_GPIO,
};
static inline void mx53_loco_fec_reset(void)
diff --git a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
index 6b2940b..79d6d71 100644
--- a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
+++ b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
@@ -65,6 +65,11 @@ imx53_sdhci_esdhc_imx_data[] __initconst = {
};
#endif /* ifdef CONFIG_SOC_IMX53 */
+static const struct esdhc_platform_data default_esdhc_pdata __initconst = {
+ .wp_type = ESDHC_WP_NONE,
+ .cd_type = ESDHC_CD_NONE,
+};
+
struct platform_device *__init imx_add_sdhci_esdhc_imx(
const struct imx_sdhci_esdhc_imx_data *data,
const struct esdhc_platform_data *pdata)
@@ -81,6 +86,13 @@ struct platform_device *__init imx_add_sdhci_esdhc_imx(
},
};
+ /*
+ * If machine does not provide pdata, use the default one
+ * which means no WP/CD support
+ */
+ if (!pdata)
+ pdata = &default_esdhc_pdata;
+
return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
ARRAY_SIZE(res), pdata, sizeof(*pdata));
}
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
index 86003f4..aaf9748 100644
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -10,17 +10,34 @@
#ifndef __ASM_ARCH_IMX_ESDHC_H
#define __ASM_ARCH_IMX_ESDHC_H
+enum wp_types {
+ ESDHC_WP_NONE, /* no WP, neither controller nor gpio */
+ ESDHC_WP_CONTROLLER, /* mmc controller internal WP */
+ ESDHC_WP_GPIO, /* external gpio pin for WP */
+};
+
+enum cd_types {
+ ESDHC_CD_NONE, /* no CD, neither controller nor gpio */
+ ESDHC_CD_CONTROLLER, /* mmc controller internal CD */
+ ESDHC_CD_GPIO, /* external gpio pin for CD */
+ ESDHC_CD_PERMANENT, /* no CD, card permanently wired to host */
+};
+
/**
- * struct esdhc_platform_data - optional platform data for esdhc on i.MX
+ * struct esdhc_platform_data - platform data for esdhc on i.MX
*
- * strongly recommended for i.MX25/35, not needed for other variants
+ * ESDHC_WP(CD)_CONTROLLER type is not available on i.MX25/35.
*
- * @wp_gpio: gpio for write_protect (-EINVAL if unused)
- * @cd_gpio: gpio for card_detect interrupt (-EINVAL if unused)
+ * @wp_gpio: gpio for write_protect
+ * @cd_gpio: gpio for card_detect interrupt
+ * @wp_type: type of write_protect method (see wp_types enum above)
+ * @cd_type: type of card_detect method (see cd_types enum above)
*/
struct esdhc_platform_data {
unsigned int wp_gpio;
unsigned int cd_gpio;
+ enum wp_types wp_type;
+ enum cd_types cd_type;
};
#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 79b7a9a..91d9579 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -29,7 +29,6 @@
#define SDHCI_VENDOR_SPEC 0xC0
#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002
-#define ESDHC_FLAG_GPIO_FOR_CD (1 << 0)
/*
* The CMDTYPE of the CMD register (offset 0xE) should be set to
* "11" when the STOP CMD12 is issued on imx53 to abort one
@@ -70,19 +69,15 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i
static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ struct esdhc_platform_data *boarddata =
+ host->mmc->parent->platform_data;
- /* fake CARD_PRESENT flag on mx25/35 */
+ /* fake CARD_PRESENT flag */
u32 val = readl(host->ioaddr + reg);
if (unlikely((reg == SDHCI_PRESENT_STATE)
- && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) {
- struct esdhc_platform_data *boarddata =
- host->mmc->parent->platform_data;
-
- if (boarddata && gpio_is_valid(boarddata->cd_gpio)
- && gpio_get_value(boarddata->cd_gpio))
+ && gpio_is_valid(boarddata->cd_gpio))) {
+ if (gpio_get_value(boarddata->cd_gpio))
/* no card, if a valid gpio says so... */
val &= ~SDHCI_CARD_PRESENT;
else
@@ -97,12 +92,13 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ struct esdhc_platform_data *boarddata =
+ host->mmc->parent->platform_data;
if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
- && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD)))
+ && (boarddata->cd_type == ESDHC_CD_GPIO)))
/*
* 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);
@@ -201,6 +197,25 @@ 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;
+
+ switch (boarddata->wp_type) {
+ case ESDHC_WP_GPIO:
+ if (gpio_is_valid(boarddata->wp_gpio))
+ return gpio_get_value(boarddata->wp_gpio);
+ case ESDHC_WP_CONTROLLER:
+ return !(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
+ SDHCI_WRITE_PROTECT);
+ case ESDHC_WP_NONE:
+ break;
+ }
+
+ return -ENOSYS;
+}
+
static struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl_le,
.read_w = esdhc_readw_le,
@@ -212,6 +227,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.get_min_clock = esdhc_pltfm_get_min_clock,
.get_max_blk_size = esdhc_pltfm_get_max_blk_size,
.get_max_blk_count = esdhc_pltfm_get_max_blk_count,
+ .get_ro = esdhc_pltfm_get_ro,
};
static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
@@ -221,17 +237,6 @@ static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
.ops = &sdhci_esdhc_ops,
};
-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 irqreturn_t cd_irq(int irq, void *data)
{
struct sdhci_host *sdhost = (struct sdhci_host *)data;
@@ -272,23 +277,34 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (!cpu_is_mx25())
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
- if (cpu_is_mx25() || cpu_is_mx35()) {
- /* write_protect can't be routed to controller, use gpio */
- sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
- }
-
if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
boarddata = host->mmc->parent->platform_data;
- if (boarddata) {
+ if (!boarddata) {
+ dev_err(mmc_dev(host->mmc), "no board data!\n");
+ err = -EINVAL;
+ goto no_board_data;
+ }
+
+ /* write_protect */
+ if (boarddata->wp_type == ESDHC_WP_GPIO) {
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;
+ "no write-protect pin available!\n");
+ boarddata->wp_gpio = -EINVAL;
}
+ } else {
+ boarddata->wp_gpio = -EINVAL;
+ }
+ /* card_detect */
+ if (boarddata->cd_type != ESDHC_CD_GPIO)
+ boarddata->cd_gpio = -EINVAL;
+
+ switch (boarddata->cd_type) {
+ case ESDHC_CD_GPIO:
err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
if (err) {
dev_warn(mmc_dev(host->mmc),
@@ -296,10 +312,6 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
goto no_card_detect_pin;
}
- /* i.MX5x has issues to be researched */
- if (!cpu_is_mx25() && !cpu_is_mx35())
- goto not_supported;
-
err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
mmc_hostname(host->mmc), host);
@@ -307,10 +319,19 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
dev_warn(mmc_dev(host->mmc), "request irq error\n");
goto no_card_detect_irq;
}
+ /* fall through */
- imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD;
- /* Now we have a working card_detect again */
+ case ESDHC_CD_CONTROLLER:
+ /* we have a working card_detect back */
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ break;
+
+ case ESDHC_CD_PERMANENT:
+ host->mmc->caps = MMC_CAP_NONREMOVABLE;
+ break;
+
+ case ESDHC_CD_NONE:
+ break;
}
err = sdhci_add_host(host);
@@ -319,16 +340,20 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
return 0;
- no_card_detect_irq:
- gpio_free(boarddata->cd_gpio);
- no_card_detect_pin:
- boarddata->cd_gpio = err;
- not_supported:
- kfree(imx_data);
- err_add_host:
+err_add_host:
+ if (gpio_is_valid(boarddata->cd_gpio))
+ free_irq(gpio_to_irq(boarddata->cd_gpio), host);
+no_card_detect_irq:
+ if (gpio_is_valid(boarddata->cd_gpio))
+ gpio_free(boarddata->cd_gpio);
+ if (gpio_is_valid(boarddata->wp_gpio))
+ gpio_free(boarddata->wp_gpio);
+no_card_detect_pin:
+no_board_data:
clk_disable(pltfm_host->clk);
clk_put(pltfm_host->clk);
- err_clk_get:
+err_clk_get:
+ kfree(imx_data);
sdhci_pltfm_free(pdev);
return err;
}
@@ -343,14 +368,12 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
sdhci_remove_host(host, dead);
- if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+ if (gpio_is_valid(boarddata->wp_gpio))
gpio_free(boarddata->wp_gpio);
- if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
+ if (gpio_is_valid(boarddata->cd_gpio)) {
+ free_irq(gpio_to_irq(boarddata->cd_gpio), host);
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);
--
1.7.4.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2011-06-17 8:18 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-15 11:15 [PATCH v2 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5 Shawn Guo
2011-06-15 11:15 ` [PATCH v2 1/4] mmc: sdhci: fix interrupt storm from card detection Shawn Guo
2011-06-15 11:15 ` [PATCH v2 2/4] mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared Shawn Guo
2011-06-16 12:01 ` Wolfram Sang
2011-06-15 11:15 ` [PATCH v2 3/4] mmc: sdhci-esdhc-imx: remove "WP" from flag ESDHC_FLAG_GPIO_FOR_CD_WP Shawn Guo
2011-06-15 11:15 ` [PATCH v2 4/4] mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5 Shawn Guo
2011-06-16 12:10 ` Wolfram Sang
2011-06-17 8:18 ` [PATCH v2 4/4 RESEND] " Shawn Guo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).