fsl_lsch3_serdes.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * Copyright 2014-2015 Freescale Semiconductor, Inc.
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <common.h>
  7. #include <asm/io.h>
  8. #include <linux/errno.h>
  9. #include <asm/arch/fsl_serdes.h>
  10. #include <asm/arch/soc.h>
  11. #include <fsl-mc/ldpaa_wriop.h>
  12. #ifdef CONFIG_SYS_FSL_SRDS_1
  13. static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
  14. #endif
  15. #ifdef CONFIG_SYS_FSL_SRDS_2
  16. static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
  17. #endif
  18. #ifdef CONFIG_FSL_MC_ENET
  19. int xfi_dpmac[XFI8 + 1];
  20. int sgmii_dpmac[SGMII16 + 1];
  21. #endif
  22. __weak void wriop_init_dpmac_qsgmii(int sd, int lane_prtcl)
  23. {
  24. return;
  25. }
  26. int is_serdes_configured(enum srds_prtcl device)
  27. {
  28. int ret = 0;
  29. #ifdef CONFIG_SYS_FSL_SRDS_1
  30. if (!serdes1_prtcl_map[NONE])
  31. fsl_serdes_init();
  32. ret |= serdes1_prtcl_map[device];
  33. #endif
  34. #ifdef CONFIG_SYS_FSL_SRDS_2
  35. if (!serdes2_prtcl_map[NONE])
  36. fsl_serdes_init();
  37. ret |= serdes2_prtcl_map[device];
  38. #endif
  39. return !!ret;
  40. }
  41. int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
  42. {
  43. struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
  44. u32 cfg = gur_in32(&gur->rcwsr[28]);
  45. int i;
  46. switch (sd) {
  47. #ifdef CONFIG_SYS_FSL_SRDS_1
  48. case FSL_SRDS_1:
  49. cfg &= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK;
  50. cfg >>= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
  51. break;
  52. #endif
  53. #ifdef CONFIG_SYS_FSL_SRDS_2
  54. case FSL_SRDS_2:
  55. cfg &= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK;
  56. cfg >>= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT;
  57. break;
  58. #endif
  59. default:
  60. printf("invalid SerDes%d\n", sd);
  61. break;
  62. }
  63. /* Is serdes enabled at all? */
  64. if (cfg == 0)
  65. return -ENODEV;
  66. for (i = 0; i < SRDS_MAX_LANES; i++) {
  67. if (serdes_get_prtcl(sd, cfg, i) == device)
  68. return i;
  69. }
  70. return -ENODEV;
  71. }
  72. void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
  73. u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
  74. {
  75. struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
  76. u32 cfg;
  77. int lane;
  78. if (serdes_prtcl_map[NONE])
  79. return;
  80. memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
  81. cfg = gur_in32(&gur->rcwsr[28]) & sd_prctl_mask;
  82. cfg >>= sd_prctl_shift;
  83. printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
  84. if (!is_serdes_prtcl_valid(sd, cfg))
  85. printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
  86. for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
  87. enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
  88. if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
  89. debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
  90. else {
  91. serdes_prtcl_map[lane_prtcl] = 1;
  92. #ifdef CONFIG_FSL_MC_ENET
  93. switch (lane_prtcl) {
  94. case QSGMII_A:
  95. case QSGMII_B:
  96. case QSGMII_C:
  97. case QSGMII_D:
  98. wriop_init_dpmac_qsgmii(sd, (int)lane_prtcl);
  99. break;
  100. default:
  101. if (lane_prtcl >= XFI1 && lane_prtcl <= XFI8)
  102. wriop_init_dpmac(sd,
  103. xfi_dpmac[lane_prtcl],
  104. (int)lane_prtcl);
  105. if (lane_prtcl >= SGMII1 &&
  106. lane_prtcl <= SGMII16)
  107. wriop_init_dpmac(sd, sgmii_dpmac[
  108. lane_prtcl],
  109. (int)lane_prtcl);
  110. break;
  111. }
  112. #endif
  113. }
  114. }
  115. /* Set the first element to indicate serdes has been initialized */
  116. serdes_prtcl_map[NONE] = 1;
  117. }
  118. void fsl_serdes_init(void)
  119. {
  120. #ifdef CONFIG_FSL_MC_ENET
  121. int i , j;
  122. for (i = XFI1, j = 1; i <= XFI8; i++, j++)
  123. xfi_dpmac[i] = j;
  124. for (i = SGMII1, j = 1; i <= SGMII16; i++, j++)
  125. sgmii_dpmac[i] = j;
  126. #endif
  127. #ifdef CONFIG_SYS_FSL_SRDS_1
  128. serdes_init(FSL_SRDS_1,
  129. CONFIG_SYS_FSL_LSCH3_SERDES_ADDR,
  130. FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK,
  131. FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT,
  132. serdes1_prtcl_map);
  133. #endif
  134. #ifdef CONFIG_SYS_FSL_SRDS_2
  135. serdes_init(FSL_SRDS_2,
  136. CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + FSL_SRDS_2 * 0x10000,
  137. FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK,
  138. FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT,
  139. serdes2_prtcl_map);
  140. #endif
  141. }