dwc3-exynos.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /**
  2. * dwc3-exynos.c - Samsung EXYNOS DWC3 Specific Glue layer
  3. *
  4. * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  5. * http://www.samsung.com
  6. *
  7. * Author: Anton Tikhomirov <av.tikhomirov@samsung.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. */
  14. #include <linux/module.h>
  15. #include <linux/kernel.h>
  16. #include <linux/slab.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/platform_data/dwc3-exynos.h>
  19. #include <linux/dma-mapping.h>
  20. #include <linux/module.h>
  21. #include <linux/clk.h>
  22. #include "core.h"
  23. struct dwc3_exynos {
  24. struct platform_device *dwc3;
  25. struct device *dev;
  26. struct clk *clk;
  27. };
  28. static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
  29. {
  30. struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
  31. struct platform_device *dwc3;
  32. struct dwc3_exynos *exynos;
  33. struct clk *clk;
  34. int devid;
  35. int ret = -ENOMEM;
  36. exynos = kzalloc(sizeof(*exynos), GFP_KERNEL);
  37. if (!exynos) {
  38. dev_err(&pdev->dev, "not enough memory\n");
  39. goto err0;
  40. }
  41. platform_set_drvdata(pdev, exynos);
  42. devid = dwc3_get_device_id();
  43. if (devid < 0)
  44. goto err1;
  45. dwc3 = platform_device_alloc("dwc3", devid);
  46. if (!dwc3) {
  47. dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
  48. goto err2;
  49. }
  50. clk = clk_get(&pdev->dev, "usbdrd30");
  51. if (IS_ERR(clk)) {
  52. dev_err(&pdev->dev, "couldn't get clock\n");
  53. ret = -EINVAL;
  54. goto err3;
  55. }
  56. dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask);
  57. dwc3->dev.parent = &pdev->dev;
  58. dwc3->dev.dma_mask = pdev->dev.dma_mask;
  59. dwc3->dev.dma_parms = pdev->dev.dma_parms;
  60. exynos->dwc3 = dwc3;
  61. exynos->dev = &pdev->dev;
  62. exynos->clk = clk;
  63. clk_enable(exynos->clk);
  64. /* PHY initialization */
  65. if (!pdata) {
  66. dev_dbg(&pdev->dev, "missing platform data\n");
  67. } else {
  68. if (pdata->phy_init)
  69. pdata->phy_init(pdev, pdata->phy_type);
  70. }
  71. ret = platform_device_add_resources(dwc3, pdev->resource,
  72. pdev->num_resources);
  73. if (ret) {
  74. dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
  75. goto err4;
  76. }
  77. ret = platform_device_add(dwc3);
  78. if (ret) {
  79. dev_err(&pdev->dev, "failed to register dwc3 device\n");
  80. goto err4;
  81. }
  82. return 0;
  83. err4:
  84. if (pdata && pdata->phy_exit)
  85. pdata->phy_exit(pdev, pdata->phy_type);
  86. clk_disable(clk);
  87. clk_put(clk);
  88. err3:
  89. platform_device_put(dwc3);
  90. err2:
  91. dwc3_put_device_id(devid);
  92. err1:
  93. kfree(exynos);
  94. err0:
  95. return ret;
  96. }
  97. static int __devexit dwc3_exynos_remove(struct platform_device *pdev)
  98. {
  99. struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
  100. struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
  101. platform_device_unregister(exynos->dwc3);
  102. dwc3_put_device_id(exynos->dwc3->id);
  103. if (pdata && pdata->phy_exit)
  104. pdata->phy_exit(pdev, pdata->phy_type);
  105. clk_disable(exynos->clk);
  106. clk_put(exynos->clk);
  107. kfree(exynos);
  108. return 0;
  109. }
  110. static struct platform_driver dwc3_exynos_driver = {
  111. .probe = dwc3_exynos_probe,
  112. .remove = __devexit_p(dwc3_exynos_remove),
  113. .driver = {
  114. .name = "exynos-dwc3",
  115. },
  116. };
  117. module_platform_driver(dwc3_exynos_driver);
  118. MODULE_ALIAS("platform:exynos-dwc3");
  119. MODULE_AUTHOR("Anton Tikhomirov <av.tikhomirov@samsung.com>");
  120. MODULE_LICENSE("GPL");
  121. MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer");