ehci-atmel.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * (C) Copyright 2012
  3. * Atmel Semiconductor <www.atmel.com>
  4. * Written-by: Bo Shen <voice.shen@atmel.com>
  5. *
  6. * SPDX-License-Identifier: GPL-2.0+
  7. */
  8. #include <common.h>
  9. #include <clk.h>
  10. #include <dm.h>
  11. #include <usb.h>
  12. #include <asm/io.h>
  13. #include <asm/arch/clk.h>
  14. #include "ehci.h"
  15. DECLARE_GLOBAL_DATA_PTR;
  16. #ifndef CONFIG_DM_USB
  17. int ehci_hcd_init(int index, enum usb_init_type init,
  18. struct ehci_hccr **hccr, struct ehci_hcor **hcor)
  19. {
  20. /* Enable UTMI PLL */
  21. if (at91_upll_clk_enable())
  22. return -1;
  23. /* Enable USB Host clock */
  24. at91_periph_clk_enable(ATMEL_ID_UHPHS);
  25. *hccr = (struct ehci_hccr *)ATMEL_BASE_EHCI;
  26. *hcor = (struct ehci_hcor *)((uint32_t)*hccr +
  27. HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
  28. return 0;
  29. }
  30. int ehci_hcd_stop(int index)
  31. {
  32. /* Disable USB Host Clock */
  33. at91_periph_clk_disable(ATMEL_ID_UHPHS);
  34. /* Disable UTMI PLL */
  35. if (at91_upll_clk_disable())
  36. return -1;
  37. return 0;
  38. }
  39. #else
  40. struct ehci_atmel_priv {
  41. struct ehci_ctrl ehci;
  42. };
  43. static int ehci_atmel_enable_clk(struct udevice *dev)
  44. {
  45. struct udevice *dev_clk;
  46. struct clk clk;
  47. int periph;
  48. int ret;
  49. ret = clk_get_by_index(dev, 0, &clk);
  50. if (ret)
  51. return ret;
  52. ret = clk_enable(&clk);
  53. if (ret)
  54. return ret;
  55. ret = clk_get_by_index(dev, 1, &clk);
  56. if (ret)
  57. return -EINVAL;
  58. periph = fdtdec_get_uint(gd->fdt_blob, clk.dev->of_offset, "reg", -1);
  59. if (periph < 0)
  60. return -EINVAL;
  61. dev_clk = dev_get_parent(clk.dev);
  62. if (!dev_clk)
  63. return -ENODEV;
  64. ret = clk_request(dev_clk, &clk);
  65. if (ret)
  66. return ret;
  67. clk.id = periph;
  68. ret = clk_enable(&clk);
  69. if (ret)
  70. return ret;
  71. clk_free(&clk);
  72. return 0;
  73. }
  74. static int ehci_atmel_probe(struct udevice *dev)
  75. {
  76. struct ehci_hccr *hccr;
  77. struct ehci_hcor *hcor;
  78. fdt_addr_t hcd_base;
  79. int ret;
  80. ret = ehci_atmel_enable_clk(dev);
  81. if (ret) {
  82. debug("Failed to enable USB Host clock\n");
  83. return ret;
  84. }
  85. /*
  86. * Get the base address for EHCI controller from the device node
  87. */
  88. hcd_base = dev_get_addr(dev);
  89. if (hcd_base == FDT_ADDR_T_NONE) {
  90. debug("Can't get the EHCI register base address\n");
  91. return -ENXIO;
  92. }
  93. hccr = (struct ehci_hccr *)hcd_base;
  94. hcor = (struct ehci_hcor *)
  95. ((u32)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
  96. debug("echi-atmel: init hccr %x and hcor %x hc_length %d\n",
  97. (u32)hccr, (u32)hcor,
  98. (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
  99. return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
  100. }
  101. static int ehci_atmel_remove(struct udevice *dev)
  102. {
  103. int ret;
  104. ret = ehci_deregister(dev);
  105. if (ret)
  106. return ret;
  107. return 0;
  108. }
  109. static const struct udevice_id ehci_usb_ids[] = {
  110. { .compatible = "atmel,at91sam9g45-ehci", },
  111. { }
  112. };
  113. U_BOOT_DRIVER(ehci_atmel) = {
  114. .name = "ehci_atmel",
  115. .id = UCLASS_USB,
  116. .of_match = ehci_usb_ids,
  117. .probe = ehci_atmel_probe,
  118. .remove = ehci_atmel_remove,
  119. .ops = &ehci_usb_ops,
  120. .platdata_auto_alloc_size = sizeof(struct usb_platdata),
  121. .priv_auto_alloc_size = sizeof(struct ehci_atmel_priv),
  122. .flags = DM_FLAG_ALLOC_PRIV_DMA,
  123. };
  124. #endif