blob: 8eaeac387df4abe8888fe815d1c79802a44fd14e [file] [log] [blame]
Aaron Williams3bb60212022-04-07 09:11:17 +02001// 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}