fsl_lsch3_serdes.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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 = 0;
  45. int i;
  46. switch (sd) {
  47. #ifdef CONFIG_SYS_FSL_SRDS_1
  48. case FSL_SRDS_1:
  49. cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]);
  50. cfg &= FSL_CHASSIS3_SRDS1_PRTCL_MASK;
  51. cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT;
  52. break;
  53. #endif
  54. #ifdef CONFIG_SYS_FSL_SRDS_2
  55. case FSL_SRDS_2:
  56. cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS2_REGSR - 1]);
  57. cfg &= FSL_CHASSIS3_SRDS2_PRTCL_MASK;
  58. cfg >>= FSL_CHASSIS3_SRDS2_PRTCL_SHIFT;
  59. break;
  60. #endif
  61. default:
  62. printf("invalid SerDes%d\n", sd);
  63. break;
  64. }
  65. /* Is serdes enabled at all? */
  66. if (cfg == 0)
  67. return -ENODEV;
  68. for (i = 0; i < SRDS_MAX_LANES; i++) {
  69. if (serdes_get_prtcl(sd, cfg, i) == device)
  70. return i;
  71. }
  72. return -ENODEV;
  73. }
  74. void serdes_init(u32 sd, u32 sd_addr, u32 rcwsr, u32 sd_prctl_mask,
  75. u32 sd_prctl_shift, u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
  76. {
  77. struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
  78. u32 cfg;
  79. int lane;
  80. if (serdes_prtcl_map[NONE])
  81. return;
  82. memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
  83. cfg = gur_in32(&gur->rcwsr[rcwsr - 1]) & sd_prctl_mask;
  84. cfg >>= sd_prctl_shift;
  85. printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
  86. if (!is_serdes_prtcl_valid(sd, cfg))
  87. printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
  88. for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
  89. enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
  90. if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
  91. debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
  92. else {
  93. serdes_prtcl_map[lane_prtcl] = 1;
  94. #ifdef CONFIG_FSL_MC_ENET
  95. switch (lane_prtcl) {
  96. case QSGMII_A:
  97. case QSGMII_B:
  98. case QSGMII_C:
  99. case QSGMII_D:
  100. wriop_init_dpmac_qsgmii(sd, (int)lane_prtcl);
  101. break;
  102. default:
  103. if (lane_prtcl >= XFI1 && lane_prtcl <= XFI8)
  104. wriop_init_dpmac(sd,
  105. xfi_dpmac[lane_prtcl],
  106. (int)lane_prtcl);
  107. if (lane_prtcl >= SGMII1 &&
  108. lane_prtcl <= SGMII16)
  109. wriop_init_dpmac(sd, sgmii_dpmac[
  110. lane_prtcl],
  111. (int)lane_prtcl);
  112. break;
  113. }
  114. #endif
  115. }
  116. }
  117. /* Set the first element to indicate serdes has been initialized */
  118. serdes_prtcl_map[NONE] = 1;
  119. }
  120. void fsl_serdes_init(void)
  121. {
  122. #ifdef CONFIG_FSL_MC_ENET
  123. int i , j;
  124. for (i = XFI1, j = 1; i <= XFI8; i++, j++)
  125. xfi_dpmac[i] = j;
  126. for (i = SGMII1, j = 1; i <= SGMII16; i++, j++)
  127. sgmii_dpmac[i] = j;
  128. #endif
  129. #ifdef CONFIG_SYS_FSL_SRDS_1
  130. serdes_init(FSL_SRDS_1,
  131. CONFIG_SYS_FSL_LSCH3_SERDES_ADDR,
  132. FSL_CHASSIS3_SRDS1_REGSR,
  133. FSL_CHASSIS3_SRDS1_PRTCL_MASK,
  134. FSL_CHASSIS3_SRDS1_PRTCL_SHIFT,
  135. serdes1_prtcl_map);
  136. #endif
  137. #ifdef CONFIG_SYS_FSL_SRDS_2
  138. serdes_init(FSL_SRDS_2,
  139. CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + FSL_SRDS_2 * 0x10000,
  140. FSL_CHASSIS3_SRDS2_REGSR,
  141. FSL_CHASSIS3_SRDS2_PRTCL_MASK,
  142. FSL_CHASSIS3_SRDS2_PRTCL_SHIFT,
  143. serdes2_prtcl_map);
  144. #endif
  145. }