diff options
Diffstat (limited to 'arch/arm')
| -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 |
3 files changed, 198 insertions, 336 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) |
