ehci-w90x900.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * linux/driver/usb/host/ehci-w90x900.c
  3. *
  4. * Copyright (c) 2008 Nuvoton technology corporation.
  5. *
  6. * Wan ZongShun <mcuos.com@gmail.com>
  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 as published by
  10. * the Free Software Foundation;version 2 of the License.
  11. *
  12. */
  13. #include <linux/dma-mapping.h>
  14. #include <linux/io.h>
  15. #include <linux/kernel.h>
  16. #include <linux/module.h>
  17. #include <linux/of.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/usb.h>
  20. #include <linux/usb/hcd.h>
  21. #include "ehci.h"
  22. /* enable phy0 and phy1 for w90p910 */
  23. #define ENPHY (0x01<<8)
  24. #define PHY0_CTR (0xA4)
  25. #define PHY1_CTR (0xA8)
  26. #define DRIVER_DESC "EHCI w90x900 driver"
  27. static const char hcd_name[] = "ehci-w90x900 ";
  28. static struct hc_driver __read_mostly ehci_w90x900_hc_driver;
  29. static int usb_w90x900_probe(const struct hc_driver *driver,
  30. struct platform_device *pdev)
  31. {
  32. struct usb_hcd *hcd;
  33. struct ehci_hcd *ehci;
  34. struct resource *res;
  35. int retval = 0, irq;
  36. unsigned long val;
  37. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  38. if (!res) {
  39. retval = -ENXIO;
  40. goto err1;
  41. }
  42. hcd = usb_create_hcd(driver, &pdev->dev, "w90x900 EHCI");
  43. if (!hcd) {
  44. retval = -ENOMEM;
  45. goto err1;
  46. }
  47. hcd->rsrc_start = res->start;
  48. hcd->rsrc_len = resource_size(res);
  49. if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
  50. retval = -EBUSY;
  51. goto err2;
  52. }
  53. hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
  54. if (hcd->regs == NULL) {
  55. retval = -EFAULT;
  56. goto err3;
  57. }
  58. ehci = hcd_to_ehci(hcd);
  59. ehci->caps = hcd->regs;
  60. ehci->regs = hcd->regs +
  61. HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
  62. /* enable PHY 0,1,the regs only apply to w90p910
  63. * 0xA4,0xA8 were offsets of PHY0 and PHY1 controller of
  64. * w90p910 IC relative to ehci->regs.
  65. */
  66. val = __raw_readl(ehci->regs+PHY0_CTR);
  67. val |= ENPHY;
  68. __raw_writel(val, ehci->regs+PHY0_CTR);
  69. val = __raw_readl(ehci->regs+PHY1_CTR);
  70. val |= ENPHY;
  71. __raw_writel(val, ehci->regs+PHY1_CTR);
  72. irq = platform_get_irq(pdev, 0);
  73. if (irq < 0)
  74. goto err4;
  75. retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
  76. if (retval != 0)
  77. goto err4;
  78. return retval;
  79. err4:
  80. iounmap(hcd->regs);
  81. err3:
  82. release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
  83. err2:
  84. usb_put_hcd(hcd);
  85. err1:
  86. return retval;
  87. }
  88. static void usb_w90x900_remove(struct usb_hcd *hcd,
  89. struct platform_device *pdev)
  90. {
  91. usb_remove_hcd(hcd);
  92. iounmap(hcd->regs);
  93. release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
  94. usb_put_hcd(hcd);
  95. }
  96. static int ehci_w90x900_probe(struct platform_device *pdev)
  97. {
  98. if (usb_disabled())
  99. return -ENODEV;
  100. return usb_w90x900_probe(&ehci_w90x900_hc_driver, pdev);
  101. }
  102. static int ehci_w90x900_remove(struct platform_device *pdev)
  103. {
  104. struct usb_hcd *hcd = platform_get_drvdata(pdev);
  105. usb_w90x900_remove(hcd, pdev);
  106. return 0;
  107. }
  108. static struct platform_driver ehci_hcd_w90x900_driver = {
  109. .probe = ehci_w90x900_probe,
  110. .remove = ehci_w90x900_remove,
  111. .driver = {
  112. .name = "w90x900-ehci",
  113. .owner = THIS_MODULE,
  114. },
  115. };
  116. static int __init ehci_w90X900_init(void)
  117. {
  118. if (usb_disabled())
  119. return -ENODEV;
  120. pr_info("%s: " DRIVER_DESC "\n", hcd_name);
  121. ehci_init_driver(&ehci_w90x900_hc_driver, NULL);
  122. return platform_driver_register(&ehci_hcd_w90x900_driver);
  123. }
  124. module_init(ehci_w90X900_init);
  125. static void __exit ehci_w90X900_cleanup(void)
  126. {
  127. platform_driver_unregister(&ehci_hcd_w90x900_driver);
  128. }
  129. module_exit(ehci_w90X900_cleanup);
  130. MODULE_DESCRIPTION(DRIVER_DESC);
  131. MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
  132. MODULE_ALIAS("platform:w90p910-ehci");
  133. MODULE_LICENSE("GPL v2");