diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-02 13:34:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-02 13:34:25 -0500 |
commit | 5057bfaff82e12f01a2ffd58f55535cbd7c5c3a2 (patch) | |
tree | 0397253173308317480ed82f0b75af46cd3f6cb1 /drivers/mmc | |
parent | 6c0ad5dfd3d5ad6def89b485ee52834547da239b (diff) | |
parent | d702d12167a2c05a346f49aac7a311d597762495 (diff) |
Merge branch 'omap-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6
* 'omap-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6: (214 commits)
omap2: Initialize Menelaus and MMC for N8X0
AM3517 EVM: correct typo - tca6416 mispelt as tca6516
AM3517 EVM: Enable I2C support
AM35x: Enable OMAP_MUX in defconfig
AM35x: Add missing GPIO mux config for EHCI port
Zoom3: Defconfig update
omap: i2c: Fix muxing for command line enabled bus
OMAP4: clock: Remove clock hacks from timer-gp.c
OMAP4: clock: Add dummy clock nodes for interface clocks
OMAP4: clock: Rename leaf clock nodes to end with a _ick or _fck
OMAP2+ clock: revise omap2_clk_{disable,enable}()
OMAP2/3 clock: combine OMAP2 & 3 boot-time MPU rate change code
OMAP clockdomain: if no autodeps exist, don't try to add or remove them
OMAP hwmod: add hwmod class support
OMAP hwmod: convert header files with static allocations into C files
OMAP hwmod: convert hwmod to use hardware clock names rather than clkdev dev+con
OMAP clock: add omap_clk_get_by_name() for use by OMAP hwmod core code
OMAP3: clock: add capability to change rate of dpll4_m5_ck_3630
OMAP4 clock: drop the ALWAYS_ENABLED clock flag
OMAP clock: drop RATE_FIXED clock flag
...
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 400 |
1 files changed, 384 insertions, 16 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4b2322518909..83f0affadcae 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,337 @@ 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 | #ifdef CONFIG_REGULATOR | ||
240 | |||
241 | static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on, | ||
242 | int vdd) | ||
243 | { | ||
244 | struct omap_hsmmc_host *host = | ||
245 | platform_get_drvdata(to_platform_device(dev)); | ||
246 | int ret; | ||
247 | |||
248 | if (mmc_slot(host).before_set_reg) | ||
249 | mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); | ||
250 | |||
251 | if (power_on) | ||
252 | ret = mmc_regulator_set_ocr(host->vcc, vdd); | ||
253 | else | ||
254 | ret = mmc_regulator_set_ocr(host->vcc, 0); | ||
255 | |||
256 | if (mmc_slot(host).after_set_reg) | ||
257 | mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); | ||
258 | |||
259 | return ret; | ||
260 | } | ||
261 | |||
262 | static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on, | ||
263 | int vdd) | ||
264 | { | ||
265 | struct omap_hsmmc_host *host = | ||
266 | platform_get_drvdata(to_platform_device(dev)); | ||
267 | int ret = 0; | ||
268 | |||
269 | /* | ||
270 | * If we don't see a Vcc regulator, assume it's a fixed | ||
271 | * voltage always-on regulator. | ||
272 | */ | ||
273 | if (!host->vcc) | ||
274 | return 0; | ||
275 | |||
276 | if (mmc_slot(host).before_set_reg) | ||
277 | mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); | ||
278 | |||
279 | /* | ||
280 | * Assume Vcc regulator is used only to power the card ... OMAP | ||
281 | * VDDS is used to power the pins, optionally with a transceiver to | ||
282 | * support cards using voltages other than VDDS (1.8V nominal). When a | ||
283 | * transceiver is used, DAT3..7 are muxed as transceiver control pins. | ||
284 | * | ||
285 | * In some cases this regulator won't support enable/disable; | ||
286 | * e.g. it's a fixed rail for a WLAN chip. | ||
287 | * | ||
288 | * In other cases vcc_aux switches interface power. Example, for | ||
289 | * eMMC cards it represents VccQ. Sometimes transceivers or SDIO | ||
290 | * chips/cards need an interface voltage rail too. | ||
291 | */ | ||
292 | if (power_on) { | ||
293 | ret = mmc_regulator_set_ocr(host->vcc, vdd); | ||
294 | /* Enable interface voltage rail, if needed */ | ||
295 | if (ret == 0 && host->vcc_aux) { | ||
296 | ret = regulator_enable(host->vcc_aux); | ||
297 | if (ret < 0) | ||
298 | ret = mmc_regulator_set_ocr(host->vcc, 0); | ||
299 | } | ||
300 | } else { | ||
301 | if (host->vcc_aux) | ||
302 | ret = regulator_disable(host->vcc_aux); | ||
303 | if (ret == 0) | ||
304 | ret = mmc_regulator_set_ocr(host->vcc, 0); | ||
305 | } | ||
306 | |||
307 | if (mmc_slot(host).after_set_reg) | ||
308 | mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); | ||
309 | |||
310 | return ret; | ||
311 | } | ||
312 | |||
313 | static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep, | ||
314 | int vdd, int cardsleep) | ||
315 | { | ||
316 | struct omap_hsmmc_host *host = | ||
317 | platform_get_drvdata(to_platform_device(dev)); | ||
318 | int mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; | ||
319 | |||
320 | return regulator_set_mode(host->vcc, mode); | ||
321 | } | ||
322 | |||
323 | static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep, | ||
324 | int vdd, int cardsleep) | ||
325 | { | ||
326 | struct omap_hsmmc_host *host = | ||
327 | platform_get_drvdata(to_platform_device(dev)); | ||
328 | int err, mode; | ||
329 | |||
330 | /* | ||
331 | * If we don't see a Vcc regulator, assume it's a fixed | ||
332 | * voltage always-on regulator. | ||
333 | */ | ||
334 | if (!host->vcc) | ||
335 | return 0; | ||
336 | |||
337 | mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; | ||
338 | |||
339 | if (!host->vcc_aux) | ||
340 | return regulator_set_mode(host->vcc, mode); | ||
341 | |||
342 | if (cardsleep) { | ||
343 | /* VCC can be turned off if card is asleep */ | ||
344 | if (sleep) | ||
345 | err = mmc_regulator_set_ocr(host->vcc, 0); | ||
346 | else | ||
347 | err = mmc_regulator_set_ocr(host->vcc, vdd); | ||
348 | } else | ||
349 | err = regulator_set_mode(host->vcc, mode); | ||
350 | if (err) | ||
351 | return err; | ||
352 | |||
353 | if (!mmc_slot(host).vcc_aux_disable_is_sleep) | ||
354 | return regulator_set_mode(host->vcc_aux, mode); | ||
355 | |||
356 | if (sleep) | ||
357 | return regulator_disable(host->vcc_aux); | ||
358 | else | ||
359 | return regulator_enable(host->vcc_aux); | ||
360 | } | ||
361 | |||
362 | static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) | ||
363 | { | ||
364 | struct regulator *reg; | ||
365 | int ret = 0; | ||
366 | |||
367 | switch (host->id) { | ||
368 | case OMAP_MMC1_DEVID: | ||
369 | /* On-chip level shifting via PBIAS0/PBIAS1 */ | ||
370 | mmc_slot(host).set_power = omap_hsmmc_1_set_power; | ||
371 | mmc_slot(host).set_sleep = omap_hsmmc_1_set_sleep; | ||
372 | break; | ||
373 | case OMAP_MMC2_DEVID: | ||
374 | case OMAP_MMC3_DEVID: | ||
375 | /* Off-chip level shifting, or none */ | ||
376 | mmc_slot(host).set_power = omap_hsmmc_23_set_power; | ||
377 | mmc_slot(host).set_sleep = omap_hsmmc_23_set_sleep; | ||
378 | break; | ||
379 | default: | ||
380 | pr_err("MMC%d configuration not supported!\n", host->id); | ||
381 | return -EINVAL; | ||
382 | } | ||
383 | |||
384 | reg = regulator_get(host->dev, "vmmc"); | ||
385 | if (IS_ERR(reg)) { | ||
386 | dev_dbg(host->dev, "vmmc regulator missing\n"); | ||
387 | /* | ||
388 | * HACK: until fixed.c regulator is usable, | ||
389 | * we don't require a main regulator | ||
390 | * for MMC2 or MMC3 | ||
391 | */ | ||
392 | if (host->id == OMAP_MMC1_DEVID) { | ||
393 | ret = PTR_ERR(reg); | ||
394 | goto err; | ||
395 | } | ||
396 | } else { | ||
397 | host->vcc = reg; | ||
398 | mmc_slot(host).ocr_mask = mmc_regulator_get_ocrmask(reg); | ||
399 | |||
400 | /* Allow an aux regulator */ | ||
401 | reg = regulator_get(host->dev, "vmmc_aux"); | ||
402 | host->vcc_aux = IS_ERR(reg) ? NULL : reg; | ||
403 | |||
404 | /* | ||
405 | * UGLY HACK: workaround regulator framework bugs. | ||
406 | * When the bootloader leaves a supply active, it's | ||
407 | * initialized with zero usecount ... and we can't | ||
408 | * disable it without first enabling it. Until the | ||
409 | * framework is fixed, we need a workaround like this | ||
410 | * (which is safe for MMC, but not in general). | ||
411 | */ | ||
412 | if (regulator_is_enabled(host->vcc) > 0) { | ||
413 | regulator_enable(host->vcc); | ||
414 | regulator_disable(host->vcc); | ||
415 | } | ||
416 | if (host->vcc_aux) { | ||
417 | if (regulator_is_enabled(reg) > 0) { | ||
418 | regulator_enable(reg); | ||
419 | regulator_disable(reg); | ||
420 | } | ||
421 | } | ||
422 | } | ||
423 | |||
424 | return 0; | ||
425 | |||
426 | err: | ||
427 | mmc_slot(host).set_power = NULL; | ||
428 | mmc_slot(host).set_sleep = NULL; | ||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) | ||
433 | { | ||
434 | regulator_put(host->vcc); | ||
435 | regulator_put(host->vcc_aux); | ||
436 | mmc_slot(host).set_power = NULL; | ||
437 | mmc_slot(host).set_sleep = NULL; | ||
438 | } | ||
439 | |||
440 | static inline int omap_hsmmc_have_reg(void) | ||
441 | { | ||
442 | return 1; | ||
443 | } | ||
444 | |||
445 | #else | ||
446 | |||
447 | static inline int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) | ||
448 | { | ||
449 | return -EINVAL; | ||
450 | } | ||
451 | |||
452 | static inline void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) | ||
453 | { | ||
454 | } | ||
455 | |||
456 | static inline int omap_hsmmc_have_reg(void) | ||
457 | { | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | #endif | ||
462 | |||
463 | static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) | ||
464 | { | ||
465 | int ret; | ||
466 | |||
467 | if (gpio_is_valid(pdata->slots[0].switch_pin)) { | ||
468 | pdata->suspend = omap_hsmmc_suspend_cdirq; | ||
469 | pdata->resume = omap_hsmmc_resume_cdirq; | ||
470 | if (pdata->slots[0].cover) | ||
471 | pdata->slots[0].get_cover_state = | ||
472 | omap_hsmmc_get_cover_state; | ||
473 | else | ||
474 | pdata->slots[0].card_detect = omap_hsmmc_card_detect; | ||
475 | pdata->slots[0].card_detect_irq = | ||
476 | gpio_to_irq(pdata->slots[0].switch_pin); | ||
477 | ret = gpio_request(pdata->slots[0].switch_pin, "mmc_cd"); | ||
478 | if (ret) | ||
479 | return ret; | ||
480 | ret = gpio_direction_input(pdata->slots[0].switch_pin); | ||
481 | if (ret) | ||
482 | goto err_free_sp; | ||
483 | } else | ||
484 | pdata->slots[0].switch_pin = -EINVAL; | ||
485 | |||
486 | if (gpio_is_valid(pdata->slots[0].gpio_wp)) { | ||
487 | pdata->slots[0].get_ro = omap_hsmmc_get_wp; | ||
488 | ret = gpio_request(pdata->slots[0].gpio_wp, "mmc_wp"); | ||
489 | if (ret) | ||
490 | goto err_free_cd; | ||
491 | ret = gpio_direction_input(pdata->slots[0].gpio_wp); | ||
492 | if (ret) | ||
493 | goto err_free_wp; | ||
494 | } else | ||
495 | pdata->slots[0].gpio_wp = -EINVAL; | ||
496 | |||
497 | return 0; | ||
498 | |||
499 | err_free_wp: | ||
500 | gpio_free(pdata->slots[0].gpio_wp); | ||
501 | err_free_cd: | ||
502 | if (gpio_is_valid(pdata->slots[0].switch_pin)) | ||
503 | err_free_sp: | ||
504 | gpio_free(pdata->slots[0].switch_pin); | ||
505 | return ret; | ||
506 | } | ||
507 | |||
508 | static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata) | ||
509 | { | ||
510 | if (gpio_is_valid(pdata->slots[0].gpio_wp)) | ||
511 | gpio_free(pdata->slots[0].gpio_wp); | ||
512 | if (gpio_is_valid(pdata->slots[0].switch_pin)) | ||
513 | gpio_free(pdata->slots[0].switch_pin); | ||
514 | } | ||
515 | |||
178 | /* | 516 | /* |
179 | * Stop clock to the card | 517 | * Stop clock to the card |
180 | */ | 518 | */ |
@@ -835,7 +1173,7 @@ static void omap_hsmmc_detect(struct work_struct *work) | |||
835 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); | 1173 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); |
836 | 1174 | ||
837 | if (slot->card_detect) | 1175 | if (slot->card_detect) |
838 | carddetect = slot->card_detect(slot->card_detect_irq); | 1176 | carddetect = slot->card_detect(host->dev, host->slot_id); |
839 | else { | 1177 | else { |
840 | omap_hsmmc_protect_card(host); | 1178 | omap_hsmmc_protect_card(host); |
841 | carddetect = -ENOSYS; | 1179 | carddetect = -ENOSYS; |
@@ -1242,7 +1580,7 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc) | |||
1242 | 1580 | ||
1243 | if (!mmc_slot(host).card_detect) | 1581 | if (!mmc_slot(host).card_detect) |
1244 | return -ENOSYS; | 1582 | return -ENOSYS; |
1245 | return mmc_slot(host).card_detect(mmc_slot(host).card_detect_irq); | 1583 | return mmc_slot(host).card_detect(host->dev, host->slot_id); |
1246 | } | 1584 | } |
1247 | 1585 | ||
1248 | static int omap_hsmmc_get_ro(struct mmc_host *mmc) | 1586 | static int omap_hsmmc_get_ro(struct mmc_host *mmc) |
@@ -1311,7 +1649,7 @@ static int omap_hsmmc_enabled_to_disabled(struct omap_hsmmc_host *host) | |||
1311 | if (host->power_mode == MMC_POWER_OFF) | 1649 | if (host->power_mode == MMC_POWER_OFF) |
1312 | return 0; | 1650 | return 0; |
1313 | 1651 | ||
1314 | return msecs_to_jiffies(OMAP_MMC_SLEEP_TIMEOUT); | 1652 | return OMAP_MMC_SLEEP_TIMEOUT; |
1315 | } | 1653 | } |
1316 | 1654 | ||
1317 | /* Handler for [DISABLED -> REGSLEEP / CARDSLEEP] transition */ | 1655 | /* Handler for [DISABLED -> REGSLEEP / CARDSLEEP] transition */ |
@@ -1347,11 +1685,14 @@ static int omap_hsmmc_disabled_to_sleep(struct omap_hsmmc_host *host) | |||
1347 | dev_dbg(mmc_dev(host->mmc), "DISABLED -> %s\n", | 1685 | dev_dbg(mmc_dev(host->mmc), "DISABLED -> %s\n", |
1348 | host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP"); | 1686 | host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP"); |
1349 | 1687 | ||
1688 | if (mmc_slot(host).no_off) | ||
1689 | return 0; | ||
1690 | |||
1350 | if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) || | 1691 | if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) || |
1351 | mmc_slot(host).card_detect || | 1692 | mmc_slot(host).card_detect || |
1352 | (mmc_slot(host).get_cover_state && | 1693 | (mmc_slot(host).get_cover_state && |
1353 | mmc_slot(host).get_cover_state(host->dev, host->slot_id))) | 1694 | mmc_slot(host).get_cover_state(host->dev, host->slot_id))) |
1354 | return msecs_to_jiffies(OMAP_MMC_OFF_TIMEOUT); | 1695 | return OMAP_MMC_OFF_TIMEOUT; |
1355 | 1696 | ||
1356 | return 0; | 1697 | return 0; |
1357 | } | 1698 | } |
@@ -1362,6 +1703,9 @@ static int omap_hsmmc_sleep_to_off(struct omap_hsmmc_host *host) | |||
1362 | if (!mmc_try_claim_host(host->mmc)) | 1703 | if (!mmc_try_claim_host(host->mmc)) |
1363 | return 0; | 1704 | return 0; |
1364 | 1705 | ||
1706 | if (mmc_slot(host).no_off) | ||
1707 | return 0; | ||
1708 | |||
1365 | if (!((host->mmc->caps & MMC_CAP_NONREMOVABLE) || | 1709 | if (!((host->mmc->caps & MMC_CAP_NONREMOVABLE) || |
1366 | mmc_slot(host).card_detect || | 1710 | mmc_slot(host).card_detect || |
1367 | (mmc_slot(host).get_cover_state && | 1711 | (mmc_slot(host).get_cover_state && |
@@ -1616,7 +1960,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1616 | struct mmc_host *mmc; | 1960 | struct mmc_host *mmc; |
1617 | struct omap_hsmmc_host *host = NULL; | 1961 | struct omap_hsmmc_host *host = NULL; |
1618 | struct resource *res; | 1962 | struct resource *res; |
1619 | int ret = 0, irq; | 1963 | int ret, irq; |
1620 | 1964 | ||
1621 | if (pdata == NULL) { | 1965 | if (pdata == NULL) { |
1622 | dev_err(&pdev->dev, "Platform Data is missing\n"); | 1966 | dev_err(&pdev->dev, "Platform Data is missing\n"); |
@@ -1638,10 +1982,14 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1638 | if (res == NULL) | 1982 | if (res == NULL) |
1639 | return -EBUSY; | 1983 | return -EBUSY; |
1640 | 1984 | ||
1985 | ret = omap_hsmmc_gpio_init(pdata); | ||
1986 | if (ret) | ||
1987 | goto err; | ||
1988 | |||
1641 | mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), &pdev->dev); | 1989 | mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), &pdev->dev); |
1642 | if (!mmc) { | 1990 | if (!mmc) { |
1643 | ret = -ENOMEM; | 1991 | ret = -ENOMEM; |
1644 | goto err; | 1992 | goto err_alloc; |
1645 | } | 1993 | } |
1646 | 1994 | ||
1647 | host = mmc_priv(mmc); | 1995 | host = mmc_priv(mmc); |
@@ -1656,7 +2004,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1656 | host->slot_id = 0; | 2004 | host->slot_id = 0; |
1657 | host->mapbase = res->start; | 2005 | host->mapbase = res->start; |
1658 | host->base = ioremap(host->mapbase, SZ_4K); | 2006 | host->base = ioremap(host->mapbase, SZ_4K); |
1659 | host->power_mode = -1; | 2007 | host->power_mode = MMC_POWER_OFF; |
1660 | 2008 | ||
1661 | platform_set_drvdata(pdev, host); | 2009 | platform_set_drvdata(pdev, host); |
1662 | INIT_WORK(&host->mmc_carddetect_work, omap_hsmmc_detect); | 2010 | INIT_WORK(&host->mmc_carddetect_work, omap_hsmmc_detect); |
@@ -1666,6 +2014,13 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1666 | else | 2014 | else |
1667 | mmc->ops = &omap_hsmmc_ops; | 2015 | mmc->ops = &omap_hsmmc_ops; |
1668 | 2016 | ||
2017 | /* | ||
2018 | * If regulator_disable can only put vcc_aux to sleep then there is | ||
2019 | * no off state. | ||
2020 | */ | ||
2021 | if (mmc_slot(host).vcc_aux_disable_is_sleep) | ||
2022 | mmc_slot(host).no_off = 1; | ||
2023 | |||
1669 | mmc->f_min = 400000; | 2024 | mmc->f_min = 400000; |
1670 | mmc->f_max = 52000000; | 2025 | mmc->f_max = 52000000; |
1671 | 2026 | ||
@@ -1781,7 +2136,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1781 | goto err_irq; | 2136 | goto err_irq; |
1782 | } | 2137 | } |
1783 | 2138 | ||
1784 | /* initialize power supplies, gpios, etc */ | ||
1785 | if (pdata->init != NULL) { | 2139 | if (pdata->init != NULL) { |
1786 | if (pdata->init(&pdev->dev) != 0) { | 2140 | if (pdata->init(&pdev->dev) != 0) { |
1787 | dev_dbg(mmc_dev(host->mmc), | 2141 | dev_dbg(mmc_dev(host->mmc), |
@@ -1789,6 +2143,14 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1789 | goto err_irq_cd_init; | 2143 | goto err_irq_cd_init; |
1790 | } | 2144 | } |
1791 | } | 2145 | } |
2146 | |||
2147 | if (omap_hsmmc_have_reg() && !mmc_slot(host).set_power) { | ||
2148 | ret = omap_hsmmc_reg_get(host); | ||
2149 | if (ret) | ||
2150 | goto err_reg; | ||
2151 | host->use_reg = 1; | ||
2152 | } | ||
2153 | |||
1792 | mmc->ocr_avail = mmc_slot(host).ocr_mask; | 2154 | mmc->ocr_avail = mmc_slot(host).ocr_mask; |
1793 | 2155 | ||
1794 | /* Request IRQ for card detect */ | 2156 | /* Request IRQ for card detect */ |
@@ -1823,19 +2185,22 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1823 | ret = device_create_file(&mmc->class_dev, | 2185 | ret = device_create_file(&mmc->class_dev, |
1824 | &dev_attr_cover_switch); | 2186 | &dev_attr_cover_switch); |
1825 | if (ret < 0) | 2187 | if (ret < 0) |
1826 | goto err_cover_switch; | 2188 | goto err_slot_name; |
1827 | } | 2189 | } |
1828 | 2190 | ||
1829 | omap_hsmmc_debugfs(mmc); | 2191 | omap_hsmmc_debugfs(mmc); |
1830 | 2192 | ||
1831 | return 0; | 2193 | return 0; |
1832 | 2194 | ||
1833 | err_cover_switch: | ||
1834 | device_remove_file(&mmc->class_dev, &dev_attr_cover_switch); | ||
1835 | err_slot_name: | 2195 | err_slot_name: |
1836 | mmc_remove_host(mmc); | 2196 | mmc_remove_host(mmc); |
1837 | err_irq_cd: | ||
1838 | free_irq(mmc_slot(host).card_detect_irq, host); | 2197 | free_irq(mmc_slot(host).card_detect_irq, host); |
2198 | err_irq_cd: | ||
2199 | if (host->use_reg) | ||
2200 | omap_hsmmc_reg_put(host); | ||
2201 | err_reg: | ||
2202 | if (host->pdata->cleanup) | ||
2203 | host->pdata->cleanup(&pdev->dev); | ||
1839 | err_irq_cd_init: | 2204 | err_irq_cd_init: |
1840 | free_irq(host->irq, host); | 2205 | free_irq(host->irq, host); |
1841 | err_irq: | 2206 | err_irq: |
@@ -1847,14 +2212,14 @@ err_irq: | |||
1847 | clk_disable(host->dbclk); | 2212 | clk_disable(host->dbclk); |
1848 | clk_put(host->dbclk); | 2213 | clk_put(host->dbclk); |
1849 | } | 2214 | } |
1850 | |||
1851 | err1: | 2215 | err1: |
1852 | iounmap(host->base); | 2216 | iounmap(host->base); |
2217 | platform_set_drvdata(pdev, NULL); | ||
2218 | mmc_free_host(mmc); | ||
2219 | err_alloc: | ||
2220 | omap_hsmmc_gpio_free(pdata); | ||
1853 | err: | 2221 | err: |
1854 | dev_dbg(mmc_dev(host->mmc), "Probe Failed\n"); | ||
1855 | release_mem_region(res->start, res->end - res->start + 1); | 2222 | release_mem_region(res->start, res->end - res->start + 1); |
1856 | if (host) | ||
1857 | mmc_free_host(mmc); | ||
1858 | return ret; | 2223 | return ret; |
1859 | } | 2224 | } |
1860 | 2225 | ||
@@ -1866,6 +2231,8 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
1866 | if (host) { | 2231 | if (host) { |
1867 | mmc_host_enable(host->mmc); | 2232 | mmc_host_enable(host->mmc); |
1868 | mmc_remove_host(host->mmc); | 2233 | mmc_remove_host(host->mmc); |
2234 | if (host->use_reg) | ||
2235 | omap_hsmmc_reg_put(host); | ||
1869 | if (host->pdata->cleanup) | 2236 | if (host->pdata->cleanup) |
1870 | host->pdata->cleanup(&pdev->dev); | 2237 | host->pdata->cleanup(&pdev->dev); |
1871 | free_irq(host->irq, host); | 2238 | free_irq(host->irq, host); |
@@ -1884,6 +2251,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
1884 | 2251 | ||
1885 | mmc_free_host(host->mmc); | 2252 | mmc_free_host(host->mmc); |
1886 | iounmap(host->base); | 2253 | iounmap(host->base); |
2254 | omap_hsmmc_gpio_free(pdev->dev.platform_data); | ||
1887 | } | 2255 | } |
1888 | 2256 | ||
1889 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2257 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |