ehci-w90x900.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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. hcd->regs = devm_ioremap_resource(&pdev->dev, res);
  50. if (IS_ERR(hcd->regs)) {
  51. retval = PTR_ERR(hcd->regs);
  52. goto err2;
  53. }
  54. ehci = hcd_to_ehci(hcd);
  55. ehci->caps = hcd->regs;
  56. ehci->regs = hcd->regs +
  57. HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
  58. /* enable PHY 0,1,the regs only apply to w90p910
  59. * 0xA4,0xA8 were offsets of PHY0 and PHY1 controller of
  60. * w90p910 IC relative to ehci->regs.
  61. */
  62. val = __raw_readl(ehci->regs+PHY0_CTR);
  63. val |= ENPHY;
  64. __raw_writel(val, ehci->regs+PHY0_CTR);
  65. val = __raw_readl(ehci->regs+PHY1_CTR);
  66. val |= ENPHY;
  67. __raw_writel(val, ehci->regs+PHY1_CTR);
  68. irq = platform_get_irq(pdev, 0);
  69. if (irq < 0)
  70. goto err2;
  71. retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
  72. if (retval != 0)
  73. goto err2;
  74. device_wakeup_enable(hcd->self.controller);
  75. return retval;
  76. err2:
  77. usb_put_hcd(hcd);
  78. err1:
  79. return retval;
  80. }
  81. static void usb_w90x900_remove(struct usb_hcd *hcd,
  82. struct platform_device *pdev)
  83. {
  84. usb_remove_hcd(hcd);
  85. usb_put_hcd(hcd);
  86. }
  87. static int ehci_w90x900_probe(struct platform_device *pdev)
  88. {
  89. if (usb_disabled())
  90. return -ENODEV;
  91. return usb_w90x900_probe(&ehci_w90x900_hc_driver, pdev);
  92. }
  93. static int ehci_w90x900_remove(struct platform_device *pdev)
  94. {
  95. struct usb_hcd *hcd = platform_get_drvdata(pdev);
  96. usb_w90x900_remove(hcd, pdev);
  97. return 0;
  98. }
  99. static struct platform_driver ehci_hcd_w90x900_driver = {
  100. .probe = ehci_w90x900_probe,
  101. .remove = ehci_w90x900_remove,
  102. .driver = {
  103. .name = "w90x900-ehci",
  104. .owner = THIS_MODULE,
  105. },
  106. };
  107. static int __init ehci_w90X900_init(void)
  108. {
  109. if (usb_disabled())
  110. return -ENODEV;
  111. pr_info("%s: " DRIVER_DESC "\n", hcd_name);
  112. ehci_init_driver(&ehci_w90x900_hc_driver, NULL);
  113. return platform_driver_register(&ehci_hcd_w90x900_driver);
  114. }
  115. module_init(ehci_w90X900_init);
  116. static void __exit ehci_w90X900_cleanup(void)
  117. {
  118. platform_driver_unregister(&ehci_hcd_w90x900_driver);
  119. }
  120. module_exit(ehci_w90X900_cleanup);
  121. MODULE_DESCRIPTION(DRIVER_DESC);
  122. MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
  123. MODULE_ALIAS("platform:w90p910-ehci");
  124. MODULE_LICENSE("GPL v2");