diff options
author | Kevin Hilman <khilman@ti.com> | 2012-03-05 18:37:04 -0500 |
---|---|---|
committer | Kevin Hilman <khilman@ti.com> | 2012-03-05 18:37:04 -0500 |
commit | 015f1e4297ad32f83251f3f4cee2389ce5516e9e (patch) | |
tree | 1b16e317005dc3d09b0551a4db9182f7f4119f71 /arch/arm/mach-omap2/hsmmc.c | |
parent | 1b35af54ee9cbbdd13fed53fd4acb0952ba522e1 (diff) | |
parent | 9cf793f9b8b1ba9414e2a7591b2e911885f85a27 (diff) |
Merge remote-tracking branch 'omap/hsmmc' into for_3.4/cleanup/pm-base
Diffstat (limited to 'arch/arm/mach-omap2/hsmmc.c')
-rw-r--r-- | arch/arm/mach-omap2/hsmmc.c | 125 |
1 files changed, 98 insertions, 27 deletions
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index ad0adb5a1e0e..a97876da7fad 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c | |||
@@ -428,69 +428,140 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, | |||
428 | return 0; | 428 | return 0; |
429 | } | 429 | } |
430 | 430 | ||
431 | static int omap_hsmmc_done; | ||
432 | |||
433 | void omap_hsmmc_late_init(struct omap2_hsmmc_info *c) | ||
434 | { | ||
435 | struct platform_device *pdev; | ||
436 | struct omap_mmc_platform_data *mmc_pdata; | ||
437 | int res; | ||
438 | |||
439 | if (omap_hsmmc_done != 1) | ||
440 | return; | ||
441 | |||
442 | omap_hsmmc_done++; | ||
443 | |||
444 | for (; c->mmc; c++) { | ||
445 | if (!c->deferred) | ||
446 | continue; | ||
447 | |||
448 | pdev = c->pdev; | ||
449 | if (!pdev) | ||
450 | continue; | ||
451 | |||
452 | mmc_pdata = pdev->dev.platform_data; | ||
453 | if (!mmc_pdata) | ||
454 | continue; | ||
455 | |||
456 | mmc_pdata->slots[0].switch_pin = c->gpio_cd; | ||
457 | mmc_pdata->slots[0].gpio_wp = c->gpio_wp; | ||
458 | |||
459 | res = omap_device_register(pdev); | ||
460 | if (res) | ||
461 | pr_err("Could not late init MMC %s\n", | ||
462 | c->name); | ||
463 | } | ||
464 | } | ||
465 | |||
431 | #define MAX_OMAP_MMC_HWMOD_NAME_LEN 16 | 466 | #define MAX_OMAP_MMC_HWMOD_NAME_LEN 16 |
432 | 467 | ||
433 | void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr) | 468 | static void omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, |
469 | int ctrl_nr) | ||
434 | { | 470 | { |
435 | struct omap_hwmod *oh; | 471 | struct omap_hwmod *oh; |
472 | struct omap_hwmod *ohs[1]; | ||
473 | struct omap_device *od; | ||
436 | struct platform_device *pdev; | 474 | struct platform_device *pdev; |
437 | char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN]; | 475 | char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN]; |
438 | struct omap_mmc_platform_data *mmc_data; | 476 | struct omap_mmc_platform_data *mmc_data; |
439 | struct omap_mmc_dev_attr *mmc_dev_attr; | 477 | struct omap_mmc_dev_attr *mmc_dev_attr; |
440 | char *name; | 478 | char *name; |
441 | int l; | 479 | int res; |
442 | 480 | ||
443 | mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL); | 481 | mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL); |
444 | if (!mmc_data) { | 482 | if (!mmc_data) { |
445 | pr_err("Cannot allocate memory for mmc device!\n"); | 483 | pr_err("Cannot allocate memory for mmc device!\n"); |
446 | goto done; | 484 | return; |
447 | } | 485 | } |
448 | 486 | ||
449 | if (omap_hsmmc_pdata_init(hsmmcinfo, mmc_data) < 0) { | 487 | res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data); |
450 | pr_err("%s fails!\n", __func__); | 488 | if (res < 0) |
451 | goto done; | 489 | goto free_mmc; |
452 | } | 490 | |
453 | omap_hsmmc_mux(mmc_data, (ctrl_nr - 1)); | 491 | omap_hsmmc_mux(mmc_data, (ctrl_nr - 1)); |
454 | 492 | ||
455 | name = "omap_hsmmc"; | 493 | name = "omap_hsmmc"; |
456 | 494 | res = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN, | |
457 | l = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN, | ||
458 | "mmc%d", ctrl_nr); | 495 | "mmc%d", ctrl_nr); |
459 | WARN(l >= MAX_OMAP_MMC_HWMOD_NAME_LEN, | 496 | WARN(res >= MAX_OMAP_MMC_HWMOD_NAME_LEN, |
460 | "String buffer overflow in MMC%d device setup\n", ctrl_nr); | 497 | "String buffer overflow in MMC%d device setup\n", ctrl_nr); |
498 | |||
461 | oh = omap_hwmod_lookup(oh_name); | 499 | oh = omap_hwmod_lookup(oh_name); |
462 | if (!oh) { | 500 | if (!oh) { |
463 | pr_err("Could not look up %s\n", oh_name); | 501 | pr_err("Could not look up %s\n", oh_name); |
464 | kfree(mmc_data->slots[0].name); | 502 | goto free_name; |
465 | goto done; | ||
466 | } | 503 | } |
467 | 504 | ohs[0] = oh; | |
468 | if (oh->dev_attr != NULL) { | 505 | if (oh->dev_attr != NULL) { |
469 | mmc_dev_attr = oh->dev_attr; | 506 | mmc_dev_attr = oh->dev_attr; |
470 | mmc_data->controller_flags = mmc_dev_attr->flags; | 507 | mmc_data->controller_flags = mmc_dev_attr->flags; |
471 | } | 508 | } |
472 | 509 | ||
473 | pdev = omap_device_build(name, ctrl_nr - 1, oh, mmc_data, | 510 | pdev = platform_device_alloc(name, ctrl_nr - 1); |
474 | sizeof(struct omap_mmc_platform_data), NULL, 0, false); | 511 | if (!pdev) { |
475 | if (IS_ERR(pdev)) { | 512 | pr_err("Could not allocate pdev for %s\n", name); |
476 | WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name); | 513 | goto free_name; |
477 | kfree(mmc_data->slots[0].name); | ||
478 | goto done; | ||
479 | } | 514 | } |
480 | /* | 515 | dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); |
481 | * return device handle to board setup code | 516 | |
482 | * required to populate for regulator framework structure | 517 | od = omap_device_alloc(pdev, ohs, 1, NULL, 0); |
483 | */ | 518 | if (!od) { |
484 | hsmmcinfo->dev = &pdev->dev; | 519 | pr_err("Could not allocate od for %s\n", name); |
520 | goto put_pdev; | ||
521 | } | ||
522 | |||
523 | res = platform_device_add_data(pdev, mmc_data, | ||
524 | sizeof(struct omap_mmc_platform_data)); | ||
525 | if (res) { | ||
526 | pr_err("Could not add pdata for %s\n", name); | ||
527 | goto put_pdev; | ||
528 | } | ||
529 | |||
530 | hsmmcinfo->pdev = pdev; | ||
531 | |||
532 | if (hsmmcinfo->deferred) | ||
533 | goto free_mmc; | ||
485 | 534 | ||
486 | done: | 535 | res = omap_device_register(pdev); |
536 | if (res) { | ||
537 | pr_err("Could not register od for %s\n", name); | ||
538 | goto free_od; | ||
539 | } | ||
540 | |||
541 | goto free_mmc; | ||
542 | |||
543 | free_od: | ||
544 | omap_device_delete(od); | ||
545 | |||
546 | put_pdev: | ||
547 | platform_device_put(pdev); | ||
548 | |||
549 | free_name: | ||
550 | kfree(mmc_data->slots[0].name); | ||
551 | |||
552 | free_mmc: | ||
487 | kfree(mmc_data); | 553 | kfree(mmc_data); |
488 | } | 554 | } |
489 | 555 | ||
490 | void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers) | 556 | void __init omap_hsmmc_init(struct omap2_hsmmc_info *controllers) |
491 | { | 557 | { |
492 | u32 reg; | 558 | u32 reg; |
493 | 559 | ||
560 | if (omap_hsmmc_done) | ||
561 | return; | ||
562 | |||
563 | omap_hsmmc_done = 1; | ||
564 | |||
494 | if (!cpu_is_omap44xx()) { | 565 | if (!cpu_is_omap44xx()) { |
495 | if (cpu_is_omap2430()) { | 566 | if (cpu_is_omap2430()) { |
496 | control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE; | 567 | control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE; |
@@ -515,7 +586,7 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers) | |||
515 | } | 586 | } |
516 | 587 | ||
517 | for (; controllers->mmc; controllers++) | 588 | for (; controllers->mmc; controllers++) |
518 | omap_init_hsmmc(controllers, controllers->mmc); | 589 | omap_hsmmc_init_one(controllers, controllers->mmc); |
519 | 590 | ||
520 | } | 591 | } |
521 | 592 | ||