ehci-w90x900.c 3.3 KB

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