hsmmc.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * linux/arch/arm/mach-omap2/hsmmc.c
  3. *
  4. * Copyright (C) 2007-2008 Texas Instruments
  5. * Copyright (C) 2008 Nokia Corporation
  6. * Author: Texas Instruments
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/slab.h>
  14. #include <linux/string.h>
  15. #include <linux/delay.h>
  16. #include <linux/mmc/host.h>
  17. #include <linux/platform_data/hsmmc-omap.h>
  18. #include "soc.h"
  19. #include "omap_device.h"
  20. #include "hsmmc.h"
  21. #include "control.h"
  22. #if IS_ENABLED(CONFIG_MMC_OMAP_HS)
  23. static u16 control_pbias_offset;
  24. static u16 control_devconf1_offset;
  25. #define HSMMC_NAME_LEN 9
  26. static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
  27. struct omap_hsmmc_platform_data *mmc)
  28. {
  29. char *hc_name;
  30. hc_name = kzalloc(HSMMC_NAME_LEN + 1, GFP_KERNEL);
  31. if (!hc_name) {
  32. kfree(hc_name);
  33. return -ENOMEM;
  34. }
  35. snprintf(hc_name, (HSMMC_NAME_LEN + 1), "mmc%islot%i", c->mmc, 1);
  36. mmc->name = hc_name;
  37. mmc->caps = c->caps;
  38. mmc->reg_offset = 0;
  39. return 0;
  40. }
  41. static int omap_hsmmc_done;
  42. void omap_hsmmc_late_init(struct omap2_hsmmc_info *c)
  43. {
  44. struct platform_device *pdev;
  45. int res;
  46. if (omap_hsmmc_done)
  47. return;
  48. omap_hsmmc_done = 1;
  49. for (; c->mmc; c++) {
  50. pdev = c->pdev;
  51. if (!pdev)
  52. continue;
  53. res = omap_device_register(pdev);
  54. if (res)
  55. pr_err("Could not late init MMC\n");
  56. }
  57. }
  58. #define MAX_OMAP_MMC_HWMOD_NAME_LEN 16
  59. static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
  60. int ctrl_nr)
  61. {
  62. struct omap_hwmod *oh;
  63. struct omap_hwmod *ohs[1];
  64. struct omap_device *od;
  65. struct platform_device *pdev;
  66. char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN];
  67. struct omap_hsmmc_platform_data *mmc_data;
  68. struct omap_hsmmc_dev_attr *mmc_dev_attr;
  69. char *name;
  70. int res;
  71. mmc_data = kzalloc(sizeof(*mmc_data), GFP_KERNEL);
  72. if (!mmc_data)
  73. return;
  74. res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data);
  75. if (res < 0)
  76. goto free_mmc;
  77. name = "omap_hsmmc";
  78. res = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
  79. "mmc%d", ctrl_nr);
  80. WARN(res >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
  81. "String buffer overflow in MMC%d device setup\n", ctrl_nr);
  82. oh = omap_hwmod_lookup(oh_name);
  83. if (!oh) {
  84. pr_err("Could not look up %s\n", oh_name);
  85. goto free_name;
  86. }
  87. ohs[0] = oh;
  88. if (oh->dev_attr != NULL) {
  89. mmc_dev_attr = oh->dev_attr;
  90. mmc_data->controller_flags = mmc_dev_attr->flags;
  91. }
  92. pdev = platform_device_alloc(name, ctrl_nr - 1);
  93. if (!pdev) {
  94. pr_err("Could not allocate pdev for %s\n", name);
  95. goto free_name;
  96. }
  97. dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
  98. od = omap_device_alloc(pdev, ohs, 1);
  99. if (IS_ERR(od)) {
  100. pr_err("Could not allocate od for %s\n", name);
  101. goto put_pdev;
  102. }
  103. res = platform_device_add_data(pdev, mmc_data,
  104. sizeof(struct omap_hsmmc_platform_data));
  105. if (res) {
  106. pr_err("Could not add pdata for %s\n", name);
  107. goto put_pdev;
  108. }
  109. hsmmcinfo->pdev = pdev;
  110. res = omap_device_register(pdev);
  111. if (res) {
  112. pr_err("Could not register od for %s\n", name);
  113. goto free_od;
  114. }
  115. goto free_mmc;
  116. free_od:
  117. omap_device_delete(od);
  118. put_pdev:
  119. platform_device_put(pdev);
  120. free_name:
  121. kfree(mmc_data->name);
  122. free_mmc:
  123. kfree(mmc_data);
  124. }
  125. void __init omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
  126. {
  127. if (omap_hsmmc_done)
  128. return;
  129. omap_hsmmc_done = 1;
  130. if (cpu_is_omap2430()) {
  131. control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE;
  132. control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1;
  133. } else {
  134. control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
  135. control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
  136. }
  137. for (; controllers->mmc; controllers++)
  138. omap_hsmmc_init_one(controllers, controllers->mmc);
  139. }
  140. #endif