aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c3
-rw-r--r--arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c3
-rw-r--r--arch/arm/mach-imx/mach-mx25_3ds.c2
-rw-r--r--arch/arm/mach-imx/mach-pcm043.c2
-rw-r--r--arch/arm/mach-mx5/board-mx51_babbage.c14
-rw-r--r--arch/arm/mach-mx5/board-mx53_loco.c4
-rw-r--r--arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c12
-rw-r--r--arch/arm/plat-mxc/include/mach/esdhc.h25
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c138
9 files changed, 140 insertions, 63 deletions
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
index 01ebcb31e482..66e8726253fa 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 = {
225 225
226static struct esdhc_platform_data sd1_pdata = { 226static struct esdhc_platform_data sd1_pdata = {
227 .cd_gpio = GPIO_SD1CD, 227 .cd_gpio = GPIO_SD1CD,
228 .wp_gpio = -EINVAL, 228 .cd_type = ESDHC_CD_GPIO,
229 .wp_type = ESDHC_WP_NONE,
229}; 230};
230 231
231/* 232/*
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
index 558eb526ba56..0f0af02b3182 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 = {
236 236
237static struct esdhc_platform_data sd1_pdata = { 237static struct esdhc_platform_data sd1_pdata = {
238 .cd_gpio = GPIO_SD1CD, 238 .cd_gpio = GPIO_SD1CD,
239 .wp_gpio = -EINVAL, 239 .cd_type = ESDHC_CD_GPIO,
240 .wp_type = ESDHC_WP_NONE,
240}; 241};
241 242
242/* 243/*
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index 01534bb61305..7f66a91df361 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 = {
215static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = { 215static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {
216 .wp_gpio = SD1_GPIO_WP, 216 .wp_gpio = SD1_GPIO_WP,
217 .cd_gpio = SD1_GPIO_CD, 217 .cd_gpio = SD1_GPIO_CD,
218 .wp_type = ESDHC_WP_GPIO,
219 .cd_type = ESDHC_CD_GPIO,
218}; 220};
219 221
220static void __init mx25pdk_init(void) 222static void __init mx25pdk_init(void)
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 163cc318cafb..660ec3e80cf8 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);
349static struct esdhc_platform_data sd1_pdata = { 349static struct esdhc_platform_data sd1_pdata = {
350 .wp_gpio = SD1_GPIO_WP, 350 .wp_gpio = SD1_GPIO_WP,
351 .cd_gpio = SD1_GPIO_CD, 351 .cd_gpio = SD1_GPIO_CD,
352 .wp_type = ESDHC_WP_GPIO,
353 .cd_type = ESDHC_CD_GPIO,
352}; 354};
353 355
354/* 356/*
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index 15c600026aee..e400b09109ce 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -41,8 +41,6 @@
41#define BABBAGE_POWER_KEY IMX_GPIO_NR(2, 21) 41#define BABBAGE_POWER_KEY IMX_GPIO_NR(2, 21)
42#define BABBAGE_ECSPI1_CS0 IMX_GPIO_NR(4, 24) 42#define BABBAGE_ECSPI1_CS0 IMX_GPIO_NR(4, 24)
43#define BABBAGE_ECSPI1_CS1 IMX_GPIO_NR(4, 25) 43#define BABBAGE_ECSPI1_CS1 IMX_GPIO_NR(4, 25)
44#define BABBAGE_SD1_CD IMX_GPIO_NR(1, 0)
45#define BABBAGE_SD1_WP IMX_GPIO_NR(1, 1)
46#define BABBAGE_SD2_CD IMX_GPIO_NR(1, 6) 44#define BABBAGE_SD2_CD IMX_GPIO_NR(1, 6)
47#define BABBAGE_SD2_WP IMX_GPIO_NR(1, 5) 45#define BABBAGE_SD2_WP IMX_GPIO_NR(1, 5)
48 46
@@ -146,8 +144,9 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
146 MX51_PAD_SD1_DATA1__SD1_DATA1, 144 MX51_PAD_SD1_DATA1__SD1_DATA1,
147 MX51_PAD_SD1_DATA2__SD1_DATA2, 145 MX51_PAD_SD1_DATA2__SD1_DATA2,
148 MX51_PAD_SD1_DATA3__SD1_DATA3, 146 MX51_PAD_SD1_DATA3__SD1_DATA3,
149 MX51_PAD_GPIO1_0__GPIO1_0, 147 /* CD/WP from controller */
150 MX51_PAD_GPIO1_1__GPIO1_1, 148 MX51_PAD_GPIO1_0__SD1_CD,
149 MX51_PAD_GPIO1_1__SD1_WP,
151 150
152 /* SD 2 */ 151 /* SD 2 */
153 MX51_PAD_SD2_CMD__SD2_CMD, 152 MX51_PAD_SD2_CMD__SD2_CMD,
@@ -156,6 +155,7 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
156 MX51_PAD_SD2_DATA1__SD2_DATA1, 155 MX51_PAD_SD2_DATA1__SD2_DATA1,
157 MX51_PAD_SD2_DATA2__SD2_DATA2, 156 MX51_PAD_SD2_DATA2__SD2_DATA2,
158 MX51_PAD_SD2_DATA3__SD2_DATA3, 157 MX51_PAD_SD2_DATA3__SD2_DATA3,
158 /* CD/WP gpio */
159 MX51_PAD_GPIO1_6__GPIO1_6, 159 MX51_PAD_GPIO1_6__GPIO1_6,
160 MX51_PAD_GPIO1_5__GPIO1_5, 160 MX51_PAD_GPIO1_5__GPIO1_5,
161 161
@@ -340,13 +340,15 @@ static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
340}; 340};
341 341
342static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = { 342static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
343 .cd_gpio = BABBAGE_SD1_CD, 343 .cd_type = ESDHC_CD_CONTROLLER,
344 .wp_gpio = BABBAGE_SD1_WP, 344 .wp_type = ESDHC_WP_CONTROLLER,
345}; 345};
346 346
347static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = { 347static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
348 .cd_gpio = BABBAGE_SD2_CD, 348 .cd_gpio = BABBAGE_SD2_CD,
349 .wp_gpio = BABBAGE_SD2_WP, 349 .wp_gpio = BABBAGE_SD2_WP,
350 .cd_type = ESDHC_CD_GPIO,
351 .wp_type = ESDHC_WP_GPIO,
350}; 352};
351 353
352/* 354/*
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 54be525e2bd7..4e1d51d252dc 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 = {
210 210
211static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = { 211static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
212 .cd_gpio = LOCO_SD1_CD, 212 .cd_gpio = LOCO_SD1_CD,
213 .cd_type = ESDHC_CD_GPIO,
214 .wp_type = ESDHC_WP_NONE,
213}; 215};
214 216
215static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = { 217static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
216 .cd_gpio = LOCO_SD3_CD, 218 .cd_gpio = LOCO_SD3_CD,
217 .wp_gpio = LOCO_SD3_WP, 219 .wp_gpio = LOCO_SD3_WP,
220 .cd_type = ESDHC_CD_GPIO,
221 .wp_type = ESDHC_WP_GPIO,
218}; 222};
219 223
220static inline void mx53_loco_fec_reset(void) 224static 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 6b2940b93d94..79d6d711d123 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 = {
65}; 65};
66#endif /* ifdef CONFIG_SOC_IMX53 */ 66#endif /* ifdef CONFIG_SOC_IMX53 */
67 67
68static const struct esdhc_platform_data default_esdhc_pdata __initconst = {
69 .wp_type = ESDHC_WP_NONE,
70 .cd_type = ESDHC_CD_NONE,
71};
72
68struct platform_device *__init imx_add_sdhci_esdhc_imx( 73struct platform_device *__init imx_add_sdhci_esdhc_imx(
69 const struct imx_sdhci_esdhc_imx_data *data, 74 const struct imx_sdhci_esdhc_imx_data *data,
70 const struct esdhc_platform_data *pdata) 75 const struct esdhc_platform_data *pdata)
@@ -81,6 +86,13 @@ struct platform_device *__init imx_add_sdhci_esdhc_imx(
81 }, 86 },
82 }; 87 };
83 88
89 /*
90 * If machine does not provide pdata, use the default one
91 * which means no WP/CD support
92 */
93 if (!pdata)
94 pdata = &default_esdhc_pdata;
95
84 return imx_add_platform_device("sdhci-esdhc-imx", data->id, res, 96 return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
85 ARRAY_SIZE(res), pdata, sizeof(*pdata)); 97 ARRAY_SIZE(res), pdata, sizeof(*pdata));
86} 98}
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
index 86003f411755..aaf97481f413 100644
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -10,17 +10,34 @@
10#ifndef __ASM_ARCH_IMX_ESDHC_H 10#ifndef __ASM_ARCH_IMX_ESDHC_H
11#define __ASM_ARCH_IMX_ESDHC_H 11#define __ASM_ARCH_IMX_ESDHC_H
12 12
13enum wp_types {
14 ESDHC_WP_NONE, /* no WP, neither controller nor gpio */
15 ESDHC_WP_CONTROLLER, /* mmc controller internal WP */
16 ESDHC_WP_GPIO, /* external gpio pin for WP */
17};
18
19enum cd_types {
20 ESDHC_CD_NONE, /* no CD, neither controller nor gpio */
21 ESDHC_CD_CONTROLLER, /* mmc controller internal CD */
22 ESDHC_CD_GPIO, /* external gpio pin for CD */
23 ESDHC_CD_PERMANENT, /* no CD, card permanently wired to host */
24};
25
13/** 26/**
14 * struct esdhc_platform_data - optional platform data for esdhc on i.MX 27 * struct esdhc_platform_data - platform data for esdhc on i.MX
15 * 28 *
16 * strongly recommended for i.MX25/35, not needed for other variants 29 * ESDHC_WP(CD)_CONTROLLER type is not available on i.MX25/35.
17 * 30 *
18 * @wp_gpio: gpio for write_protect (-EINVAL if unused) 31 * @wp_gpio: gpio for write_protect
19 * @cd_gpio: gpio for card_detect interrupt (-EINVAL if unused) 32 * @cd_gpio: gpio for card_detect interrupt
33 * @wp_type: type of write_protect method (see wp_types enum above)
34 * @cd_type: type of card_detect method (see cd_types enum above)
20 */ 35 */
21 36
22struct esdhc_platform_data { 37struct esdhc_platform_data {
23 unsigned int wp_gpio; 38 unsigned int wp_gpio;
24 unsigned int cd_gpio; 39 unsigned int cd_gpio;
40 enum wp_types wp_type;
41 enum cd_types cd_type;
25}; 42};
26#endif /* __ASM_ARCH_IMX_ESDHC_H */ 43#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 710b706f4fcf..4269bb498ff0 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -29,7 +29,6 @@
29#define SDHCI_VENDOR_SPEC 0xC0 29#define SDHCI_VENDOR_SPEC 0xC0
30#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002 30#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002
31 31
32#define ESDHC_FLAG_GPIO_FOR_CD (1 << 0)
33/* 32/*
34 * The CMDTYPE of the CMD register (offset 0xE) should be set to 33 * The CMDTYPE of the CMD register (offset 0xE) should be set to
35 * "11" when the STOP CMD12 is issued on imx53 to abort one 34 * "11" when the STOP CMD12 is issued on imx53 to abort one
@@ -58,19 +57,15 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i
58 57
59static u32 esdhc_readl_le(struct sdhci_host *host, int reg) 58static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
60{ 59{
61 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 60 struct esdhc_platform_data *boarddata =
62 struct pltfm_imx_data *imx_data = pltfm_host->priv; 61 host->mmc->parent->platform_data;
63 62
64 /* fake CARD_PRESENT flag on mx25/35 */ 63 /* fake CARD_PRESENT flag */
65 u32 val = readl(host->ioaddr + reg); 64 u32 val = readl(host->ioaddr + reg);
66 65
67 if (unlikely((reg == SDHCI_PRESENT_STATE) 66 if (unlikely((reg == SDHCI_PRESENT_STATE)
68 && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) { 67 && gpio_is_valid(boarddata->cd_gpio))) {
69 struct esdhc_platform_data *boarddata = 68 if (gpio_get_value(boarddata->cd_gpio))
70 host->mmc->parent->platform_data;
71
72 if (boarddata && gpio_is_valid(boarddata->cd_gpio)
73 && gpio_get_value(boarddata->cd_gpio))
74 /* no card, if a valid gpio says so... */ 69 /* no card, if a valid gpio says so... */
75 val &= ~SDHCI_CARD_PRESENT; 70 val &= ~SDHCI_CARD_PRESENT;
76 else 71 else
@@ -85,12 +80,13 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
85{ 80{
86 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 81 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
87 struct pltfm_imx_data *imx_data = pltfm_host->priv; 82 struct pltfm_imx_data *imx_data = pltfm_host->priv;
83 struct esdhc_platform_data *boarddata =
84 host->mmc->parent->platform_data;
88 85
89 if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE) 86 if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
90 && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) 87 && (boarddata->cd_type == ESDHC_CD_GPIO)))
91 /* 88 /*
92 * these interrupts won't work with a custom card_detect gpio 89 * these interrupts won't work with a custom card_detect gpio
93 * (only applied to mx25/35)
94 */ 90 */
95 val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); 91 val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
96 92
@@ -173,6 +169,17 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
173 return; 169 return;
174 } 170 }
175 esdhc_clrset_le(host, 0xff, val, reg); 171 esdhc_clrset_le(host, 0xff, val, reg);
172
173 /*
174 * The esdhc has a design violation to SDHC spec which tells
175 * that software reset should not affect card detection circuit.
176 * But esdhc clears its SYSCTL register bits [0..2] during the
177 * software reset. This will stop those clocks that card detection
178 * circuit relies on. To work around it, we turn the clocks on back
179 * to keep card detection circuit functional.
180 */
181 if ((reg == SDHCI_SOFTWARE_RESET) && (val & 1))
182 esdhc_clrset_le(host, 0x7, 0x7, ESDHC_SYSTEM_CONTROL);
176} 183}
177 184
178static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) 185static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
@@ -189,6 +196,25 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
189 return clk_get_rate(pltfm_host->clk) / 256 / 16; 196 return clk_get_rate(pltfm_host->clk) / 256 / 16;
190} 197}
191 198
199static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
200{
201 struct esdhc_platform_data *boarddata =
202 host->mmc->parent->platform_data;
203
204 switch (boarddata->wp_type) {
205 case ESDHC_WP_GPIO:
206 if (gpio_is_valid(boarddata->wp_gpio))
207 return gpio_get_value(boarddata->wp_gpio);
208 case ESDHC_WP_CONTROLLER:
209 return !(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
210 SDHCI_WRITE_PROTECT);
211 case ESDHC_WP_NONE:
212 break;
213 }
214
215 return -ENOSYS;
216}
217
192static struct sdhci_ops sdhci_esdhc_ops = { 218static struct sdhci_ops sdhci_esdhc_ops = {
193 .read_l = esdhc_readl_le, 219 .read_l = esdhc_readl_le,
194 .read_w = esdhc_readw_le, 220 .read_w = esdhc_readw_le,
@@ -198,6 +224,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
198 .set_clock = esdhc_set_clock, 224 .set_clock = esdhc_set_clock,
199 .get_max_clock = esdhc_pltfm_get_max_clock, 225 .get_max_clock = esdhc_pltfm_get_max_clock,
200 .get_min_clock = esdhc_pltfm_get_min_clock, 226 .get_min_clock = esdhc_pltfm_get_min_clock,
227 .get_ro = esdhc_pltfm_get_ro,
201}; 228};
202 229
203static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { 230static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
@@ -207,17 +234,6 @@ static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
207 .ops = &sdhci_esdhc_ops, 234 .ops = &sdhci_esdhc_ops,
208}; 235};
209 236
210static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
211{
212 struct esdhc_platform_data *boarddata =
213 host->mmc->parent->platform_data;
214
215 if (boarddata && gpio_is_valid(boarddata->wp_gpio))
216 return gpio_get_value(boarddata->wp_gpio);
217 else
218 return -ENOSYS;
219}
220
221static irqreturn_t cd_irq(int irq, void *data) 237static irqreturn_t cd_irq(int irq, void *data)
222{ 238{
223 struct sdhci_host *sdhost = (struct sdhci_host *)data; 239 struct sdhci_host *sdhost = (struct sdhci_host *)data;
@@ -258,47 +274,65 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
258 if (!cpu_is_mx25()) 274 if (!cpu_is_mx25())
259 host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 275 host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
260 276
261 if (cpu_is_mx25() || cpu_is_mx35()) { 277 if (cpu_is_mx25() || cpu_is_mx35())
262 /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */ 278 /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
263 host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK; 279 host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
264 /* write_protect can't be routed to controller, use gpio */
265 sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
266 }
267 280
268 if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51())) 281 if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
269 imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT; 282 imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
270 283
271 boarddata = host->mmc->parent->platform_data; 284 boarddata = host->mmc->parent->platform_data;
272 if (boarddata) { 285 if (!boarddata) {
286 dev_err(mmc_dev(host->mmc), "no board data!\n");
287 err = -EINVAL;
288 goto no_board_data;
289 }
290
291 /* write_protect */
292 if (boarddata->wp_type == ESDHC_WP_GPIO) {
273 err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP"); 293 err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
274 if (err) { 294 if (err) {
275 dev_warn(mmc_dev(host->mmc), 295 dev_warn(mmc_dev(host->mmc),
276 "no write-protect pin available!\n"); 296 "no write-protect pin available!\n");
277 boarddata->wp_gpio = err; 297 boarddata->wp_gpio = -EINVAL;
278 } 298 }
299 } else {
300 boarddata->wp_gpio = -EINVAL;
301 }
302
303 /* card_detect */
304 if (boarddata->cd_type != ESDHC_CD_GPIO)
305 boarddata->cd_gpio = -EINVAL;
279 306
307 switch (boarddata->cd_type) {
308 case ESDHC_CD_GPIO:
280 err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD"); 309 err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
281 if (err) { 310 if (err) {
282 dev_warn(mmc_dev(host->mmc), 311 dev_err(mmc_dev(host->mmc),
283 "no card-detect pin available!\n"); 312 "no card-detect pin available!\n");
284 goto no_card_detect_pin; 313 goto no_card_detect_pin;
285 } 314 }
286 315
287 /* i.MX5x has issues to be researched */
288 if (!cpu_is_mx25() && !cpu_is_mx35())
289 goto not_supported;
290
291 err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq, 316 err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
292 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, 317 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
293 mmc_hostname(host->mmc), host); 318 mmc_hostname(host->mmc), host);
294 if (err) { 319 if (err) {
295 dev_warn(mmc_dev(host->mmc), "request irq error\n"); 320 dev_err(mmc_dev(host->mmc), "request irq error\n");
296 goto no_card_detect_irq; 321 goto no_card_detect_irq;
297 } 322 }
323 /* fall through */
298 324
299 imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD; 325 case ESDHC_CD_CONTROLLER:
300 /* Now we have a working card_detect again */ 326 /* we have a working card_detect back */
301 host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; 327 host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
328 break;
329
330 case ESDHC_CD_PERMANENT:
331 host->mmc->caps = MMC_CAP_NONREMOVABLE;
332 break;
333
334 case ESDHC_CD_NONE:
335 break;
302 } 336 }
303 337
304 err = sdhci_add_host(host); 338 err = sdhci_add_host(host);
@@ -307,16 +341,20 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
307 341
308 return 0; 342 return 0;
309 343
310 no_card_detect_irq: 344err_add_host:
311 gpio_free(boarddata->cd_gpio); 345 if (gpio_is_valid(boarddata->cd_gpio))
312 no_card_detect_pin: 346 free_irq(gpio_to_irq(boarddata->cd_gpio), host);
313 boarddata->cd_gpio = err; 347no_card_detect_irq:
314 not_supported: 348 if (gpio_is_valid(boarddata->cd_gpio))
315 kfree(imx_data); 349 gpio_free(boarddata->cd_gpio);
316 err_add_host: 350 if (gpio_is_valid(boarddata->wp_gpio))
351 gpio_free(boarddata->wp_gpio);
352no_card_detect_pin:
353no_board_data:
317 clk_disable(pltfm_host->clk); 354 clk_disable(pltfm_host->clk);
318 clk_put(pltfm_host->clk); 355 clk_put(pltfm_host->clk);
319 err_clk_get: 356err_clk_get:
357 kfree(imx_data);
320 sdhci_pltfm_free(pdev); 358 sdhci_pltfm_free(pdev);
321 return err; 359 return err;
322} 360}
@@ -331,14 +369,12 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
331 369
332 sdhci_remove_host(host, dead); 370 sdhci_remove_host(host, dead);
333 371
334 if (boarddata && gpio_is_valid(boarddata->wp_gpio)) 372 if (gpio_is_valid(boarddata->wp_gpio))
335 gpio_free(boarddata->wp_gpio); 373 gpio_free(boarddata->wp_gpio);
336 374
337 if (boarddata && gpio_is_valid(boarddata->cd_gpio)) { 375 if (gpio_is_valid(boarddata->cd_gpio)) {
376 free_irq(gpio_to_irq(boarddata->cd_gpio), host);
338 gpio_free(boarddata->cd_gpio); 377 gpio_free(boarddata->cd_gpio);
339
340 if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
341 free_irq(gpio_to_irq(boarddata->cd_gpio), host);
342 } 378 }
343 379
344 clk_disable(pltfm_host->clk); 380 clk_disable(pltfm_host->clk);