cvmx-helper-loop.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2018-2022 Marvell International Ltd.
  4. *
  5. * Functions for LOOP initialization, configuration,
  6. * and monitoring.
  7. */
  8. #include <log.h>
  9. #include <malloc.h>
  10. #include <net.h>
  11. #include <linux/delay.h>
  12. #include <mach/cvmx-regs.h>
  13. #include <mach/cvmx-csr.h>
  14. #include <mach/cvmx-bootmem.h>
  15. #include <mach/octeon-model.h>
  16. #include <mach/octeon_fdt.h>
  17. #include <mach/cvmx-helper.h>
  18. #include <mach/cvmx-helper-board.h>
  19. #include <mach/cvmx-helper-cfg.h>
  20. #include <mach/cvmx-helper-fdt.h>
  21. #include <mach/cvmx-helper-gpio.h>
  22. #include <mach/cvmx-agl-defs.h>
  23. #include <mach/cvmx-bgxx-defs.h>
  24. #include <mach/cvmx-ciu-defs.h>
  25. #include <mach/cvmx-gmxx-defs.h>
  26. #include <mach/cvmx-gserx-defs.h>
  27. #include <mach/cvmx-ilk-defs.h>
  28. #include <mach/cvmx-ipd-defs.h>
  29. #include <mach/cvmx-lbk-defs.h>
  30. #include <mach/cvmx-pcsx-defs.h>
  31. #include <mach/cvmx-pcsxx-defs.h>
  32. #include <mach/cvmx-pki-defs.h>
  33. #include <mach/cvmx-pko-defs.h>
  34. #include <mach/cvmx-xcv-defs.h>
  35. #include <mach/cvmx-hwpko.h>
  36. #include <mach/cvmx-ilk.h>
  37. #include <mach/cvmx-pki.h>
  38. int __cvmx_helper_loop_enumerate(int xiface)
  39. {
  40. return OCTEON_IS_MODEL(OCTEON_CN68XX) ?
  41. 8 : (OCTEON_IS_MODEL(OCTEON_CNF71XX) ? 2 : 4);
  42. }
  43. /**
  44. * @INTERNAL
  45. * Probe a LOOP interface and determine the number of ports
  46. * connected to it. The LOOP interface should still be down
  47. * after this call.
  48. *
  49. * @param xiface Interface to probe
  50. *
  51. * @return Number of ports on the interface. Zero to disable.
  52. */
  53. int __cvmx_helper_loop_probe(int xiface)
  54. {
  55. return __cvmx_helper_loop_enumerate(xiface);
  56. }
  57. /**
  58. * @INTERNAL
  59. * Bringup and enable a LOOP interface. After this call packet
  60. * I/O should be fully functional. This is called with IPD
  61. * enabled but PKO disabled.
  62. *
  63. * @param interface to bring up
  64. *
  65. * @return Zero on success, negative on failure
  66. */
  67. int __cvmx_helper_loop_enable(int xiface)
  68. {
  69. cvmx_pip_prt_cfgx_t port_cfg;
  70. int num_ports, index;
  71. unsigned long offset;
  72. struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
  73. num_ports = __cvmx_helper_get_num_ipd_ports(xiface);
  74. /*
  75. * We need to disable length checking so packet < 64 bytes and jumbo
  76. * frames don't get errors
  77. */
  78. for (index = 0; index < num_ports; index++) {
  79. offset = ((octeon_has_feature(OCTEON_FEATURE_PKND)) ?
  80. cvmx_helper_get_pknd(xiface, index) :
  81. cvmx_helper_get_ipd_port(xiface, index));
  82. if (octeon_has_feature(OCTEON_FEATURE_PKI)) {
  83. cvmx_pki_endis_l2_errs(xi.node, offset, 1, 0, 0);
  84. cvmx_pki_endis_fcs_check(xi.node, offset, 0, 0);
  85. } else {
  86. port_cfg.u64 = csr_rd(CVMX_PIP_PRT_CFGX(offset));
  87. port_cfg.s.maxerr_en = 0;
  88. port_cfg.s.minerr_en = 0;
  89. csr_wr(CVMX_PIP_PRT_CFGX(offset), port_cfg.u64);
  90. }
  91. }
  92. /*
  93. * Disable FCS stripping for loopback ports
  94. */
  95. if (!octeon_has_feature(OCTEON_FEATURE_PKND)) {
  96. cvmx_ipd_sub_port_fcs_t ipd_sub_port_fcs;
  97. ipd_sub_port_fcs.u64 = csr_rd(CVMX_IPD_SUB_PORT_FCS);
  98. ipd_sub_port_fcs.s.port_bit2 = 0;
  99. csr_wr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
  100. }
  101. /*
  102. * Set PKND and BPID for loopback ports.
  103. */
  104. if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
  105. cvmx_pko_reg_loopback_pkind_t lp_pknd;
  106. cvmx_pko_reg_loopback_bpid_t lp_bpid;
  107. for (index = 0; index < num_ports; index++) {
  108. int pknd = cvmx_helper_get_pknd(xiface, index);
  109. int bpid = cvmx_helper_get_bpid(xiface, index);
  110. lp_pknd.u64 = csr_rd(CVMX_PKO_REG_LOOPBACK_PKIND);
  111. lp_bpid.u64 = csr_rd(CVMX_PKO_REG_LOOPBACK_BPID);
  112. if (index == 0)
  113. lp_pknd.s.num_ports = num_ports;
  114. switch (index) {
  115. case 0:
  116. lp_pknd.s.pkind0 = pknd;
  117. lp_bpid.s.bpid0 = bpid;
  118. break;
  119. case 1:
  120. lp_pknd.s.pkind1 = pknd;
  121. lp_bpid.s.bpid1 = bpid;
  122. break;
  123. case 2:
  124. lp_pknd.s.pkind2 = pknd;
  125. lp_bpid.s.bpid2 = bpid;
  126. break;
  127. case 3:
  128. lp_pknd.s.pkind3 = pknd;
  129. lp_bpid.s.bpid3 = bpid;
  130. break;
  131. case 4:
  132. lp_pknd.s.pkind4 = pknd;
  133. lp_bpid.s.bpid4 = bpid;
  134. break;
  135. case 5:
  136. lp_pknd.s.pkind5 = pknd;
  137. lp_bpid.s.bpid5 = bpid;
  138. break;
  139. case 6:
  140. lp_pknd.s.pkind6 = pknd;
  141. lp_bpid.s.bpid6 = bpid;
  142. break;
  143. case 7:
  144. lp_pknd.s.pkind7 = pknd;
  145. lp_bpid.s.bpid7 = bpid;
  146. break;
  147. }
  148. csr_wr(CVMX_PKO_REG_LOOPBACK_PKIND, lp_pknd.u64);
  149. csr_wr(CVMX_PKO_REG_LOOPBACK_BPID, lp_bpid.u64);
  150. }
  151. } else if (octeon_has_feature(OCTEON_FEATURE_BGX)) {
  152. cvmx_lbk_chx_pkind_t lbk_pkind;
  153. for (index = 0; index < num_ports; index++) {
  154. lbk_pkind.u64 = 0;
  155. lbk_pkind.s.pkind = cvmx_helper_get_pknd(xiface, index);
  156. csr_wr_node(xi.node, CVMX_LBK_CHX_PKIND(index),
  157. lbk_pkind.u64);
  158. }
  159. }
  160. return 0;
  161. }