ci13xxx_msm.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. */
  7. #include <linux/module.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/pm_runtime.h>
  10. #include <linux/usb/msm_hsusb_hw.h>
  11. #include <linux/usb/ulpi.h>
  12. #include "ci13xxx_udc.c"
  13. #define MSM_USB_BASE (udc->regs)
  14. static irqreturn_t msm_udc_irq(int irq, void *data)
  15. {
  16. return udc_irq();
  17. }
  18. static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
  19. {
  20. struct device *dev = udc->gadget.dev.parent;
  21. int val;
  22. switch (event) {
  23. case CI13XXX_CONTROLLER_RESET_EVENT:
  24. dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
  25. writel(0, USB_AHBBURST);
  26. writel(0, USB_AHBMODE);
  27. break;
  28. case CI13XXX_CONTROLLER_STOPPED_EVENT:
  29. dev_dbg(dev, "CI13XXX_CONTROLLER_STOPPED_EVENT received\n");
  30. /*
  31. * Put the transceiver in non-driving mode. Otherwise host
  32. * may not detect soft-disconnection.
  33. */
  34. val = otg_io_read(udc->transceiver, ULPI_FUNC_CTRL);
  35. val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
  36. val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
  37. otg_io_write(udc->transceiver, val, ULPI_FUNC_CTRL);
  38. break;
  39. default:
  40. dev_dbg(dev, "unknown ci13xxx_udc event\n");
  41. break;
  42. }
  43. }
  44. static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
  45. .name = "ci13xxx_msm",
  46. .flags = CI13XXX_REGS_SHARED |
  47. CI13XXX_REQUIRE_TRANSCEIVER |
  48. CI13XXX_PULLUP_ON_VBUS |
  49. CI13XXX_DISABLE_STREAMING,
  50. .notify_event = ci13xxx_msm_notify_event,
  51. };
  52. static int ci13xxx_msm_probe(struct platform_device *pdev)
  53. {
  54. struct resource *res;
  55. void __iomem *regs;
  56. int irq;
  57. int ret;
  58. dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
  59. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  60. if (!res) {
  61. dev_err(&pdev->dev, "failed to get platform resource mem\n");
  62. return -ENXIO;
  63. }
  64. regs = ioremap(res->start, resource_size(res));
  65. if (!regs) {
  66. dev_err(&pdev->dev, "ioremap failed\n");
  67. return -ENOMEM;
  68. }
  69. ret = udc_probe(&ci13xxx_msm_udc_driver, &pdev->dev, regs);
  70. if (ret < 0) {
  71. dev_err(&pdev->dev, "udc_probe failed\n");
  72. goto iounmap;
  73. }
  74. irq = platform_get_irq(pdev, 0);
  75. if (irq < 0) {
  76. dev_err(&pdev->dev, "IRQ not found\n");
  77. ret = -ENXIO;
  78. goto udc_remove;
  79. }
  80. ret = request_irq(irq, msm_udc_irq, IRQF_SHARED, pdev->name, pdev);
  81. if (ret < 0) {
  82. dev_err(&pdev->dev, "request_irq failed\n");
  83. goto udc_remove;
  84. }
  85. pm_runtime_no_callbacks(&pdev->dev);
  86. pm_runtime_enable(&pdev->dev);
  87. return 0;
  88. udc_remove:
  89. udc_remove();
  90. iounmap:
  91. iounmap(regs);
  92. return ret;
  93. }
  94. static struct platform_driver ci13xxx_msm_driver = {
  95. .probe = ci13xxx_msm_probe,
  96. .driver = { .name = "msm_hsusb", },
  97. };
  98. MODULE_ALIAS("platform:msm_hsusb");
  99. static int __init ci13xxx_msm_init(void)
  100. {
  101. return platform_driver_register(&ci13xxx_msm_driver);
  102. }
  103. module_init(ci13xxx_msm_init);
  104. MODULE_LICENSE("GPL v2");