ehci-atmel.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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 clk clk;
  46. int ret;
  47. ret = clk_get_by_index(dev, 0, &clk);
  48. if (ret)
  49. return ret;
  50. ret = clk_enable(&clk);
  51. if (ret)
  52. return ret;
  53. ret = clk_get_by_index(dev, 1, &clk);
  54. if (ret)
  55. return -EINVAL;
  56. ret = clk_enable(&clk);
  57. if (ret)
  58. return ret;
  59. clk_free(&clk);
  60. return 0;
  61. }
  62. static int ehci_atmel_probe(struct udevice *dev)
  63. {
  64. struct ehci_hccr *hccr;
  65. struct ehci_hcor *hcor;
  66. fdt_addr_t hcd_base;
  67. int ret;
  68. ret = ehci_atmel_enable_clk(dev);
  69. if (ret) {
  70. debug("Failed to enable USB Host clock\n");
  71. return ret;
  72. }
  73. /*
  74. * Get the base address for EHCI controller from the device node
  75. */
  76. hcd_base = dev_get_addr(dev);
  77. if (hcd_base == FDT_ADDR_T_NONE) {
  78. debug("Can't get the EHCI register base address\n");
  79. return -ENXIO;
  80. }
  81. hccr = (struct ehci_hccr *)hcd_base;
  82. hcor = (struct ehci_hcor *)
  83. ((u32)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
  84. debug("echi-atmel: init hccr %x and hcor %x hc_length %d\n",
  85. (u32)hccr, (u32)hcor,
  86. (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
  87. return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
  88. }
  89. static const struct udevice_id ehci_usb_ids[] = {
  90. { .compatible = "atmel,at91sam9g45-ehci", },
  91. { }
  92. };
  93. U_BOOT_DRIVER(ehci_atmel) = {
  94. .name = "ehci_atmel",
  95. .id = UCLASS_USB,
  96. .of_match = ehci_usb_ids,
  97. .probe = ehci_atmel_probe,
  98. .remove = ehci_deregister,
  99. .ops = &ehci_usb_ops,
  100. .platdata_auto_alloc_size = sizeof(struct usb_platdata),
  101. .priv_auto_alloc_size = sizeof(struct ehci_atmel_priv),
  102. .flags = DM_FLAG_ALLOC_PRIV_DMA,
  103. };
  104. #endif