1 /***********************license start***************
2 * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * * Neither the name of Cavium Networks nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
23 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
24 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
25 * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
26 * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
27 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
28 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
29 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
30 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
31 * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
32 * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
35 * For any questions regarding licensing please contact marketing@caviumnetworks.com
37 ***********************license end**************************************/
47 * Functions for XAUI initialization, configuration,
50 * <hr>$Revision: 42417 $<hr>
53 #include "cvmx-helper.h"
55 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
58 * Probe a XAUI interface and determine the number of ports
59 * connected to it. The XAUI interface should still be down
62 * @param interface Interface to probe
64 * @return Number of ports on the interface. Zero to disable.
66 int __cvmx_helper_xaui_probe(int interface)
69 cvmx_gmxx_hg2_control_t gmx_hg2_control;
70 cvmx_gmxx_inf_mode_t mode;
72 /* Due to errata GMX-700 on CN56XXp1.x and CN52XXp1.x, the interface
73 needs to be enabled before IPD otherwise per port backpressure
74 may not work properly */
75 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
77 cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64);
79 __cvmx_helper_setup_gmx(interface, 1);
81 /* Setup PKO to support 16 ports for HiGig2 virtual ports. We're pointing
82 all of the PKO packet ports for this interface to the XAUI. This allows
83 us to use HiGig2 backpressure per port */
86 cvmx_pko_mem_port_ptrs_t pko_mem_port_ptrs;
87 pko_mem_port_ptrs.u64 = 0;
88 /* We set each PKO port to have equal priority in a round robin
90 pko_mem_port_ptrs.s.static_p = 0;
91 pko_mem_port_ptrs.s.qos_mask = 0xff;
92 /* All PKO ports map to the same XAUI hardware port */
93 pko_mem_port_ptrs.s.eid = interface*4;
94 pko_mem_port_ptrs.s.pid = interface*16 + i;
95 cvmx_write_csr(CVMX_PKO_MEM_PORT_PTRS, pko_mem_port_ptrs.u64);
98 /* If HiGig2 is enabled return 16 ports, otherwise return 1 port */
99 gmx_hg2_control.u64 = cvmx_read_csr(CVMX_GMXX_HG2_CONTROL(interface));
100 if (gmx_hg2_control.s.hg2tx_en)
109 * Bringup and enable a XAUI interface. After this call packet
110 * I/O should be fully functional. This is called with IPD
111 * enabled but PKO disabled.
113 * @param interface Interface to bring up
115 * @return Zero on success, negative on failure
117 int __cvmx_helper_xaui_enable(int interface)
119 cvmx_gmxx_prtx_cfg_t gmx_cfg;
120 cvmx_pcsxx_control1_reg_t xauiCtl;
121 cvmx_pcsxx_misc_ctl_reg_t xauiMiscCtl;
122 cvmx_gmxx_tx_xaui_ctl_t gmxXauiTxCtl;
123 cvmx_gmxx_rxx_int_en_t gmx_rx_int_en;
124 cvmx_gmxx_tx_int_en_t gmx_tx_int_en;
125 cvmx_pcsxx_int_en_reg_t pcsx_int_en_reg;
127 /* (1) Interface has already been enabled. */
129 /* (2) Disable GMX. */
130 xauiMiscCtl.u64 = cvmx_read_csr(CVMX_PCSXX_MISC_CTL_REG(interface));
131 xauiMiscCtl.s.gmxeno = 1;
132 cvmx_write_csr (CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64);
134 /* (3) Disable GMX and PCSX interrupts. */
135 gmx_rx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(0,interface));
136 cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0,interface), 0x0);
137 gmx_tx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_TX_INT_EN(interface));
138 cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0x0);
139 pcsx_int_en_reg.u64 = cvmx_read_csr(CVMX_PCSXX_INT_EN_REG(interface));
140 cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), 0x0);
142 /* (4) Bring up the PCSX and GMX reconciliation layer. */
143 /* (4)a Set polarity and lane swapping. */
145 gmxXauiTxCtl.u64 = cvmx_read_csr (CVMX_GMXX_TX_XAUI_CTL(interface));
146 gmxXauiTxCtl.s.dic_en = 1; /* Enable better IFG packing and improves performance */
147 gmxXauiTxCtl.s.uni_en = 0;
148 cvmx_write_csr (CVMX_GMXX_TX_XAUI_CTL(interface), gmxXauiTxCtl.u64);
150 /* (4)c Aply reset sequence */
151 xauiCtl.u64 = cvmx_read_csr (CVMX_PCSXX_CONTROL1_REG(interface));
152 xauiCtl.s.lo_pwr = 0;
154 cvmx_write_csr (CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64);
156 /* Wait for PCS to come out of reset */
157 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_CONTROL1_REG(interface), cvmx_pcsxx_control1_reg_t, reset, ==, 0, 10000))
159 /* Wait for PCS to be aligned */
160 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_10GBX_STATUS_REG(interface), cvmx_pcsxx_10gbx_status_reg_t, alignd, ==, 1, 10000))
162 /* Wait for RX to be ready */
163 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_RX_XAUI_CTL(interface), cvmx_gmxx_rx_xaui_ctl_t, status, ==, 0, 10000))
166 /* (6) Configure GMX */
167 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
169 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
171 /* Wait for GMX RX to be idle */
172 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(0, interface), cvmx_gmxx_prtx_cfg_t, rx_idle, ==, 1, 10000))
174 /* Wait for GMX TX to be idle */
175 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(0, interface), cvmx_gmxx_prtx_cfg_t, tx_idle, ==, 1, 10000))
179 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
181 gmx_cfg.s.speed_msb = 0;
182 gmx_cfg.s.slottime = 1;
183 cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), 1);
184 cvmx_write_csr(CVMX_GMXX_TXX_SLOT(0, interface), 512);
185 cvmx_write_csr(CVMX_GMXX_TXX_BURST(0, interface), 8192);
186 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
188 /* (7) Clear out any error state */
189 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(0,interface), cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(0,interface)));
190 cvmx_write_csr(CVMX_GMXX_TX_INT_REG(interface), cvmx_read_csr(CVMX_GMXX_TX_INT_REG(interface)));
191 cvmx_write_csr(CVMX_PCSXX_INT_REG(interface), cvmx_read_csr(CVMX_PCSXX_INT_REG(interface)));
193 /* Wait for receive link */
194 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS1_REG(interface), cvmx_pcsxx_status1_reg_t, rcv_lnk, ==, 1, 10000))
196 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, xmtflt, ==, 0, 10000))
198 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, rcvflt, ==, 0, 10000))
201 cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0,interface), gmx_rx_int_en.u64);
202 cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), gmx_tx_int_en.u64);
203 cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), pcsx_int_en_reg.u64);
205 cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port(interface, 0));
207 /* (8) Enable packet reception */
208 xauiMiscCtl.s.gmxeno = 0;
209 cvmx_write_csr (CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64);
211 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
213 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
219 * Return the link state of an IPD/PKO port as returned by
220 * auto negotiation. The result of this function may not match
221 * Octeon's link config if auto negotiation has changed since
222 * the last call to cvmx_helper_link_set().
224 * @param ipd_port IPD/PKO port to query
228 cvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port)
230 int interface = cvmx_helper_get_interface_num(ipd_port);
231 cvmx_gmxx_tx_xaui_ctl_t gmxx_tx_xaui_ctl;
232 cvmx_gmxx_rx_xaui_ctl_t gmxx_rx_xaui_ctl;
233 cvmx_pcsxx_status1_reg_t pcsxx_status1_reg;
234 cvmx_helper_link_info_t result;
236 gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface));
237 gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface));
238 pcsxx_status1_reg.u64 = cvmx_read_csr(CVMX_PCSXX_STATUS1_REG(interface));
241 /* Only return a link if both RX and TX are happy */
242 if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0) &&
243 (pcsxx_status1_reg.s.rcv_lnk == 1))
245 result.s.link_up = 1;
246 result.s.full_duplex = 1;
247 result.s.speed = 10000;
251 /* Disable GMX and PCSX interrupts. */
252 cvmx_write_csr (CVMX_GMXX_RXX_INT_EN(0,interface), 0x0);
253 cvmx_write_csr (CVMX_GMXX_TX_INT_EN(interface), 0x0);
254 cvmx_write_csr (CVMX_PCSXX_INT_EN_REG(interface), 0x0);
262 * Configure an IPD/PKO port for the specified link state. This
263 * function does not influence auto negotiation at the PHY level.
264 * The passed link state must always match the link state returned
265 * by cvmx_helper_link_get(). It is normally best to use
266 * cvmx_helper_link_autoconf() instead.
268 * @param ipd_port IPD/PKO port to configure
269 * @param link_info The new link state
271 * @return Zero on success, negative on failure
273 int __cvmx_helper_xaui_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
275 int interface = cvmx_helper_get_interface_num(ipd_port);
276 cvmx_gmxx_tx_xaui_ctl_t gmxx_tx_xaui_ctl;
277 cvmx_gmxx_rx_xaui_ctl_t gmxx_rx_xaui_ctl;
279 gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface));
280 gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface));
282 /* If the link shouldn't be up, then just return */
283 if (!link_info.s.link_up)
286 /* Do nothing if both RX and TX are happy */
287 if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0))
290 /* Bring the link up */
291 return __cvmx_helper_xaui_enable(interface);
297 * Configure a port for internal and/or external loopback. Internal loopback
298 * causes packets sent by the port to be received by Octeon. External loopback
299 * causes packets received from the wire to sent out again.
301 * @param ipd_port IPD/PKO port to loopback.
302 * @param enable_internal
303 * Non zero if you want internal loopback
304 * @param enable_external
305 * Non zero if you want external loopback
307 * @return Zero on success, negative on failure.
309 extern int __cvmx_helper_xaui_configure_loopback(int ipd_port, int enable_internal, int enable_external)
311 int interface = cvmx_helper_get_interface_num(ipd_port);
312 cvmx_pcsxx_control1_reg_t pcsxx_control1_reg;
313 cvmx_gmxx_xaui_ext_loopback_t gmxx_xaui_ext_loopback;
315 /* Set the internal loop */
316 pcsxx_control1_reg.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface));
317 pcsxx_control1_reg.s.loopbck1 = enable_internal;
318 cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), pcsxx_control1_reg.u64);
320 /* Set the external loop */
321 gmxx_xaui_ext_loopback.u64 = cvmx_read_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface));
322 gmxx_xaui_ext_loopback.s.en = enable_external;
323 cvmx_write_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface), gmxx_xaui_ext_loopback.u64);
325 /* Take the link through a reset */
326 return __cvmx_helper_xaui_enable(interface);
329 #endif /* CVMX_ENABLE_PKO_FUNCTIONS */