diff options
-rw-r--r-- | arch/arm/configs/rx51_defconfig | 4 | ||||
-rw-r--r-- | arch/arm/mach-omap2/mmc-twl4030.c | 352 | ||||
-rw-r--r-- | arch/arm/mach-omap2/mmc-twl4030.h | 4 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/mmc.h | 28 | ||||
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 352 |
5 files changed, 391 insertions, 349 deletions
diff --git a/arch/arm/configs/rx51_defconfig b/arch/arm/configs/rx51_defconfig index b6eeebb31761..426ae948aefe 100644 --- a/arch/arm/configs/rx51_defconfig +++ b/arch/arm/configs/rx51_defconfig | |||
@@ -1354,7 +1354,7 @@ CONFIG_USB_OTG_UTILS=y | |||
1354 | # CONFIG_USB_GPIO_VBUS is not set | 1354 | # CONFIG_USB_GPIO_VBUS is not set |
1355 | # CONFIG_ISP1301_OMAP is not set | 1355 | # CONFIG_ISP1301_OMAP is not set |
1356 | CONFIG_TWL4030_USB=y | 1356 | CONFIG_TWL4030_USB=y |
1357 | CONFIG_MMC=y | 1357 | CONFIG_MMC=m |
1358 | # CONFIG_MMC_DEBUG is not set | 1358 | # CONFIG_MMC_DEBUG is not set |
1359 | # CONFIG_MMC_UNSAFE_RESUME is not set | 1359 | # CONFIG_MMC_UNSAFE_RESUME is not set |
1360 | 1360 | ||
@@ -1362,7 +1362,7 @@ CONFIG_MMC=y | |||
1362 | # MMC/SD/SDIO Card Drivers | 1362 | # MMC/SD/SDIO Card Drivers |
1363 | # | 1363 | # |
1364 | CONFIG_MMC_BLOCK=m | 1364 | CONFIG_MMC_BLOCK=m |
1365 | CONFIG_MMC_BLOCK_BOUNCE=y | 1365 | # CONFIG_MMC_BLOCK_BOUNCE is not set |
1366 | # CONFIG_SDIO_UART is not set | 1366 | # CONFIG_SDIO_UART is not set |
1367 | # CONFIG_MMC_TEST is not set | 1367 | # CONFIG_MMC_TEST is not set |
1368 | 1368 | ||
diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index 8afe9dd3f150..6f8f29e99ff2 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c | |||
@@ -9,26 +9,17 @@ | |||
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | #include <linux/err.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/io.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/module.h> | 14 | #include <linux/string.h> |
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
18 | #include <linux/gpio.h> | ||
19 | #include <linux/mmc/host.h> | ||
20 | #include <linux/regulator/consumer.h> | ||
21 | |||
22 | #include <mach/hardware.h> | 16 | #include <mach/hardware.h> |
23 | #include <plat/control.h> | 17 | #include <plat/control.h> |
24 | #include <plat/mmc.h> | 18 | #include <plat/mmc.h> |
25 | #include <plat/board.h> | ||
26 | 19 | ||
27 | #include "mmc-twl4030.h" | 20 | #include "mmc-twl4030.h" |
28 | 21 | ||
29 | 22 | #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) | |
30 | #if defined(CONFIG_REGULATOR) && \ | ||
31 | (defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)) | ||
32 | 23 | ||
33 | static u16 control_pbias_offset; | 24 | static u16 control_pbias_offset; |
34 | static u16 control_devconf1_offset; | 25 | static u16 control_devconf1_offset; |
@@ -36,168 +27,9 @@ static u16 control_devconf1_offset; | |||
36 | #define HSMMC_NAME_LEN 9 | 27 | #define HSMMC_NAME_LEN 9 |
37 | 28 | ||
38 | static struct twl_mmc_controller { | 29 | static struct twl_mmc_controller { |
39 | struct omap_mmc_platform_data *mmc; | ||
40 | /* Vcc == configured supply | ||
41 | * Vcc_alt == optional | ||
42 | * - MMC1, supply for DAT4..DAT7 | ||
43 | * - MMC2/MMC2, external level shifter voltage supply, for | ||
44 | * chip (SDIO, eMMC, etc) or transceiver (MMC2 only) | ||
45 | */ | ||
46 | struct regulator *vcc; | ||
47 | struct regulator *vcc_aux; | ||
48 | char name[HSMMC_NAME_LEN + 1]; | 30 | char name[HSMMC_NAME_LEN + 1]; |
49 | } hsmmc[OMAP34XX_NR_MMC]; | 31 | } hsmmc[OMAP34XX_NR_MMC]; |
50 | 32 | ||
51 | static int twl_mmc_card_detect(int irq) | ||
52 | { | ||
53 | unsigned i; | ||
54 | |||
55 | for (i = 0; i < ARRAY_SIZE(hsmmc); i++) { | ||
56 | struct omap_mmc_platform_data *mmc; | ||
57 | |||
58 | mmc = hsmmc[i].mmc; | ||
59 | if (!mmc) | ||
60 | continue; | ||
61 | if (irq != mmc->slots[0].card_detect_irq) | ||
62 | continue; | ||
63 | |||
64 | /* NOTE: assumes card detect signal is active-low */ | ||
65 | return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); | ||
66 | } | ||
67 | return -ENOSYS; | ||
68 | } | ||
69 | |||
70 | static int twl_mmc_get_ro(struct device *dev, int slot) | ||
71 | { | ||
72 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
73 | |||
74 | /* NOTE: assumes write protect signal is active-high */ | ||
75 | return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); | ||
76 | } | ||
77 | |||
78 | static int twl_mmc_get_cover_state(struct device *dev, int slot) | ||
79 | { | ||
80 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
81 | |||
82 | /* NOTE: assumes card detect signal is active-low */ | ||
83 | return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * MMC Slot Initialization. | ||
88 | */ | ||
89 | static int twl_mmc_late_init(struct device *dev) | ||
90 | { | ||
91 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
92 | int ret = 0; | ||
93 | int i; | ||
94 | |||
95 | /* MMC/SD/SDIO doesn't require a card detect switch */ | ||
96 | if (gpio_is_valid(mmc->slots[0].switch_pin)) { | ||
97 | ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd"); | ||
98 | if (ret) | ||
99 | goto done; | ||
100 | ret = gpio_direction_input(mmc->slots[0].switch_pin); | ||
101 | if (ret) | ||
102 | goto err; | ||
103 | } | ||
104 | |||
105 | /* require at least main regulator */ | ||
106 | for (i = 0; i < ARRAY_SIZE(hsmmc); i++) { | ||
107 | if (hsmmc[i].name == mmc->slots[0].name) { | ||
108 | struct regulator *reg; | ||
109 | |||
110 | hsmmc[i].mmc = mmc; | ||
111 | |||
112 | reg = regulator_get(dev, "vmmc"); | ||
113 | if (IS_ERR(reg)) { | ||
114 | dev_dbg(dev, "vmmc regulator missing\n"); | ||
115 | /* HACK: until fixed.c regulator is usable, | ||
116 | * we don't require a main regulator | ||
117 | * for MMC2 or MMC3 | ||
118 | */ | ||
119 | if (i != 0) | ||
120 | break; | ||
121 | ret = PTR_ERR(reg); | ||
122 | hsmmc[i].vcc = NULL; | ||
123 | goto err; | ||
124 | } | ||
125 | hsmmc[i].vcc = reg; | ||
126 | mmc->slots[0].ocr_mask = mmc_regulator_get_ocrmask(reg); | ||
127 | |||
128 | /* allow an aux regulator */ | ||
129 | reg = regulator_get(dev, "vmmc_aux"); | ||
130 | hsmmc[i].vcc_aux = IS_ERR(reg) ? NULL : reg; | ||
131 | |||
132 | /* UGLY HACK: workaround regulator framework bugs. | ||
133 | * When the bootloader leaves a supply active, it's | ||
134 | * initialized with zero usecount ... and we can't | ||
135 | * disable it without first enabling it. Until the | ||
136 | * framework is fixed, we need a workaround like this | ||
137 | * (which is safe for MMC, but not in general). | ||
138 | */ | ||
139 | if (regulator_is_enabled(hsmmc[i].vcc) > 0) { | ||
140 | regulator_enable(hsmmc[i].vcc); | ||
141 | regulator_disable(hsmmc[i].vcc); | ||
142 | } | ||
143 | if (hsmmc[i].vcc_aux) { | ||
144 | if (regulator_is_enabled(reg) > 0) { | ||
145 | regulator_enable(reg); | ||
146 | regulator_disable(reg); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | break; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | return 0; | ||
155 | |||
156 | err: | ||
157 | gpio_free(mmc->slots[0].switch_pin); | ||
158 | done: | ||
159 | mmc->slots[0].card_detect_irq = 0; | ||
160 | mmc->slots[0].card_detect = NULL; | ||
161 | |||
162 | dev_err(dev, "err %d configuring card detect\n", ret); | ||
163 | return ret; | ||
164 | } | ||
165 | |||
166 | static void twl_mmc_cleanup(struct device *dev) | ||
167 | { | ||
168 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
169 | int i; | ||
170 | |||
171 | gpio_free(mmc->slots[0].switch_pin); | ||
172 | for(i = 0; i < ARRAY_SIZE(hsmmc); i++) { | ||
173 | regulator_put(hsmmc[i].vcc); | ||
174 | regulator_put(hsmmc[i].vcc_aux); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | #ifdef CONFIG_PM | ||
179 | |||
180 | static int twl_mmc_suspend(struct device *dev, int slot) | ||
181 | { | ||
182 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
183 | |||
184 | disable_irq(mmc->slots[0].card_detect_irq); | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int twl_mmc_resume(struct device *dev, int slot) | ||
189 | { | ||
190 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
191 | |||
192 | enable_irq(mmc->slots[0].card_detect_irq); | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | #else | ||
197 | #define twl_mmc_suspend NULL | ||
198 | #define twl_mmc_resume NULL | ||
199 | #endif | ||
200 | |||
201 | #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) | 33 | #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) |
202 | 34 | ||
203 | static int twl4030_mmc_get_context_loss(struct device *dev) | 35 | static int twl4030_mmc_get_context_loss(struct device *dev) |
@@ -210,12 +42,10 @@ static int twl4030_mmc_get_context_loss(struct device *dev) | |||
210 | #define twl4030_mmc_get_context_loss NULL | 42 | #define twl4030_mmc_get_context_loss NULL |
211 | #endif | 43 | #endif |
212 | 44 | ||
213 | static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, | 45 | static void hsmmc1_before_set_reg(struct device *dev, int slot, |
214 | int vdd) | 46 | int power_on, int vdd) |
215 | { | 47 | { |
216 | u32 reg, prog_io; | 48 | u32 reg, prog_io; |
217 | int ret = 0; | ||
218 | struct twl_mmc_controller *c = &hsmmc[0]; | ||
219 | struct omap_mmc_platform_data *mmc = dev->platform_data; | 49 | struct omap_mmc_platform_data *mmc = dev->platform_data; |
220 | 50 | ||
221 | /* | 51 | /* |
@@ -255,11 +85,22 @@ static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, | |||
255 | } | 85 | } |
256 | reg &= ~OMAP2_PBIASLITEPWRDNZ0; | 86 | reg &= ~OMAP2_PBIASLITEPWRDNZ0; |
257 | omap_ctrl_writel(reg, control_pbias_offset); | 87 | omap_ctrl_writel(reg, control_pbias_offset); |
88 | } else { | ||
89 | reg = omap_ctrl_readl(control_pbias_offset); | ||
90 | reg &= ~OMAP2_PBIASLITEPWRDNZ0; | ||
91 | omap_ctrl_writel(reg, control_pbias_offset); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | static void hsmmc1_after_set_reg(struct device *dev, int slot, | ||
96 | int power_on, int vdd) | ||
97 | { | ||
98 | u32 reg; | ||
258 | 99 | ||
259 | ret = mmc_regulator_set_ocr(c->vcc, vdd); | 100 | /* 100ms delay required for PBIAS configuration */ |
101 | msleep(100); | ||
260 | 102 | ||
261 | /* 100ms delay required for PBIAS configuration */ | 103 | if (power_on) { |
262 | msleep(100); | ||
263 | reg = omap_ctrl_readl(control_pbias_offset); | 104 | reg = omap_ctrl_readl(control_pbias_offset); |
264 | reg |= (OMAP2_PBIASLITEPWRDNZ0 | OMAP2_PBIASSPEEDCTRL0); | 105 | reg |= (OMAP2_PBIASLITEPWRDNZ0 | OMAP2_PBIASSPEEDCTRL0); |
265 | if ((1 << vdd) <= MMC_VDD_165_195) | 106 | if ((1 << vdd) <= MMC_VDD_165_195) |
@@ -269,60 +110,19 @@ static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, | |||
269 | omap_ctrl_writel(reg, control_pbias_offset); | 110 | omap_ctrl_writel(reg, control_pbias_offset); |
270 | } else { | 111 | } else { |
271 | reg = omap_ctrl_readl(control_pbias_offset); | 112 | reg = omap_ctrl_readl(control_pbias_offset); |
272 | reg &= ~OMAP2_PBIASLITEPWRDNZ0; | ||
273 | omap_ctrl_writel(reg, control_pbias_offset); | ||
274 | |||
275 | ret = mmc_regulator_set_ocr(c->vcc, 0); | ||
276 | |||
277 | /* 100ms delay required for PBIAS configuration */ | ||
278 | msleep(100); | ||
279 | reg = omap_ctrl_readl(control_pbias_offset); | ||
280 | reg |= (OMAP2_PBIASSPEEDCTRL0 | OMAP2_PBIASLITEPWRDNZ0 | | 113 | reg |= (OMAP2_PBIASSPEEDCTRL0 | OMAP2_PBIASLITEPWRDNZ0 | |
281 | OMAP2_PBIASLITEVMODE0); | 114 | OMAP2_PBIASLITEVMODE0); |
282 | omap_ctrl_writel(reg, control_pbias_offset); | 115 | omap_ctrl_writel(reg, control_pbias_offset); |
283 | } | 116 | } |
284 | |||
285 | return ret; | ||
286 | } | 117 | } |
287 | 118 | ||
288 | static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int vdd) | 119 | static void hsmmc23_before_set_reg(struct device *dev, int slot, |
120 | int power_on, int vdd) | ||
289 | { | 121 | { |
290 | int ret = 0; | ||
291 | struct twl_mmc_controller *c = NULL; | ||
292 | struct omap_mmc_platform_data *mmc = dev->platform_data; | 122 | struct omap_mmc_platform_data *mmc = dev->platform_data; |
293 | int i; | ||
294 | |||
295 | for (i = 1; i < ARRAY_SIZE(hsmmc); i++) { | ||
296 | if (mmc == hsmmc[i].mmc) { | ||
297 | c = &hsmmc[i]; | ||
298 | break; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | if (c == NULL) | ||
303 | return -ENODEV; | ||
304 | |||
305 | /* If we don't see a Vcc regulator, assume it's a fixed | ||
306 | * voltage always-on regulator. | ||
307 | */ | ||
308 | if (!c->vcc) | ||
309 | return 0; | ||
310 | 123 | ||
311 | /* | ||
312 | * Assume Vcc regulator is used only to power the card ... OMAP | ||
313 | * VDDS is used to power the pins, optionally with a transceiver to | ||
314 | * support cards using voltages other than VDDS (1.8V nominal). When a | ||
315 | * transceiver is used, DAT3..7 are muxed as transceiver control pins. | ||
316 | * | ||
317 | * In some cases this regulator won't support enable/disable; | ||
318 | * e.g. it's a fixed rail for a WLAN chip. | ||
319 | * | ||
320 | * In other cases vcc_aux switches interface power. Example, for | ||
321 | * eMMC cards it represents VccQ. Sometimes transceivers or SDIO | ||
322 | * chips/cards need an interface voltage rail too. | ||
323 | */ | ||
324 | if (power_on) { | 124 | if (power_on) { |
325 | /* only MMC2 supports a CLKIN */ | 125 | /* Only MMC2 supports a CLKIN */ |
326 | if (mmc->slots[0].internal_clock) { | 126 | if (mmc->slots[0].internal_clock) { |
327 | u32 reg; | 127 | u32 reg; |
328 | 128 | ||
@@ -330,76 +130,7 @@ static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int v | |||
330 | reg |= OMAP2_MMCSDIO2ADPCLKISEL; | 130 | reg |= OMAP2_MMCSDIO2ADPCLKISEL; |
331 | omap_ctrl_writel(reg, control_devconf1_offset); | 131 | omap_ctrl_writel(reg, control_devconf1_offset); |
332 | } | 132 | } |
333 | ret = mmc_regulator_set_ocr(c->vcc, vdd); | ||
334 | /* enable interface voltage rail, if needed */ | ||
335 | if (ret == 0 && c->vcc_aux) { | ||
336 | ret = regulator_enable(c->vcc_aux); | ||
337 | if (ret < 0) | ||
338 | ret = mmc_regulator_set_ocr(c->vcc, 0); | ||
339 | } | ||
340 | } else { | ||
341 | if (c->vcc_aux && (ret = regulator_is_enabled(c->vcc_aux)) > 0) | ||
342 | ret = regulator_disable(c->vcc_aux); | ||
343 | if (ret == 0) | ||
344 | ret = mmc_regulator_set_ocr(c->vcc, 0); | ||
345 | } | ||
346 | |||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | static int twl_mmc1_set_sleep(struct device *dev, int slot, int sleep, int vdd, | ||
351 | int cardsleep) | ||
352 | { | ||
353 | struct twl_mmc_controller *c = &hsmmc[0]; | ||
354 | int mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; | ||
355 | |||
356 | return regulator_set_mode(c->vcc, mode); | ||
357 | } | ||
358 | |||
359 | static int twl_mmc23_set_sleep(struct device *dev, int slot, int sleep, int vdd, | ||
360 | int cardsleep) | ||
361 | { | ||
362 | struct twl_mmc_controller *c = NULL; | ||
363 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
364 | int i, err, mode; | ||
365 | |||
366 | for (i = 1; i < ARRAY_SIZE(hsmmc); i++) { | ||
367 | if (mmc == hsmmc[i].mmc) { | ||
368 | c = &hsmmc[i]; | ||
369 | break; | ||
370 | } | ||
371 | } | 133 | } |
372 | |||
373 | if (c == NULL) | ||
374 | return -ENODEV; | ||
375 | |||
376 | /* | ||
377 | * If we don't see a Vcc regulator, assume it's a fixed | ||
378 | * voltage always-on regulator. | ||
379 | */ | ||
380 | if (!c->vcc) | ||
381 | return 0; | ||
382 | |||
383 | mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; | ||
384 | |||
385 | if (!c->vcc_aux) | ||
386 | return regulator_set_mode(c->vcc, mode); | ||
387 | |||
388 | if (cardsleep) { | ||
389 | /* VCC can be turned off if card is asleep */ | ||
390 | struct regulator *vcc_aux = c->vcc_aux; | ||
391 | |||
392 | c->vcc_aux = NULL; | ||
393 | if (sleep) | ||
394 | err = twl_mmc23_set_power(dev, slot, 0, 0); | ||
395 | else | ||
396 | err = twl_mmc23_set_power(dev, slot, 1, vdd); | ||
397 | c->vcc_aux = vcc_aux; | ||
398 | } else | ||
399 | err = regulator_set_mode(c->vcc, mode); | ||
400 | if (err) | ||
401 | return err; | ||
402 | return regulator_set_mode(c->vcc_aux, mode); | ||
403 | } | 134 | } |
404 | 135 | ||
405 | static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; | 136 | static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; |
@@ -413,7 +144,6 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | |||
413 | if (cpu_is_omap2430()) { | 144 | if (cpu_is_omap2430()) { |
414 | control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE; | 145 | control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE; |
415 | control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1; | 146 | control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1; |
416 | nr_hsmmc = 2; | ||
417 | } else { | 147 | } else { |
418 | control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE; | 148 | control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE; |
419 | control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1; | 149 | control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1; |
@@ -448,35 +178,15 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | |||
448 | mmc->slots[0].wires = c->wires; | 178 | mmc->slots[0].wires = c->wires; |
449 | mmc->slots[0].internal_clock = !c->ext_clock; | 179 | mmc->slots[0].internal_clock = !c->ext_clock; |
450 | mmc->dma_mask = 0xffffffff; | 180 | mmc->dma_mask = 0xffffffff; |
451 | mmc->init = twl_mmc_late_init; | ||
452 | |||
453 | /* note: twl4030 card detect GPIOs can disable VMMCx ... */ | ||
454 | if (gpio_is_valid(c->gpio_cd)) { | ||
455 | mmc->cleanup = twl_mmc_cleanup; | ||
456 | mmc->suspend = twl_mmc_suspend; | ||
457 | mmc->resume = twl_mmc_resume; | ||
458 | |||
459 | mmc->slots[0].switch_pin = c->gpio_cd; | ||
460 | mmc->slots[0].card_detect_irq = gpio_to_irq(c->gpio_cd); | ||
461 | if (c->cover_only) | ||
462 | mmc->slots[0].get_cover_state = twl_mmc_get_cover_state; | ||
463 | else | ||
464 | mmc->slots[0].card_detect = twl_mmc_card_detect; | ||
465 | } else | ||
466 | mmc->slots[0].switch_pin = -EINVAL; | ||
467 | 181 | ||
468 | mmc->get_context_loss_count = | 182 | mmc->get_context_loss_count = |
469 | twl4030_mmc_get_context_loss; | 183 | twl4030_mmc_get_context_loss; |
470 | 184 | ||
471 | /* write protect normally uses an OMAP gpio */ | 185 | mmc->slots[0].switch_pin = c->gpio_cd; |
472 | if (gpio_is_valid(c->gpio_wp)) { | 186 | mmc->slots[0].gpio_wp = c->gpio_wp; |
473 | gpio_request(c->gpio_wp, "mmc_wp"); | ||
474 | gpio_direction_input(c->gpio_wp); | ||
475 | 187 | ||
476 | mmc->slots[0].gpio_wp = c->gpio_wp; | 188 | if (c->cover_only) |
477 | mmc->slots[0].get_ro = twl_mmc_get_ro; | 189 | mmc->slots[0].cover = 1; |
478 | } else | ||
479 | mmc->slots[0].gpio_wp = -EINVAL; | ||
480 | 190 | ||
481 | if (c->nonremovable) | 191 | if (c->nonremovable) |
482 | mmc->slots[0].nonremovable = 1; | 192 | mmc->slots[0].nonremovable = 1; |
@@ -495,8 +205,8 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | |||
495 | switch (c->mmc) { | 205 | switch (c->mmc) { |
496 | case 1: | 206 | case 1: |
497 | /* on-chip level shifting via PBIAS0/PBIAS1 */ | 207 | /* on-chip level shifting via PBIAS0/PBIAS1 */ |
498 | mmc->slots[0].set_power = twl_mmc1_set_power; | 208 | mmc->slots[0].before_set_reg = hsmmc1_before_set_reg; |
499 | mmc->slots[0].set_sleep = twl_mmc1_set_sleep; | 209 | mmc->slots[0].after_set_reg = hsmmc1_after_set_reg; |
500 | 210 | ||
501 | /* Omap3630 HSMMC1 supports only 4-bit */ | 211 | /* Omap3630 HSMMC1 supports only 4-bit */ |
502 | if (cpu_is_omap3630() && c->wires > 4) { | 212 | if (cpu_is_omap3630() && c->wires > 4) { |
@@ -512,8 +222,8 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | |||
512 | /* FALLTHROUGH */ | 222 | /* FALLTHROUGH */ |
513 | case 3: | 223 | case 3: |
514 | /* off-chip level shifting, or none */ | 224 | /* off-chip level shifting, or none */ |
515 | mmc->slots[0].set_power = twl_mmc23_set_power; | 225 | mmc->slots[0].before_set_reg = hsmmc23_before_set_reg; |
516 | mmc->slots[0].set_sleep = twl_mmc23_set_sleep; | 226 | mmc->slots[0].after_set_reg = NULL; |
517 | break; | 227 | break; |
518 | default: | 228 | default: |
519 | pr_err("MMC%d configuration not supported!\n", c->mmc); | 229 | pr_err("MMC%d configuration not supported!\n", c->mmc); |
diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h index a47e68563fb6..87d67c10bdec 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.h +++ b/arch/arm/mach-omap2/mmc-twl4030.h | |||
@@ -21,9 +21,7 @@ struct twl4030_hsmmc_info { | |||
21 | int ocr_mask; /* temporary HACK */ | 21 | int ocr_mask; /* temporary HACK */ |
22 | }; | 22 | }; |
23 | 23 | ||
24 | #if defined(CONFIG_REGULATOR) && \ | 24 | #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) |
25 | (defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ | ||
26 | defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)) | ||
27 | 25 | ||
28 | void twl4030_mmc_init(struct twl4030_hsmmc_info *); | 26 | void twl4030_mmc_init(struct twl4030_hsmmc_info *); |
29 | 27 | ||
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h index 29937137bf3e..515701bb47d2 100644 --- a/arch/arm/plat-omap/include/plat/mmc.h +++ b/arch/arm/plat-omap/include/plat/mmc.h | |||
@@ -55,12 +55,12 @@ struct omap_mmc_platform_data { | |||
55 | unsigned int max_freq; | 55 | unsigned int max_freq; |
56 | 56 | ||
57 | /* switch the bus to a new slot */ | 57 | /* switch the bus to a new slot */ |
58 | int (* switch_slot)(struct device *dev, int slot); | 58 | int (*switch_slot)(struct device *dev, int slot); |
59 | /* initialize board-specific MMC functionality, can be NULL if | 59 | /* initialize board-specific MMC functionality, can be NULL if |
60 | * not supported */ | 60 | * not supported */ |
61 | int (* init)(struct device *dev); | 61 | int (*init)(struct device *dev); |
62 | void (* cleanup)(struct device *dev); | 62 | void (*cleanup)(struct device *dev); |
63 | void (* shutdown)(struct device *dev); | 63 | void (*shutdown)(struct device *dev); |
64 | 64 | ||
65 | /* To handle board related suspend/resume functionality for MMC */ | 65 | /* To handle board related suspend/resume functionality for MMC */ |
66 | int (*suspend)(struct device *dev, int slot); | 66 | int (*suspend)(struct device *dev, int slot); |
@@ -99,11 +99,18 @@ struct omap_mmc_platform_data { | |||
99 | int switch_pin; /* gpio (card detect) */ | 99 | int switch_pin; /* gpio (card detect) */ |
100 | int gpio_wp; /* gpio (write protect) */ | 100 | int gpio_wp; /* gpio (write protect) */ |
101 | 101 | ||
102 | int (* set_bus_mode)(struct device *dev, int slot, int bus_mode); | 102 | int (*set_bus_mode)(struct device *dev, int slot, int bus_mode); |
103 | int (* set_power)(struct device *dev, int slot, int power_on, int vdd); | 103 | int (*set_power)(struct device *dev, int slot, |
104 | int (* get_ro)(struct device *dev, int slot); | 104 | int power_on, int vdd); |
105 | int (*get_ro)(struct device *dev, int slot); | ||
105 | int (*set_sleep)(struct device *dev, int slot, int sleep, | 106 | int (*set_sleep)(struct device *dev, int slot, int sleep, |
106 | int vdd, int cardsleep); | 107 | int vdd, int cardsleep); |
108 | /* Call back before enabling / disabling regulators */ | ||
109 | void (*before_set_reg)(struct device *dev, int slot, | ||
110 | int power_on, int vdd); | ||
111 | /* Call back after enabling / disabling regulators */ | ||
112 | void (*after_set_reg)(struct device *dev, int slot, | ||
113 | int power_on, int vdd); | ||
107 | 114 | ||
108 | /* return MMC cover switch state, can be NULL if not supported. | 115 | /* return MMC cover switch state, can be NULL if not supported. |
109 | * | 116 | * |
@@ -111,14 +118,14 @@ struct omap_mmc_platform_data { | |||
111 | * 0 - closed | 118 | * 0 - closed |
112 | * 1 - open | 119 | * 1 - open |
113 | */ | 120 | */ |
114 | int (* get_cover_state)(struct device *dev, int slot); | 121 | int (*get_cover_state)(struct device *dev, int slot); |
115 | 122 | ||
116 | const char *name; | 123 | const char *name; |
117 | u32 ocr_mask; | 124 | u32 ocr_mask; |
118 | 125 | ||
119 | /* Card detection IRQs */ | 126 | /* Card detection IRQs */ |
120 | int card_detect_irq; | 127 | int card_detect_irq; |
121 | int (* card_detect)(int irq); | 128 | int (*card_detect)(struct device *dev, int slot); |
122 | 129 | ||
123 | unsigned int ban_openended:1; | 130 | unsigned int ban_openended:1; |
124 | 131 | ||
@@ -126,7 +133,8 @@ struct omap_mmc_platform_data { | |||
126 | }; | 133 | }; |
127 | 134 | ||
128 | /* called from board-specific card detection service routine */ | 135 | /* called from board-specific card detection service routine */ |
129 | extern void omap_mmc_notify_cover_event(struct device *dev, int slot, int is_closed); | 136 | extern void omap_mmc_notify_cover_event(struct device *dev, int slot, |
137 | int is_closed); | ||
130 | 138 | ||
131 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ | 139 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ |
132 | defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) | 140 | defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4b2322518909..2c5e15d9f864 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/mmc/core.h> | 30 | #include <linux/mmc/core.h> |
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/semaphore.h> | 32 | #include <linux/semaphore.h> |
33 | #include <linux/gpio.h> | ||
34 | #include <linux/regulator/consumer.h> | ||
33 | #include <plat/dma.h> | 35 | #include <plat/dma.h> |
34 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
35 | #include <plat/board.h> | 37 | #include <plat/board.h> |
@@ -146,6 +148,15 @@ struct omap_hsmmc_host { | |||
146 | struct clk *fclk; | 148 | struct clk *fclk; |
147 | struct clk *iclk; | 149 | struct clk *iclk; |
148 | struct clk *dbclk; | 150 | struct clk *dbclk; |
151 | /* | ||
152 | * vcc == configured supply | ||
153 | * vcc_aux == optional | ||
154 | * - MMC1, supply for DAT4..DAT7 | ||
155 | * - MMC2/MMC2, external level shifter voltage supply, for | ||
156 | * chip (SDIO, eMMC, etc) or transceiver (MMC2 only) | ||
157 | */ | ||
158 | struct regulator *vcc; | ||
159 | struct regulator *vcc_aux; | ||
149 | struct semaphore sem; | 160 | struct semaphore sem; |
150 | struct work_struct mmc_carddetect_work; | 161 | struct work_struct mmc_carddetect_work; |
151 | void __iomem *base; | 162 | void __iomem *base; |
@@ -171,10 +182,308 @@ struct omap_hsmmc_host { | |||
171 | int vdd; | 182 | int vdd; |
172 | int protect_card; | 183 | int protect_card; |
173 | int reqs_blocked; | 184 | int reqs_blocked; |
185 | int use_reg; | ||
174 | 186 | ||
175 | struct omap_mmc_platform_data *pdata; | 187 | struct omap_mmc_platform_data *pdata; |
176 | }; | 188 | }; |
177 | 189 | ||
190 | static int omap_hsmmc_card_detect(struct device *dev, int slot) | ||
191 | { | ||
192 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
193 | |||
194 | /* NOTE: assumes card detect signal is active-low */ | ||
195 | return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); | ||
196 | } | ||
197 | |||
198 | static int omap_hsmmc_get_wp(struct device *dev, int slot) | ||
199 | { | ||
200 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
201 | |||
202 | /* NOTE: assumes write protect signal is active-high */ | ||
203 | return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); | ||
204 | } | ||
205 | |||
206 | static int omap_hsmmc_get_cover_state(struct device *dev, int slot) | ||
207 | { | ||
208 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
209 | |||
210 | /* NOTE: assumes card detect signal is active-low */ | ||
211 | return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); | ||
212 | } | ||
213 | |||
214 | #ifdef CONFIG_PM | ||
215 | |||
216 | static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) | ||
217 | { | ||
218 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
219 | |||
220 | disable_irq(mmc->slots[0].card_detect_irq); | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) | ||
225 | { | ||
226 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
227 | |||
228 | enable_irq(mmc->slots[0].card_detect_irq); | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | #else | ||
233 | |||
234 | #define omap_hsmmc_suspend_cdirq NULL | ||
235 | #define omap_hsmmc_resume_cdirq NULL | ||
236 | |||
237 | #endif | ||
238 | |||
239 | static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on, | ||
240 | int vdd) | ||
241 | { | ||
242 | struct omap_hsmmc_host *host = | ||
243 | platform_get_drvdata(to_platform_device(dev)); | ||
244 | int ret; | ||
245 | |||
246 | if (mmc_slot(host).before_set_reg) | ||
247 | mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); | ||
248 | |||
249 | if (power_on) | ||
250 | ret = mmc_regulator_set_ocr(host->vcc, vdd); | ||
251 | else | ||
252 | ret = mmc_regulator_set_ocr(host->vcc, 0); | ||
253 | |||
254 | if (mmc_slot(host).after_set_reg) | ||
255 | mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); | ||
256 | |||
257 | return ret; | ||
258 | } | ||
259 | |||
260 | static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on, | ||
261 | int vdd) | ||
262 | { | ||
263 | struct omap_hsmmc_host *host = | ||
264 | platform_get_drvdata(to_platform_device(dev)); | ||
265 | int ret = 0; | ||
266 | |||
267 | /* | ||
268 | * If we don't see a Vcc regulator, assume it's a fixed | ||
269 | * voltage always-on regulator. | ||
270 | */ | ||
271 | if (!host->vcc) | ||
272 | return 0; | ||
273 | |||
274 | if (mmc_slot(host).before_set_reg) | ||
275 | mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); | ||
276 | |||
277 | /* | ||
278 | * Assume Vcc regulator is used only to power the card ... OMAP | ||
279 | * VDDS is used to power the pins, optionally with a transceiver to | ||
280 | * support cards using voltages other than VDDS (1.8V nominal). When a | ||
281 | * transceiver is used, DAT3..7 are muxed as transceiver control pins. | ||
282 | * | ||
283 | * In some cases this regulator won't support enable/disable; | ||
284 | * e.g. it's a fixed rail for a WLAN chip. | ||
285 | * | ||
286 | * In other cases vcc_aux switches interface power. Example, for | ||
287 | * eMMC cards it represents VccQ. Sometimes transceivers or SDIO | ||
288 | * chips/cards need an interface voltage rail too. | ||
289 | */ | ||
290 | if (power_on) { | ||
291 | ret = mmc_regulator_set_ocr(host->vcc, vdd); | ||
292 | /* Enable interface voltage rail, if needed */ | ||
293 | if (ret == 0 && host->vcc_aux) { | ||
294 | ret = regulator_enable(host->vcc_aux); | ||
295 | if (ret < 0) | ||
296 | ret = mmc_regulator_set_ocr(host->vcc, 0); | ||
297 | } | ||
298 | } else { | ||
299 | if (host->vcc_aux) { | ||
300 | ret = regulator_is_enabled(host->vcc_aux); | ||
301 | if (ret > 0) | ||
302 | ret = regulator_disable(host->vcc_aux); | ||
303 | } | ||
304 | if (ret == 0) | ||
305 | ret = mmc_regulator_set_ocr(host->vcc, 0); | ||
306 | } | ||
307 | |||
308 | if (mmc_slot(host).after_set_reg) | ||
309 | mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); | ||
310 | |||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep, | ||
315 | int vdd, int cardsleep) | ||
316 | { | ||
317 | struct omap_hsmmc_host *host = | ||
318 | platform_get_drvdata(to_platform_device(dev)); | ||
319 | int mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; | ||
320 | |||
321 | return regulator_set_mode(host->vcc, mode); | ||
322 | } | ||
323 | |||
324 | static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep, | ||
325 | int vdd, int cardsleep) | ||
326 | { | ||
327 | struct omap_hsmmc_host *host = | ||
328 | platform_get_drvdata(to_platform_device(dev)); | ||
329 | int err, mode; | ||
330 | |||
331 | /* | ||
332 | * If we don't see a Vcc regulator, assume it's a fixed | ||
333 | * voltage always-on regulator. | ||
334 | */ | ||
335 | if (!host->vcc) | ||
336 | return 0; | ||
337 | |||
338 | mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; | ||
339 | |||
340 | if (!host->vcc_aux) | ||
341 | return regulator_set_mode(host->vcc, mode); | ||
342 | |||
343 | if (cardsleep) { | ||
344 | /* VCC can be turned off if card is asleep */ | ||
345 | if (sleep) | ||
346 | err = mmc_regulator_set_ocr(host->vcc, 0); | ||
347 | else | ||
348 | err = mmc_regulator_set_ocr(host->vcc, vdd); | ||
349 | } else | ||
350 | err = regulator_set_mode(host->vcc, mode); | ||
351 | if (err) | ||
352 | return err; | ||
353 | return regulator_set_mode(host->vcc_aux, mode); | ||
354 | } | ||
355 | |||
356 | static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) | ||
357 | { | ||
358 | int ret; | ||
359 | |||
360 | if (gpio_is_valid(pdata->slots[0].switch_pin)) { | ||
361 | pdata->suspend = omap_hsmmc_suspend_cdirq; | ||
362 | pdata->resume = omap_hsmmc_resume_cdirq; | ||
363 | if (pdata->slots[0].cover) | ||
364 | pdata->slots[0].get_cover_state = | ||
365 | omap_hsmmc_get_cover_state; | ||
366 | else | ||
367 | pdata->slots[0].card_detect = omap_hsmmc_card_detect; | ||
368 | pdata->slots[0].card_detect_irq = | ||
369 | gpio_to_irq(pdata->slots[0].switch_pin); | ||
370 | ret = gpio_request(pdata->slots[0].switch_pin, "mmc_cd"); | ||
371 | if (ret) | ||
372 | return ret; | ||
373 | ret = gpio_direction_input(pdata->slots[0].switch_pin); | ||
374 | if (ret) | ||
375 | goto err_free_sp; | ||
376 | } else | ||
377 | pdata->slots[0].switch_pin = -EINVAL; | ||
378 | |||
379 | if (gpio_is_valid(pdata->slots[0].gpio_wp)) { | ||
380 | pdata->slots[0].get_ro = omap_hsmmc_get_wp; | ||
381 | ret = gpio_request(pdata->slots[0].gpio_wp, "mmc_wp"); | ||
382 | if (ret) | ||
383 | goto err_free_cd; | ||
384 | ret = gpio_direction_input(pdata->slots[0].gpio_wp); | ||
385 | if (ret) | ||
386 | goto err_free_wp; | ||
387 | } else | ||
388 | pdata->slots[0].gpio_wp = -EINVAL; | ||
389 | |||
390 | return 0; | ||
391 | |||
392 | err_free_wp: | ||
393 | gpio_free(pdata->slots[0].gpio_wp); | ||
394 | err_free_cd: | ||
395 | if (gpio_is_valid(pdata->slots[0].switch_pin)) | ||
396 | err_free_sp: | ||
397 | gpio_free(pdata->slots[0].switch_pin); | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata) | ||
402 | { | ||
403 | if (gpio_is_valid(pdata->slots[0].gpio_wp)) | ||
404 | gpio_free(pdata->slots[0].gpio_wp); | ||
405 | if (gpio_is_valid(pdata->slots[0].switch_pin)) | ||
406 | gpio_free(pdata->slots[0].switch_pin); | ||
407 | } | ||
408 | |||
409 | static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) | ||
410 | { | ||
411 | struct regulator *reg; | ||
412 | int ret = 0; | ||
413 | |||
414 | switch (host->id) { | ||
415 | case OMAP_MMC1_DEVID: | ||
416 | /* On-chip level shifting via PBIAS0/PBIAS1 */ | ||
417 | mmc_slot(host).set_power = omap_hsmmc_1_set_power; | ||
418 | mmc_slot(host).set_sleep = omap_hsmmc_1_set_sleep; | ||
419 | break; | ||
420 | case OMAP_MMC2_DEVID: | ||
421 | case OMAP_MMC3_DEVID: | ||
422 | /* Off-chip level shifting, or none */ | ||
423 | mmc_slot(host).set_power = omap_hsmmc_23_set_power; | ||
424 | mmc_slot(host).set_sleep = omap_hsmmc_23_set_sleep; | ||
425 | break; | ||
426 | default: | ||
427 | pr_err("MMC%d configuration not supported!\n", host->id); | ||
428 | return -EINVAL; | ||
429 | } | ||
430 | |||
431 | reg = regulator_get(host->dev, "vmmc"); | ||
432 | if (IS_ERR(reg)) { | ||
433 | dev_dbg(host->dev, "vmmc regulator missing\n"); | ||
434 | /* | ||
435 | * HACK: until fixed.c regulator is usable, | ||
436 | * we don't require a main regulator | ||
437 | * for MMC2 or MMC3 | ||
438 | */ | ||
439 | if (host->id == OMAP_MMC1_DEVID) { | ||
440 | ret = PTR_ERR(reg); | ||
441 | goto err; | ||
442 | } | ||
443 | } else { | ||
444 | host->vcc = reg; | ||
445 | mmc_slot(host).ocr_mask = mmc_regulator_get_ocrmask(reg); | ||
446 | |||
447 | /* Allow an aux regulator */ | ||
448 | reg = regulator_get(host->dev, "vmmc_aux"); | ||
449 | host->vcc_aux = IS_ERR(reg) ? NULL : reg; | ||
450 | |||
451 | /* | ||
452 | * UGLY HACK: workaround regulator framework bugs. | ||
453 | * When the bootloader leaves a supply active, it's | ||
454 | * initialized with zero usecount ... and we can't | ||
455 | * disable it without first enabling it. Until the | ||
456 | * framework is fixed, we need a workaround like this | ||
457 | * (which is safe for MMC, but not in general). | ||
458 | */ | ||
459 | if (regulator_is_enabled(host->vcc) > 0) { | ||
460 | regulator_enable(host->vcc); | ||
461 | regulator_disable(host->vcc); | ||
462 | } | ||
463 | if (host->vcc_aux) { | ||
464 | if (regulator_is_enabled(reg) > 0) { | ||
465 | regulator_enable(reg); | ||
466 | regulator_disable(reg); | ||
467 | } | ||
468 | } | ||
469 | } | ||
470 | |||
471 | return 0; | ||
472 | |||
473 | err: | ||
474 | mmc_slot(host).set_power = NULL; | ||
475 | mmc_slot(host).set_sleep = NULL; | ||
476 | return ret; | ||
477 | } | ||
478 | |||
479 | static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) | ||
480 | { | ||
481 | regulator_put(host->vcc); | ||
482 | regulator_put(host->vcc_aux); | ||
483 | mmc_slot(host).set_power = NULL; | ||
484 | mmc_slot(host).set_sleep = NULL; | ||
485 | } | ||
486 | |||
178 | /* | 487 | /* |
179 | * Stop clock to the card | 488 | * Stop clock to the card |
180 | */ | 489 | */ |
@@ -835,7 +1144,7 @@ static void omap_hsmmc_detect(struct work_struct *work) | |||
835 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); | 1144 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); |
836 | 1145 | ||
837 | if (slot->card_detect) | 1146 | if (slot->card_detect) |
838 | carddetect = slot->card_detect(slot->card_detect_irq); | 1147 | carddetect = slot->card_detect(host->dev, host->slot_id); |
839 | else { | 1148 | else { |
840 | omap_hsmmc_protect_card(host); | 1149 | omap_hsmmc_protect_card(host); |
841 | carddetect = -ENOSYS; | 1150 | carddetect = -ENOSYS; |
@@ -1242,7 +1551,7 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc) | |||
1242 | 1551 | ||
1243 | if (!mmc_slot(host).card_detect) | 1552 | if (!mmc_slot(host).card_detect) |
1244 | return -ENOSYS; | 1553 | return -ENOSYS; |
1245 | return mmc_slot(host).card_detect(mmc_slot(host).card_detect_irq); | 1554 | return mmc_slot(host).card_detect(host->dev, host->slot_id); |
1246 | } | 1555 | } |
1247 | 1556 | ||
1248 | static int omap_hsmmc_get_ro(struct mmc_host *mmc) | 1557 | static int omap_hsmmc_get_ro(struct mmc_host *mmc) |
@@ -1616,7 +1925,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1616 | struct mmc_host *mmc; | 1925 | struct mmc_host *mmc; |
1617 | struct omap_hsmmc_host *host = NULL; | 1926 | struct omap_hsmmc_host *host = NULL; |
1618 | struct resource *res; | 1927 | struct resource *res; |
1619 | int ret = 0, irq; | 1928 | int ret, irq; |
1620 | 1929 | ||
1621 | if (pdata == NULL) { | 1930 | if (pdata == NULL) { |
1622 | dev_err(&pdev->dev, "Platform Data is missing\n"); | 1931 | dev_err(&pdev->dev, "Platform Data is missing\n"); |
@@ -1638,10 +1947,14 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1638 | if (res == NULL) | 1947 | if (res == NULL) |
1639 | return -EBUSY; | 1948 | return -EBUSY; |
1640 | 1949 | ||
1950 | ret = omap_hsmmc_gpio_init(pdata); | ||
1951 | if (ret) | ||
1952 | goto err; | ||
1953 | |||
1641 | mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), &pdev->dev); | 1954 | mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), &pdev->dev); |
1642 | if (!mmc) { | 1955 | if (!mmc) { |
1643 | ret = -ENOMEM; | 1956 | ret = -ENOMEM; |
1644 | goto err; | 1957 | goto err_alloc; |
1645 | } | 1958 | } |
1646 | 1959 | ||
1647 | host = mmc_priv(mmc); | 1960 | host = mmc_priv(mmc); |
@@ -1781,7 +2094,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1781 | goto err_irq; | 2094 | goto err_irq; |
1782 | } | 2095 | } |
1783 | 2096 | ||
1784 | /* initialize power supplies, gpios, etc */ | ||
1785 | if (pdata->init != NULL) { | 2097 | if (pdata->init != NULL) { |
1786 | if (pdata->init(&pdev->dev) != 0) { | 2098 | if (pdata->init(&pdev->dev) != 0) { |
1787 | dev_dbg(mmc_dev(host->mmc), | 2099 | dev_dbg(mmc_dev(host->mmc), |
@@ -1789,6 +2101,14 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1789 | goto err_irq_cd_init; | 2101 | goto err_irq_cd_init; |
1790 | } | 2102 | } |
1791 | } | 2103 | } |
2104 | |||
2105 | if (!mmc_slot(host).set_power) { | ||
2106 | ret = omap_hsmmc_reg_get(host); | ||
2107 | if (ret) | ||
2108 | goto err_reg; | ||
2109 | host->use_reg = 1; | ||
2110 | } | ||
2111 | |||
1792 | mmc->ocr_avail = mmc_slot(host).ocr_mask; | 2112 | mmc->ocr_avail = mmc_slot(host).ocr_mask; |
1793 | 2113 | ||
1794 | /* Request IRQ for card detect */ | 2114 | /* Request IRQ for card detect */ |
@@ -1823,19 +2143,22 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1823 | ret = device_create_file(&mmc->class_dev, | 2143 | ret = device_create_file(&mmc->class_dev, |
1824 | &dev_attr_cover_switch); | 2144 | &dev_attr_cover_switch); |
1825 | if (ret < 0) | 2145 | if (ret < 0) |
1826 | goto err_cover_switch; | 2146 | goto err_slot_name; |
1827 | } | 2147 | } |
1828 | 2148 | ||
1829 | omap_hsmmc_debugfs(mmc); | 2149 | omap_hsmmc_debugfs(mmc); |
1830 | 2150 | ||
1831 | return 0; | 2151 | return 0; |
1832 | 2152 | ||
1833 | err_cover_switch: | ||
1834 | device_remove_file(&mmc->class_dev, &dev_attr_cover_switch); | ||
1835 | err_slot_name: | 2153 | err_slot_name: |
1836 | mmc_remove_host(mmc); | 2154 | mmc_remove_host(mmc); |
1837 | err_irq_cd: | ||
1838 | free_irq(mmc_slot(host).card_detect_irq, host); | 2155 | free_irq(mmc_slot(host).card_detect_irq, host); |
2156 | err_irq_cd: | ||
2157 | if (host->use_reg) | ||
2158 | omap_hsmmc_reg_put(host); | ||
2159 | err_reg: | ||
2160 | if (host->pdata->cleanup) | ||
2161 | host->pdata->cleanup(&pdev->dev); | ||
1839 | err_irq_cd_init: | 2162 | err_irq_cd_init: |
1840 | free_irq(host->irq, host); | 2163 | free_irq(host->irq, host); |
1841 | err_irq: | 2164 | err_irq: |
@@ -1847,14 +2170,14 @@ err_irq: | |||
1847 | clk_disable(host->dbclk); | 2170 | clk_disable(host->dbclk); |
1848 | clk_put(host->dbclk); | 2171 | clk_put(host->dbclk); |
1849 | } | 2172 | } |
1850 | |||
1851 | err1: | 2173 | err1: |
1852 | iounmap(host->base); | 2174 | iounmap(host->base); |
2175 | platform_set_drvdata(pdev, NULL); | ||
2176 | mmc_free_host(mmc); | ||
2177 | err_alloc: | ||
2178 | omap_hsmmc_gpio_free(pdata); | ||
1853 | err: | 2179 | err: |
1854 | dev_dbg(mmc_dev(host->mmc), "Probe Failed\n"); | ||
1855 | release_mem_region(res->start, res->end - res->start + 1); | 2180 | release_mem_region(res->start, res->end - res->start + 1); |
1856 | if (host) | ||
1857 | mmc_free_host(mmc); | ||
1858 | return ret; | 2181 | return ret; |
1859 | } | 2182 | } |
1860 | 2183 | ||
@@ -1866,6 +2189,8 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
1866 | if (host) { | 2189 | if (host) { |
1867 | mmc_host_enable(host->mmc); | 2190 | mmc_host_enable(host->mmc); |
1868 | mmc_remove_host(host->mmc); | 2191 | mmc_remove_host(host->mmc); |
2192 | if (host->use_reg) | ||
2193 | omap_hsmmc_reg_put(host); | ||
1869 | if (host->pdata->cleanup) | 2194 | if (host->pdata->cleanup) |
1870 | host->pdata->cleanup(&pdev->dev); | 2195 | host->pdata->cleanup(&pdev->dev); |
1871 | free_irq(host->irq, host); | 2196 | free_irq(host->irq, host); |
@@ -1884,6 +2209,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
1884 | 2209 | ||
1885 | mmc_free_host(host->mmc); | 2210 | mmc_free_host(host->mmc); |
1886 | iounmap(host->base); | 2211 | iounmap(host->base); |
2212 | omap_hsmmc_gpio_free(pdev->dev.platform_data); | ||
1887 | } | 2213 | } |
1888 | 2214 | ||
1889 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2215 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |