xhci-uniphier.c 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <common.h>
  7. #include <linux/err.h>
  8. #include <linux/io.h>
  9. #include <usb.h>
  10. #include <fdtdec.h>
  11. #include "xhci.h"
  12. static int get_uniphier_xhci_base(int index, struct xhci_hccr **base)
  13. {
  14. DECLARE_GLOBAL_DATA_PTR;
  15. int node_list[2];
  16. fdt_addr_t addr;
  17. int count;
  18. count = fdtdec_find_aliases_for_id(gd->fdt_blob, "usb",
  19. COMPAT_SOCIONEXT_XHCI, node_list,
  20. ARRAY_SIZE(node_list));
  21. if (index >= count)
  22. return -ENODEV;
  23. addr = fdtdec_get_addr(gd->fdt_blob, node_list[index], "reg");
  24. if (addr == FDT_ADDR_T_NONE)
  25. return -ENODEV;
  26. *base = (struct xhci_hccr *)addr;
  27. return 0;
  28. }
  29. #define USB3_RST_CTRL 0x00100040
  30. #define IOMMU_RST_N (1 << 5)
  31. #define LINK_RST_N (1 << 4)
  32. static void uniphier_xhci_reset(void __iomem *base, int on)
  33. {
  34. u32 tmp;
  35. tmp = readl(base + USB3_RST_CTRL);
  36. if (on)
  37. tmp &= ~(IOMMU_RST_N | LINK_RST_N);
  38. else
  39. tmp |= IOMMU_RST_N | LINK_RST_N;
  40. writel(tmp, base + USB3_RST_CTRL);
  41. }
  42. int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
  43. {
  44. int ret;
  45. struct xhci_hccr *cr;
  46. struct xhci_hcor *or;
  47. ret = get_uniphier_xhci_base(index, &cr);
  48. if (ret < 0)
  49. return ret;
  50. uniphier_xhci_reset(cr, 0);
  51. or = (void *)cr + HC_LENGTH(xhci_readl(&cr->cr_capbase));
  52. *hccr = cr;
  53. *hcor = or;
  54. return 0;
  55. }
  56. void xhci_hcd_stop(int index)
  57. {
  58. int ret;
  59. struct xhci_hccr *cr;
  60. ret = get_uniphier_xhci_base(index, &cr);
  61. if (ret < 0)
  62. return;
  63. uniphier_xhci_reset(cr, 1);
  64. }