diff options
-rw-r--r-- | arch/arm/mach-omap2/devices.c | 168 | ||||
-rw-r--r-- | arch/arm/mach-omap2/hsmmc.c | 346 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/mmc.h | 20 | ||||
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 4 |
4 files changed, 200 insertions, 338 deletions
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 2f4a598ba67e..31632ac1ca7c 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c | |||
@@ -544,112 +544,6 @@ static inline void omap_init_aes(void) { } | |||
544 | 544 | ||
545 | /*-------------------------------------------------------------------------*/ | 545 | /*-------------------------------------------------------------------------*/ |
546 | 546 | ||
547 | #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) | ||
548 | |||
549 | #define MMCHS_SYSCONFIG 0x0010 | ||
550 | #define MMCHS_SYSCONFIG_SWRESET (1 << 1) | ||
551 | #define MMCHS_SYSSTATUS 0x0014 | ||
552 | #define MMCHS_SYSSTATUS_RESETDONE (1 << 0) | ||
553 | |||
554 | static struct platform_device dummy_pdev = { | ||
555 | .dev = { | ||
556 | .bus = &platform_bus_type, | ||
557 | }, | ||
558 | }; | ||
559 | |||
560 | /** | ||
561 | * omap_hsmmc_reset() - Full reset of each HS-MMC controller | ||
562 | * | ||
563 | * Ensure that each MMC controller is fully reset. Controllers | ||
564 | * left in an unknown state (by bootloader) may prevent retention | ||
565 | * or OFF-mode. This is especially important in cases where the | ||
566 | * MMC driver is not enabled, _or_ built as a module. | ||
567 | * | ||
568 | * In order for reset to work, interface, functional and debounce | ||
569 | * clocks must be enabled. The debounce clock comes from func_32k_clk | ||
570 | * and is not under SW control, so we only enable i- and f-clocks. | ||
571 | **/ | ||
572 | static void __init omap_hsmmc_reset(void) | ||
573 | { | ||
574 | u32 i, nr_controllers; | ||
575 | struct clk *iclk, *fclk; | ||
576 | |||
577 | if (cpu_is_omap242x()) | ||
578 | return; | ||
579 | |||
580 | nr_controllers = cpu_is_omap44xx() ? OMAP44XX_NR_MMC : | ||
581 | (cpu_is_omap34xx() ? OMAP34XX_NR_MMC : OMAP24XX_NR_MMC); | ||
582 | |||
583 | for (i = 0; i < nr_controllers; i++) { | ||
584 | u32 v, base = 0; | ||
585 | struct device *dev = &dummy_pdev.dev; | ||
586 | |||
587 | switch (i) { | ||
588 | case 0: | ||
589 | base = OMAP2_MMC1_BASE; | ||
590 | break; | ||
591 | case 1: | ||
592 | base = OMAP2_MMC2_BASE; | ||
593 | break; | ||
594 | case 2: | ||
595 | base = OMAP3_MMC3_BASE; | ||
596 | break; | ||
597 | case 3: | ||
598 | if (!cpu_is_omap44xx()) | ||
599 | return; | ||
600 | base = OMAP4_MMC4_BASE; | ||
601 | break; | ||
602 | case 4: | ||
603 | if (!cpu_is_omap44xx()) | ||
604 | return; | ||
605 | base = OMAP4_MMC5_BASE; | ||
606 | break; | ||
607 | } | ||
608 | |||
609 | if (cpu_is_omap44xx()) | ||
610 | base += OMAP4_MMC_REG_OFFSET; | ||
611 | |||
612 | dummy_pdev.id = i; | ||
613 | dev_set_name(&dummy_pdev.dev, "mmci-omap-hs.%d", i); | ||
614 | iclk = clk_get(dev, "ick"); | ||
615 | if (IS_ERR(iclk)) | ||
616 | goto err1; | ||
617 | if (clk_enable(iclk)) | ||
618 | goto err2; | ||
619 | |||
620 | fclk = clk_get(dev, "fck"); | ||
621 | if (IS_ERR(fclk)) | ||
622 | goto err3; | ||
623 | if (clk_enable(fclk)) | ||
624 | goto err4; | ||
625 | |||
626 | omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG); | ||
627 | v = omap_readl(base + MMCHS_SYSSTATUS); | ||
628 | while (!(omap_readl(base + MMCHS_SYSSTATUS) & | ||
629 | MMCHS_SYSSTATUS_RESETDONE)) | ||
630 | cpu_relax(); | ||
631 | |||
632 | clk_disable(fclk); | ||
633 | clk_put(fclk); | ||
634 | clk_disable(iclk); | ||
635 | clk_put(iclk); | ||
636 | } | ||
637 | return; | ||
638 | |||
639 | err4: | ||
640 | clk_put(fclk); | ||
641 | err3: | ||
642 | clk_disable(iclk); | ||
643 | err2: | ||
644 | clk_put(iclk); | ||
645 | err1: | ||
646 | printk(KERN_WARNING "%s: Unable to enable clocks for MMC%d, " | ||
647 | "cannot reset.\n", __func__, i); | ||
648 | } | ||
649 | #else | ||
650 | static inline void omap_hsmmc_reset(void) {} | ||
651 | #endif | ||
652 | |||
653 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) | 547 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) |
654 | 548 | ||
655 | static inline void omap242x_mmc_mux(struct omap_mmc_platform_data | 549 | static inline void omap242x_mmc_mux(struct omap_mmc_platform_data |
@@ -706,67 +600,6 @@ void __init omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data) | |||
706 | 600 | ||
707 | #endif | 601 | #endif |
708 | 602 | ||
709 | #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) | ||
710 | |||
711 | void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, | ||
712 | int nr_controllers) | ||
713 | { | ||
714 | int i; | ||
715 | char *name; | ||
716 | |||
717 | for (i = 0; i < nr_controllers; i++) { | ||
718 | unsigned long base, size; | ||
719 | unsigned int irq = 0; | ||
720 | |||
721 | if (!mmc_data[i]) | ||
722 | continue; | ||
723 | |||
724 | switch (i) { | ||
725 | case 0: | ||
726 | base = OMAP2_MMC1_BASE; | ||
727 | irq = INT_24XX_MMC_IRQ; | ||
728 | break; | ||
729 | case 1: | ||
730 | base = OMAP2_MMC2_BASE; | ||
731 | irq = INT_24XX_MMC2_IRQ; | ||
732 | break; | ||
733 | case 2: | ||
734 | if (!cpu_is_omap44xx() && !cpu_is_omap34xx()) | ||
735 | return; | ||
736 | base = OMAP3_MMC3_BASE; | ||
737 | irq = INT_34XX_MMC3_IRQ; | ||
738 | break; | ||
739 | case 3: | ||
740 | if (!cpu_is_omap44xx()) | ||
741 | return; | ||
742 | base = OMAP4_MMC4_BASE; | ||
743 | irq = OMAP44XX_IRQ_MMC4; | ||
744 | break; | ||
745 | case 4: | ||
746 | if (!cpu_is_omap44xx()) | ||
747 | return; | ||
748 | base = OMAP4_MMC5_BASE; | ||
749 | irq = OMAP44XX_IRQ_MMC5; | ||
750 | break; | ||
751 | default: | ||
752 | continue; | ||
753 | } | ||
754 | |||
755 | if (cpu_is_omap44xx()) { | ||
756 | if (i < 3) | ||
757 | irq += OMAP44XX_IRQ_GIC_START; | ||
758 | size = OMAP4_HSMMC_SIZE; | ||
759 | name = "mmci-omap-hs"; | ||
760 | } else { | ||
761 | size = OMAP3_HSMMC_SIZE; | ||
762 | name = "mmci-omap-hs"; | ||
763 | } | ||
764 | omap_mmc_add(name, i, base, size, irq, mmc_data[i]); | ||
765 | }; | ||
766 | } | ||
767 | |||
768 | #endif | ||
769 | |||
770 | /*-------------------------------------------------------------------------*/ | 603 | /*-------------------------------------------------------------------------*/ |
771 | 604 | ||
772 | #if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE) | 605 | #if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE) |
@@ -836,7 +669,6 @@ static int __init omap2_init_devices(void) | |||
836 | * please keep these calls, and their implementations above, | 669 | * please keep these calls, and their implementations above, |
837 | * in alphabetical order so they're easier to sort through. | 670 | * in alphabetical order so they're easier to sort through. |
838 | */ | 671 | */ |
839 | omap_hsmmc_reset(); | ||
840 | omap_init_audio(); | 672 | omap_init_audio(); |
841 | omap_init_camera(); | 673 | omap_init_camera(); |
842 | omap_init_mbox(); | 674 | omap_init_mbox(); |
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 1348ac3d60e3..d492bc4d3428 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <plat/mmc.h> | 17 | #include <plat/mmc.h> |
18 | #include <plat/omap-pm.h> | 18 | #include <plat/omap-pm.h> |
19 | #include <plat/mux.h> | 19 | #include <plat/mux.h> |
20 | #include <plat/omap_device.h> | ||
20 | 21 | ||
21 | #include "mux.h" | 22 | #include "mux.h" |
22 | #include "hsmmc.h" | 23 | #include "hsmmc.h" |
@@ -30,10 +31,6 @@ static u16 control_mmc1; | |||
30 | 31 | ||
31 | #define HSMMC_NAME_LEN 9 | 32 | #define HSMMC_NAME_LEN 9 |
32 | 33 | ||
33 | static struct hsmmc_controller { | ||
34 | char name[HSMMC_NAME_LEN + 1]; | ||
35 | } hsmmc[OMAP34XX_NR_MMC]; | ||
36 | |||
37 | #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) | 34 | #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) |
38 | 35 | ||
39 | static int hsmmc_get_context_loss(struct device *dev) | 36 | static int hsmmc_get_context_loss(struct device *dev) |
@@ -287,13 +284,203 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, | |||
287 | } | 284 | } |
288 | } | 285 | } |
289 | 286 | ||
290 | static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; | 287 | static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, |
288 | struct omap_mmc_platform_data *mmc) | ||
289 | { | ||
290 | char *hc_name; | ||
291 | |||
292 | hc_name = kzalloc(sizeof(char) * (HSMMC_NAME_LEN + 1), GFP_KERNEL); | ||
293 | if (!hc_name) { | ||
294 | pr_err("Cannot allocate memory for controller slot name\n"); | ||
295 | kfree(hc_name); | ||
296 | return -ENOMEM; | ||
297 | } | ||
298 | |||
299 | if (c->name) | ||
300 | strncpy(hc_name, c->name, HSMMC_NAME_LEN); | ||
301 | else | ||
302 | snprintf(hc_name, (HSMMC_NAME_LEN + 1), "mmc%islot%i", | ||
303 | c->mmc, 1); | ||
304 | mmc->slots[0].name = hc_name; | ||
305 | mmc->nr_slots = 1; | ||
306 | mmc->slots[0].caps = c->caps; | ||
307 | mmc->slots[0].internal_clock = !c->ext_clock; | ||
308 | mmc->dma_mask = 0xffffffff; | ||
309 | if (cpu_is_omap44xx()) | ||
310 | mmc->reg_offset = OMAP4_MMC_REG_OFFSET; | ||
311 | else | ||
312 | mmc->reg_offset = 0; | ||
313 | |||
314 | mmc->get_context_loss_count = hsmmc_get_context_loss; | ||
315 | |||
316 | mmc->slots[0].switch_pin = c->gpio_cd; | ||
317 | mmc->slots[0].gpio_wp = c->gpio_wp; | ||
318 | |||
319 | mmc->slots[0].remux = c->remux; | ||
320 | mmc->slots[0].init_card = c->init_card; | ||
321 | |||
322 | if (c->cover_only) | ||
323 | mmc->slots[0].cover = 1; | ||
324 | |||
325 | if (c->nonremovable) | ||
326 | mmc->slots[0].nonremovable = 1; | ||
327 | |||
328 | if (c->power_saving) | ||
329 | mmc->slots[0].power_saving = 1; | ||
330 | |||
331 | if (c->no_off) | ||
332 | mmc->slots[0].no_off = 1; | ||
333 | |||
334 | if (c->vcc_aux_disable_is_sleep) | ||
335 | mmc->slots[0].vcc_aux_disable_is_sleep = 1; | ||
336 | |||
337 | /* | ||
338 | * NOTE: MMC slots should have a Vcc regulator set up. | ||
339 | * This may be from a TWL4030-family chip, another | ||
340 | * controllable regulator, or a fixed supply. | ||
341 | * | ||
342 | * temporary HACK: ocr_mask instead of fixed supply | ||
343 | */ | ||
344 | mmc->slots[0].ocr_mask = c->ocr_mask; | ||
345 | |||
346 | if (cpu_is_omap3517() || cpu_is_omap3505()) | ||
347 | mmc->slots[0].set_power = nop_mmc_set_power; | ||
348 | else | ||
349 | mmc->slots[0].features |= HSMMC_HAS_PBIAS; | ||
350 | |||
351 | if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0)) | ||
352 | mmc->slots[0].features |= HSMMC_HAS_UPDATED_RESET; | ||
353 | |||
354 | switch (c->mmc) { | ||
355 | case 1: | ||
356 | if (mmc->slots[0].features & HSMMC_HAS_PBIAS) { | ||
357 | /* on-chip level shifting via PBIAS0/PBIAS1 */ | ||
358 | if (cpu_is_omap44xx()) { | ||
359 | mmc->slots[0].before_set_reg = | ||
360 | omap4_hsmmc1_before_set_reg; | ||
361 | mmc->slots[0].after_set_reg = | ||
362 | omap4_hsmmc1_after_set_reg; | ||
363 | } else { | ||
364 | mmc->slots[0].before_set_reg = | ||
365 | omap_hsmmc1_before_set_reg; | ||
366 | mmc->slots[0].after_set_reg = | ||
367 | omap_hsmmc1_after_set_reg; | ||
368 | } | ||
369 | } | ||
370 | |||
371 | /* OMAP3630 HSMMC1 supports only 4-bit */ | ||
372 | if (cpu_is_omap3630() && | ||
373 | (c->caps & MMC_CAP_8_BIT_DATA)) { | ||
374 | c->caps &= ~MMC_CAP_8_BIT_DATA; | ||
375 | c->caps |= MMC_CAP_4_BIT_DATA; | ||
376 | mmc->slots[0].caps = c->caps; | ||
377 | } | ||
378 | break; | ||
379 | case 2: | ||
380 | if (c->ext_clock) | ||
381 | c->transceiver = 1; | ||
382 | if (c->transceiver && (c->caps & MMC_CAP_8_BIT_DATA)) { | ||
383 | c->caps &= ~MMC_CAP_8_BIT_DATA; | ||
384 | c->caps |= MMC_CAP_4_BIT_DATA; | ||
385 | } | ||
386 | /* FALLTHROUGH */ | ||
387 | case 3: | ||
388 | if (mmc->slots[0].features & HSMMC_HAS_PBIAS) { | ||
389 | /* off-chip level shifting, or none */ | ||
390 | mmc->slots[0].before_set_reg = hsmmc23_before_set_reg; | ||
391 | mmc->slots[0].after_set_reg = NULL; | ||
392 | } | ||
393 | break; | ||
394 | case 4: | ||
395 | case 5: | ||
396 | mmc->slots[0].before_set_reg = NULL; | ||
397 | mmc->slots[0].after_set_reg = NULL; | ||
398 | break; | ||
399 | default: | ||
400 | pr_err("MMC%d configuration not supported!\n", c->mmc); | ||
401 | kfree(hc_name); | ||
402 | return -ENODEV; | ||
403 | } | ||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | static struct omap_device_pm_latency omap_hsmmc_latency[] = { | ||
408 | [0] = { | ||
409 | .deactivate_func = omap_device_idle_hwmods, | ||
410 | .activate_func = omap_device_enable_hwmods, | ||
411 | .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, | ||
412 | }, | ||
413 | /* | ||
414 | * XXX There should also be an entry here to power off/on the | ||
415 | * MMC regulators/PBIAS cells, etc. | ||
416 | */ | ||
417 | }; | ||
418 | |||
419 | #define MAX_OMAP_MMC_HWMOD_NAME_LEN 16 | ||
420 | |||
421 | void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr) | ||
422 | { | ||
423 | struct omap_hwmod *oh; | ||
424 | struct omap_device *od; | ||
425 | struct omap_device_pm_latency *ohl; | ||
426 | char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN]; | ||
427 | struct omap_mmc_platform_data *mmc_data; | ||
428 | struct omap_mmc_dev_attr *mmc_dev_attr; | ||
429 | char *name; | ||
430 | int l; | ||
431 | int ohl_cnt = 0; | ||
432 | |||
433 | mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL); | ||
434 | if (!mmc_data) { | ||
435 | pr_err("Cannot allocate memory for mmc device!\n"); | ||
436 | goto done; | ||
437 | } | ||
438 | |||
439 | if (omap_hsmmc_pdata_init(hsmmcinfo, mmc_data) < 0) { | ||
440 | pr_err("%s fails!\n", __func__); | ||
441 | goto done; | ||
442 | } | ||
443 | omap_hsmmc_mux(mmc_data, (ctrl_nr - 1)); | ||
444 | |||
445 | name = "mmci-omap-hs"; | ||
446 | ohl = omap_hsmmc_latency; | ||
447 | ohl_cnt = ARRAY_SIZE(omap_hsmmc_latency); | ||
448 | |||
449 | l = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN, | ||
450 | "mmc%d", ctrl_nr); | ||
451 | WARN(l >= MAX_OMAP_MMC_HWMOD_NAME_LEN, | ||
452 | "String buffer overflow in MMC%d device setup\n", ctrl_nr); | ||
453 | oh = omap_hwmod_lookup(oh_name); | ||
454 | if (!oh) { | ||
455 | pr_err("Could not look up %s\n", oh_name); | ||
456 | kfree(mmc_data->slots[0].name); | ||
457 | goto done; | ||
458 | } | ||
459 | |||
460 | if (oh->dev_attr != NULL) { | ||
461 | mmc_dev_attr = oh->dev_attr; | ||
462 | mmc_data->controller_flags = mmc_dev_attr->flags; | ||
463 | } | ||
464 | |||
465 | od = omap_device_build(name, ctrl_nr - 1, oh, mmc_data, | ||
466 | sizeof(struct omap_mmc_platform_data), ohl, ohl_cnt, false); | ||
467 | if (IS_ERR(od)) { | ||
468 | WARN(1, "Cant build omap_device for %s:%s.\n", name, oh->name); | ||
469 | kfree(mmc_data->slots[0].name); | ||
470 | goto done; | ||
471 | } | ||
472 | /* | ||
473 | * return device handle to board setup code | ||
474 | * required to populate for regulator framework structure | ||
475 | */ | ||
476 | hsmmcinfo->dev = &od->pdev.dev; | ||
477 | |||
478 | done: | ||
479 | kfree(mmc_data); | ||
480 | } | ||
291 | 481 | ||
292 | void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers) | 482 | void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers) |
293 | { | 483 | { |
294 | struct omap2_hsmmc_info *c; | ||
295 | int nr_hsmmc = ARRAY_SIZE(hsmmc_data); | ||
296 | int i; | ||
297 | u32 reg; | 484 | u32 reg; |
298 | 485 | ||
299 | if (!cpu_is_omap44xx()) { | 486 | if (!cpu_is_omap44xx()) { |
@@ -319,148 +506,9 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers) | |||
319 | omap4_ctrl_pad_writel(reg, control_mmc1); | 506 | omap4_ctrl_pad_writel(reg, control_mmc1); |
320 | } | 507 | } |
321 | 508 | ||
322 | for (c = controllers; c->mmc; c++) { | 509 | for (; controllers->mmc; controllers++) |
323 | struct hsmmc_controller *hc = hsmmc + c->mmc - 1; | 510 | omap_init_hsmmc(controllers, controllers->mmc); |
324 | struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1]; | ||
325 | |||
326 | if (!c->mmc || c->mmc > nr_hsmmc) { | ||
327 | pr_debug("MMC%d: no such controller\n", c->mmc); | ||
328 | continue; | ||
329 | } | ||
330 | if (mmc) { | ||
331 | pr_debug("MMC%d: already configured\n", c->mmc); | ||
332 | continue; | ||
333 | } | ||
334 | |||
335 | mmc = kzalloc(sizeof(struct omap_mmc_platform_data), | ||
336 | GFP_KERNEL); | ||
337 | if (!mmc) { | ||
338 | pr_err("Cannot allocate memory for mmc device!\n"); | ||
339 | goto done; | ||
340 | } | ||
341 | |||
342 | if (c->name) | ||
343 | strncpy(hc->name, c->name, HSMMC_NAME_LEN); | ||
344 | else | ||
345 | snprintf(hc->name, ARRAY_SIZE(hc->name), | ||
346 | "mmc%islot%i", c->mmc, 1); | ||
347 | mmc->slots[0].name = hc->name; | ||
348 | mmc->nr_slots = 1; | ||
349 | mmc->slots[0].caps = c->caps; | ||
350 | mmc->slots[0].internal_clock = !c->ext_clock; | ||
351 | mmc->dma_mask = 0xffffffff; | ||
352 | if (cpu_is_omap44xx()) | ||
353 | mmc->reg_offset = OMAP4_MMC_REG_OFFSET; | ||
354 | else | ||
355 | mmc->reg_offset = 0; | ||
356 | |||
357 | mmc->get_context_loss_count = hsmmc_get_context_loss; | ||
358 | |||
359 | mmc->slots[0].switch_pin = c->gpio_cd; | ||
360 | mmc->slots[0].gpio_wp = c->gpio_wp; | ||
361 | |||
362 | mmc->slots[0].remux = c->remux; | ||
363 | mmc->slots[0].init_card = c->init_card; | ||
364 | |||
365 | if (c->cover_only) | ||
366 | mmc->slots[0].cover = 1; | ||
367 | |||
368 | if (c->nonremovable) | ||
369 | mmc->slots[0].nonremovable = 1; | ||
370 | |||
371 | if (c->power_saving) | ||
372 | mmc->slots[0].power_saving = 1; | ||
373 | |||
374 | if (c->no_off) | ||
375 | mmc->slots[0].no_off = 1; | ||
376 | |||
377 | if (c->vcc_aux_disable_is_sleep) | ||
378 | mmc->slots[0].vcc_aux_disable_is_sleep = 1; | ||
379 | |||
380 | /* NOTE: MMC slots should have a Vcc regulator set up. | ||
381 | * This may be from a TWL4030-family chip, another | ||
382 | * controllable regulator, or a fixed supply. | ||
383 | * | ||
384 | * temporary HACK: ocr_mask instead of fixed supply | ||
385 | */ | ||
386 | mmc->slots[0].ocr_mask = c->ocr_mask; | ||
387 | |||
388 | if (cpu_is_omap3517() || cpu_is_omap3505()) | ||
389 | mmc->slots[0].set_power = nop_mmc_set_power; | ||
390 | else | ||
391 | mmc->slots[0].features |= HSMMC_HAS_PBIAS; | ||
392 | |||
393 | if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0)) | ||
394 | mmc->slots[0].features |= HSMMC_HAS_UPDATED_RESET; | ||
395 | |||
396 | switch (c->mmc) { | ||
397 | case 1: | ||
398 | if (mmc->slots[0].features & HSMMC_HAS_PBIAS) { | ||
399 | /* on-chip level shifting via PBIAS0/PBIAS1 */ | ||
400 | if (cpu_is_omap44xx()) { | ||
401 | mmc->slots[0].before_set_reg = | ||
402 | omap4_hsmmc1_before_set_reg; | ||
403 | mmc->slots[0].after_set_reg = | ||
404 | omap4_hsmmc1_after_set_reg; | ||
405 | } else { | ||
406 | mmc->slots[0].before_set_reg = | ||
407 | omap_hsmmc1_before_set_reg; | ||
408 | mmc->slots[0].after_set_reg = | ||
409 | omap_hsmmc1_after_set_reg; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | /* Omap3630 HSMMC1 supports only 4-bit */ | ||
414 | if (cpu_is_omap3630() && | ||
415 | (c->caps & MMC_CAP_8_BIT_DATA)) { | ||
416 | c->caps &= ~MMC_CAP_8_BIT_DATA; | ||
417 | c->caps |= MMC_CAP_4_BIT_DATA; | ||
418 | mmc->slots[0].caps = c->caps; | ||
419 | } | ||
420 | break; | ||
421 | case 2: | ||
422 | if (c->ext_clock) | ||
423 | c->transceiver = 1; | ||
424 | if (c->transceiver && (c->caps & MMC_CAP_8_BIT_DATA)) { | ||
425 | c->caps &= ~MMC_CAP_8_BIT_DATA; | ||
426 | c->caps |= MMC_CAP_4_BIT_DATA; | ||
427 | } | ||
428 | /* FALLTHROUGH */ | ||
429 | case 3: | ||
430 | if (mmc->slots[0].features & HSMMC_HAS_PBIAS) { | ||
431 | /* off-chip level shifting, or none */ | ||
432 | mmc->slots[0].before_set_reg = hsmmc23_before_set_reg; | ||
433 | mmc->slots[0].after_set_reg = NULL; | ||
434 | } | ||
435 | break; | ||
436 | case 4: | ||
437 | case 5: | ||
438 | mmc->slots[0].before_set_reg = NULL; | ||
439 | mmc->slots[0].after_set_reg = NULL; | ||
440 | break; | ||
441 | default: | ||
442 | pr_err("MMC%d configuration not supported!\n", c->mmc); | ||
443 | kfree(mmc); | ||
444 | continue; | ||
445 | } | ||
446 | hsmmc_data[c->mmc - 1] = mmc; | ||
447 | omap_hsmmc_mux(hsmmc_data[c->mmc - 1], (c->mmc - 1)); | ||
448 | } | ||
449 | |||
450 | omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC); | ||
451 | |||
452 | /* pass the device nodes back to board setup code */ | ||
453 | for (c = controllers; c->mmc; c++) { | ||
454 | struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1]; | ||
455 | 511 | ||
456 | if (!c->mmc || c->mmc > nr_hsmmc) | ||
457 | continue; | ||
458 | c->dev = mmc->dev; | ||
459 | } | ||
460 | |||
461 | done: | ||
462 | for (i = 0; i < nr_hsmmc; i++) | ||
463 | kfree(hsmmc_data[i]); | ||
464 | } | 512 | } |
465 | 513 | ||
466 | #endif | 514 | #endif |
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h index a7afab095716..f38fef9f1310 100644 --- a/arch/arm/plat-omap/include/plat/mmc.h +++ b/arch/arm/plat-omap/include/plat/mmc.h | |||
@@ -24,22 +24,10 @@ | |||
24 | #define OMAP1_MMC2_BASE 0xfffb7c00 /* omap16xx only */ | 24 | #define OMAP1_MMC2_BASE 0xfffb7c00 /* omap16xx only */ |
25 | 25 | ||
26 | #define OMAP24XX_NR_MMC 2 | 26 | #define OMAP24XX_NR_MMC 2 |
27 | #define OMAP34XX_NR_MMC 3 | ||
28 | #define OMAP44XX_NR_MMC 5 | ||
29 | #define OMAP2420_MMC_SIZE OMAP1_MMC_SIZE | 27 | #define OMAP2420_MMC_SIZE OMAP1_MMC_SIZE |
30 | #define OMAP3_HSMMC_SIZE 0x200 | ||
31 | #define OMAP4_HSMMC_SIZE 0x1000 | ||
32 | #define OMAP2_MMC1_BASE 0x4809c000 | 28 | #define OMAP2_MMC1_BASE 0x4809c000 |
33 | #define OMAP2_MMC2_BASE 0x480b4000 | 29 | |
34 | #define OMAP3_MMC3_BASE 0x480ad000 | ||
35 | #define OMAP4_MMC4_BASE 0x480d1000 | ||
36 | #define OMAP4_MMC5_BASE 0x480d5000 | ||
37 | #define OMAP4_MMC_REG_OFFSET 0x100 | 30 | #define OMAP4_MMC_REG_OFFSET 0x100 |
38 | #define HSMMC5 (1 << 4) | ||
39 | #define HSMMC4 (1 << 3) | ||
40 | #define HSMMC3 (1 << 2) | ||
41 | #define HSMMC2 (1 << 1) | ||
42 | #define HSMMC1 (1 << 0) | ||
43 | 31 | ||
44 | #define OMAP_MMC_MAX_SLOTS 2 | 32 | #define OMAP_MMC_MAX_SLOTS 2 |
45 | 33 | ||
@@ -169,8 +157,6 @@ extern void omap_mmc_notify_cover_event(struct device *dev, int slot, | |||
169 | void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, | 157 | void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, |
170 | int nr_controllers); | 158 | int nr_controllers); |
171 | void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data); | 159 | void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data); |
172 | void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, | ||
173 | int nr_controllers); | ||
174 | int omap_mmc_add(const char *name, int id, unsigned long base, | 160 | int omap_mmc_add(const char *name, int id, unsigned long base, |
175 | unsigned long size, unsigned int irq, | 161 | unsigned long size, unsigned int irq, |
176 | struct omap_mmc_platform_data *data); | 162 | struct omap_mmc_platform_data *data); |
@@ -182,10 +168,6 @@ static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, | |||
182 | static inline void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data) | 168 | static inline void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data) |
183 | { | 169 | { |
184 | } | 170 | } |
185 | static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, | ||
186 | int nr_controllers) | ||
187 | { | ||
188 | } | ||
189 | static inline int omap_mmc_add(const char *name, int id, unsigned long base, | 171 | static inline int omap_mmc_add(const char *name, int id, unsigned long base, |
190 | unsigned long size, unsigned int irq, | 172 | unsigned long size, unsigned int irq, |
191 | struct omap_mmc_platform_data *data) | 173 | struct omap_mmc_platform_data *data) |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 8c42573f42ea..d0bd2b43393a 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -1571,7 +1571,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1571 | break; | 1571 | break; |
1572 | } | 1572 | } |
1573 | 1573 | ||
1574 | if (host->id == OMAP_MMC1_DEVID) { | 1574 | if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { |
1575 | /* Only MMC1 can interface at 3V without some flavor | 1575 | /* Only MMC1 can interface at 3V without some flavor |
1576 | * of external transceiver; but they all handle 1.8V. | 1576 | * of external transceiver; but they all handle 1.8V. |
1577 | */ | 1577 | */ |
@@ -1663,7 +1663,7 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) | |||
1663 | u32 hctl, capa, value; | 1663 | u32 hctl, capa, value; |
1664 | 1664 | ||
1665 | /* Only MMC1 supports 3.0V */ | 1665 | /* Only MMC1 supports 3.0V */ |
1666 | if (host->id == OMAP_MMC1_DEVID) { | 1666 | if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { |
1667 | hctl = SDVS30; | 1667 | hctl = SDVS30; |
1668 | capa = VS30 | VS18; | 1668 | capa = VS30 | VS18; |
1669 | } else { | 1669 | } else { |