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