xcv.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2018 Marvell International Ltd.
  4. */
  5. #include <config.h>
  6. #include <dm.h>
  7. #include <errno.h>
  8. #include <fdt_support.h>
  9. #include <pci.h>
  10. #include <malloc.h>
  11. #include <miiphy.h>
  12. #include <misc.h>
  13. #include <net.h>
  14. #include <netdev.h>
  15. #include <asm/io.h>
  16. #include <linux/delay.h>
  17. #include <linux/libfdt.h>
  18. #include <asm/arch/csrs/csrs-xcv.h>
  19. #define XCVX_BASE 0x87E0DB000000ULL
  20. /* Initialize XCV block */
  21. void xcv_init_hw(void)
  22. {
  23. union xcvx_reset reset;
  24. union xcvx_dll_ctl xcv_dll_ctl;
  25. /* Take the DLL out of reset */
  26. reset.u = readq(XCVX_BASE + XCVX_RESET(0));
  27. reset.s.dllrst = 0;
  28. writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
  29. /* Take the clock tree out of reset */
  30. reset.u = readq(XCVX_BASE + XCVX_RESET(0));
  31. reset.s.clkrst = 0;
  32. writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
  33. /* Once the 125MHz ref clock is stable, wait 10us for DLL to lock */
  34. udelay(10);
  35. /* Optionally, bypass the DLL setting */
  36. xcv_dll_ctl.u = readq(XCVX_BASE + XCVX_DLL_CTL(0));
  37. xcv_dll_ctl.s.clkrx_set = 0;
  38. xcv_dll_ctl.s.clkrx_byp = 1;
  39. xcv_dll_ctl.s.clktx_byp = 0;
  40. writeq(xcv_dll_ctl.u, XCVX_BASE + XCVX_DLL_CTL(0));
  41. /* Enable the compensation controller */
  42. reset.u = readq(XCVX_BASE + XCVX_RESET(0));
  43. reset.s.comp = 1;
  44. writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
  45. reset.u = readq(XCVX_BASE + XCVX_RESET(0));
  46. /* Wait for 1040 reference clock cycles for the compensation state
  47. * machine lock.
  48. */
  49. udelay(100);
  50. /* Enable the XCV block */
  51. reset.u = readq(XCVX_BASE + XCVX_RESET(0));
  52. reset.s.enable = 1;
  53. writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
  54. /* set XCV(0)_RESET[CLKRST] to 1 */
  55. reset.u = readq(XCVX_BASE + XCVX_RESET(0));
  56. reset.s.clkrst = 1;
  57. writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
  58. }
  59. /*
  60. * Configure XCV link based on the speed
  61. * link_up : Set to 1 when link is up otherwise 0
  62. * link_speed: The speed of the link.
  63. */
  64. void xcv_setup_link(bool link_up, int link_speed)
  65. {
  66. union xcvx_ctl xcv_ctl;
  67. union xcvx_reset reset;
  68. union xcvx_batch_crd_ret xcv_crd_ret;
  69. int speed = 2;
  70. /* Check RGMII link */
  71. if (link_speed == 100)
  72. speed = 1;
  73. else if (link_speed == 10)
  74. speed = 0;
  75. if (link_up) {
  76. /* Set operating speed */
  77. xcv_ctl.u = readq(XCVX_BASE + XCVX_CTL(0));
  78. xcv_ctl.s.speed = speed;
  79. writeq(xcv_ctl.u, XCVX_BASE + XCVX_CTL(0));
  80. /* Datapaths come out of reset
  81. * - The datapath resets will disengage BGX from the
  82. * RGMII interface
  83. * - XCV will continue to return TX credits for each tick
  84. * that is sent on the TX data path
  85. */
  86. reset.u = readq(XCVX_BASE + XCVX_RESET(0));
  87. reset.s.tx_dat_rst_n = 1;
  88. reset.s.rx_dat_rst_n = 1;
  89. writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
  90. /* Enable packet flow */
  91. reset.u = readq(XCVX_BASE + XCVX_RESET(0));
  92. reset.s.tx_pkt_rst_n = 1;
  93. reset.s.rx_pkt_rst_n = 1;
  94. writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
  95. xcv_crd_ret.u = readq(XCVX_BASE + XCVX_BATCH_CRD_RET(0));
  96. xcv_crd_ret.s.crd_ret = 1;
  97. writeq(xcv_crd_ret.u, XCVX_BASE + XCVX_BATCH_CRD_RET(0));
  98. } else {
  99. /* Enable packet flow */
  100. reset.u = readq(XCVX_BASE + XCVX_RESET(0));
  101. reset.s.tx_pkt_rst_n = 0;
  102. reset.s.rx_pkt_rst_n = 0;
  103. writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
  104. reset.u = readq(XCVX_BASE + XCVX_RESET(0));
  105. }
  106. }