ehci-sunxi.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. * Sunxi ehci glue
  3. *
  4. * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
  5. * Copyright (C) 2014 Roman Byshko <rbyshko@gmail.com>
  6. *
  7. * Based on code from
  8. * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
  9. *
  10. * SPDX-License-Identifier: GPL-2.0+
  11. */
  12. #include <common.h>
  13. #include <asm/arch/clock.h>
  14. #include <asm/arch/usb_phy.h>
  15. #include <asm/io.h>
  16. #include <dm.h>
  17. #include "ehci.h"
  18. struct ehci_sunxi_priv {
  19. struct ehci_ctrl ehci;
  20. int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */
  21. int phy_index; /* Index of the usb-phy attached to this hcd */
  22. };
  23. static int ehci_usb_probe(struct udevice *dev)
  24. {
  25. struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
  26. struct usb_platdata *plat = dev_get_platdata(dev);
  27. struct ehci_sunxi_priv *priv = dev_get_priv(dev);
  28. struct ehci_hccr *hccr = (struct ehci_hccr *)dev_get_addr(dev);
  29. struct ehci_hcor *hcor;
  30. /*
  31. * This should go away once we've moved to the driver model for
  32. * clocks resp. phys.
  33. */
  34. if (hccr == (void *)SUNXI_USB1_BASE) {
  35. priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0;
  36. priv->phy_index = 1;
  37. } else {
  38. priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI1;
  39. priv->phy_index = 2;
  40. }
  41. setbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask);
  42. #ifdef CONFIG_SUNXI_GEN_SUN6I
  43. setbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask);
  44. #endif
  45. sunxi_usb_phy_init(priv->phy_index);
  46. sunxi_usb_phy_power_on(priv->phy_index);
  47. hcor = (struct ehci_hcor *)((uint32_t)hccr +
  48. HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
  49. return ehci_register(dev, hccr, hcor, NULL, 0, plat->init_type);
  50. }
  51. static int ehci_usb_remove(struct udevice *dev)
  52. {
  53. struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
  54. struct ehci_sunxi_priv *priv = dev_get_priv(dev);
  55. int ret;
  56. ret = ehci_deregister(dev);
  57. if (ret)
  58. return ret;
  59. sunxi_usb_phy_exit(priv->phy_index);
  60. #ifdef CONFIG_SUNXI_GEN_SUN6I
  61. clrbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask);
  62. #endif
  63. clrbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask);
  64. return 0;
  65. }
  66. static const struct udevice_id ehci_usb_ids[] = {
  67. { .compatible = "allwinner,sun4i-a10-ehci", },
  68. { .compatible = "allwinner,sun5i-a13-ehci", },
  69. { .compatible = "allwinner,sun6i-a31-ehci", },
  70. { .compatible = "allwinner,sun7i-a20-ehci", },
  71. { .compatible = "allwinner,sun8i-a23-ehci", },
  72. { .compatible = "allwinner,sun9i-a80-ehci", },
  73. { }
  74. };
  75. U_BOOT_DRIVER(ehci_sunxi) = {
  76. .name = "ehci_sunxi",
  77. .id = UCLASS_USB,
  78. .of_match = ehci_usb_ids,
  79. .probe = ehci_usb_probe,
  80. .remove = ehci_usb_remove,
  81. .ops = &ehci_usb_ops,
  82. .platdata_auto_alloc_size = sizeof(struct usb_platdata),
  83. .priv_auto_alloc_size = sizeof(struct ehci_sunxi_priv),
  84. .flags = DM_FLAG_ALLOC_PRIV_DMA,
  85. };