ehci-atmel.c 2.5 KB

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