ehci-sunxi.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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_power_off(priv->phy_index);
  60. sunxi_usb_phy_exit(priv->phy_index);
  61. #ifdef CONFIG_SUNXI_GEN_SUN6I
  62. clrbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask);
  63. #endif
  64. clrbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask);
  65. return 0;
  66. }
  67. static const struct udevice_id ehci_usb_ids[] = {
  68. { .compatible = "allwinner,sun4i-a10-ehci", },
  69. { .compatible = "allwinner,sun5i-a13-ehci", },
  70. { .compatible = "allwinner,sun6i-a31-ehci", },
  71. { .compatible = "allwinner,sun7i-a20-ehci", },
  72. { .compatible = "allwinner,sun8i-a23-ehci", },
  73. { .compatible = "allwinner,sun9i-a80-ehci", },
  74. { }
  75. };
  76. U_BOOT_DRIVER(usb_ehci) = {
  77. .name = "ehci_sunxi",
  78. .id = UCLASS_USB,
  79. .of_match = ehci_usb_ids,
  80. .probe = ehci_usb_probe,
  81. .remove = ehci_usb_remove,
  82. .ops = &ehci_usb_ops,
  83. .platdata_auto_alloc_size = sizeof(struct usb_platdata),
  84. .priv_auto_alloc_size = sizeof(struct ehci_sunxi_priv),
  85. .flags = DM_FLAG_ALLOC_PRIV_DMA,
  86. };