1 /***********************license start***************
2 * Copyright (c) 2003-2010 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 * This Software, including technical data, may be subject to U.S. export control
24 * laws, including the U.S. Export Administration Act and its associated
25 * regulations, and may be subject to export or import regulations in other
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
49 * Functions for XAUI initialization, configuration,
52 * <hr>$Revision: 52004 $<hr>
54 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
55 #include <asm/octeon/cvmx.h>
56 #include <asm/octeon/cvmx-config.h>
57 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
58 #include <asm/octeon/cvmx-helper.h>
60 #include <asm/octeon/cvmx-gmxx-defs.h>
61 #include <asm/octeon/cvmx-pko-defs.h>
62 #include <asm/octeon/cvmx-pcsxx-defs.h>
63 #include <asm/octeon/cvmx-ciu-defs.h>
65 #if !defined(__FreeBSD__) || !defined(_KERNEL)
66 #include "executive-config.h"
67 #include "cvmx-config.h"
69 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
72 #include "cvmx-helper.h"
76 #include "cvmx-helper.h"
80 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
85 * Probe a XAUI interface and determine the number of ports
86 * connected to it. The XAUI interface should still be down
89 * @param interface Interface to probe
91 * @return Number of ports on the interface. Zero to disable.
93 int __cvmx_helper_xaui_probe(int interface)
96 cvmx_gmxx_hg2_control_t gmx_hg2_control;
97 cvmx_gmxx_inf_mode_t mode;
99 /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be programmed */
100 if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0))
102 cvmx_ciu_qlm2_t ciu_qlm;
103 ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM2);
104 ciu_qlm.s.txbypass = 1;
105 ciu_qlm.s.txdeemph = 0x5;
106 ciu_qlm.s.txmargin = 0x1a;
107 cvmx_write_csr(CVMX_CIU_QLM2, ciu_qlm.u64);
110 /* Due to errata GMX-700 on CN56XXp1.x and CN52XXp1.x, the interface
111 needs to be enabled before IPD otherwise per port backpressure
112 may not work properly */
113 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
115 cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64);
117 __cvmx_helper_setup_gmx(interface, 1);
119 /* Setup PKO to support 16 ports for HiGig2 virtual ports. We're pointing
120 all of the PKO packet ports for this interface to the XAUI. This allows
121 us to use HiGig2 backpressure per port */
124 cvmx_pko_mem_port_ptrs_t pko_mem_port_ptrs;
125 pko_mem_port_ptrs.u64 = 0;
126 /* We set each PKO port to have equal priority in a round robin
128 pko_mem_port_ptrs.s.static_p = 0;
129 pko_mem_port_ptrs.s.qos_mask = 0xff;
130 /* All PKO ports map to the same XAUI hardware port */
131 pko_mem_port_ptrs.s.eid = interface*4;
132 pko_mem_port_ptrs.s.pid = interface*16 + i;
133 cvmx_write_csr(CVMX_PKO_MEM_PORT_PTRS, pko_mem_port_ptrs.u64);
136 /* If HiGig2 is enabled return 16 ports, otherwise return 1 port */
137 gmx_hg2_control.u64 = cvmx_read_csr(CVMX_GMXX_HG2_CONTROL(interface));
138 if (gmx_hg2_control.s.hg2tx_en)
147 * Bringup and enable a XAUI interface. After this call packet
148 * I/O should be fully functional. This is called with IPD
149 * enabled but PKO disabled.
151 * @param interface Interface to bring up
153 * @return Zero on success, negative on failure
155 int __cvmx_helper_xaui_enable(int interface)
157 cvmx_gmxx_prtx_cfg_t gmx_cfg;
158 cvmx_pcsxx_control1_reg_t xauiCtl;
159 cvmx_pcsxx_misc_ctl_reg_t xauiMiscCtl;
160 cvmx_gmxx_tx_xaui_ctl_t gmxXauiTxCtl;
161 cvmx_helper_link_info_t link_info;
163 /* (1) Interface has already been enabled. */
165 /* (2) Disable GMX. */
166 xauiMiscCtl.u64 = cvmx_read_csr(CVMX_PCSXX_MISC_CTL_REG(interface));
167 xauiMiscCtl.s.gmxeno = 1;
168 cvmx_write_csr (CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64);
170 /* (3) Disable GMX and PCSX interrupts. */
171 cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0,interface), 0x0);
172 cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0x0);
173 cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), 0x0);
175 /* (4) Bring up the PCSX and GMX reconciliation layer. */
176 /* (4)a Set polarity and lane swapping. */
178 gmxXauiTxCtl.u64 = cvmx_read_csr (CVMX_GMXX_TX_XAUI_CTL(interface));
179 gmxXauiTxCtl.s.dic_en = 1; /* Enable better IFG packing and improves performance */
180 gmxXauiTxCtl.s.uni_en = 0;
181 cvmx_write_csr (CVMX_GMXX_TX_XAUI_CTL(interface), gmxXauiTxCtl.u64);
183 /* (4)c Aply reset sequence */
184 xauiCtl.u64 = cvmx_read_csr (CVMX_PCSXX_CONTROL1_REG(interface));
185 xauiCtl.s.lo_pwr = 0;
187 cvmx_write_csr (CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64);
189 /* Wait for PCS to come out of reset */
190 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_CONTROL1_REG(interface), cvmx_pcsxx_control1_reg_t, reset, ==, 0, 10000))
192 /* Wait for PCS to be aligned */
193 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_10GBX_STATUS_REG(interface), cvmx_pcsxx_10gbx_status_reg_t, alignd, ==, 1, 10000))
195 /* Wait for RX to be ready */
196 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_RX_XAUI_CTL(interface), cvmx_gmxx_rx_xaui_ctl_t, status, ==, 0, 10000))
199 /* (6) Configure GMX */
200 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
202 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
204 /* Wait for GMX RX to be idle */
205 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(0, interface), cvmx_gmxx_prtx_cfg_t, rx_idle, ==, 1, 10000))
207 /* Wait for GMX TX to be idle */
208 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(0, interface), cvmx_gmxx_prtx_cfg_t, tx_idle, ==, 1, 10000))
212 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
214 gmx_cfg.s.speed_msb = 0;
215 gmx_cfg.s.slottime = 1;
216 cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), 1);
217 cvmx_write_csr(CVMX_GMXX_TXX_SLOT(0, interface), 512);
218 cvmx_write_csr(CVMX_GMXX_TXX_BURST(0, interface), 8192);
219 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
221 /* Wait for receive link */
222 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS1_REG(interface), cvmx_pcsxx_status1_reg_t, rcv_lnk, ==, 1, 10000))
224 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, xmtflt, ==, 0, 10000))
226 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, rcvflt, ==, 0, 10000))
229 /* (8) Enable packet reception */
230 xauiMiscCtl.s.gmxeno = 0;
231 cvmx_write_csr (CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64);
233 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
235 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
237 link_info = cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port(interface, 0));
238 if (!link_info.s.link_up)
246 * Return the link state of an IPD/PKO port as returned by
247 * auto negotiation. The result of this function may not match
248 * Octeon's link config if auto negotiation has changed since
249 * the last call to cvmx_helper_link_set().
251 * @param ipd_port IPD/PKO port to query
255 cvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port)
257 int interface = cvmx_helper_get_interface_num(ipd_port);
258 cvmx_gmxx_tx_xaui_ctl_t gmxx_tx_xaui_ctl;
259 cvmx_gmxx_rx_xaui_ctl_t gmxx_rx_xaui_ctl;
260 cvmx_pcsxx_status1_reg_t pcsxx_status1_reg;
261 cvmx_helper_link_info_t result;
263 gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface));
264 gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface));
265 pcsxx_status1_reg.u64 = cvmx_read_csr(CVMX_PCSXX_STATUS1_REG(interface));
268 /* Only return a link if both RX and TX are happy */
269 if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0) &&
270 (pcsxx_status1_reg.s.rcv_lnk == 1))
272 result.s.link_up = 1;
273 result.s.full_duplex = 1;
274 result.s.speed = 10000;
278 /* Disable GMX and PCSX interrupts. */
279 cvmx_write_csr (CVMX_GMXX_RXX_INT_EN(0,interface), 0x0);
280 cvmx_write_csr (CVMX_GMXX_TX_INT_EN(interface), 0x0);
281 cvmx_write_csr (CVMX_PCSXX_INT_EN_REG(interface), 0x0);
289 * Configure an IPD/PKO port for the specified link state. This
290 * function does not influence auto negotiation at the PHY level.
291 * The passed link state must always match the link state returned
292 * by cvmx_helper_link_get(). It is normally best to use
293 * cvmx_helper_link_autoconf() instead.
295 * @param ipd_port IPD/PKO port to configure
296 * @param link_info The new link state
298 * @return Zero on success, negative on failure
300 int __cvmx_helper_xaui_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
302 int interface = cvmx_helper_get_interface_num(ipd_port);
303 cvmx_gmxx_tx_xaui_ctl_t gmxx_tx_xaui_ctl;
304 cvmx_gmxx_rx_xaui_ctl_t gmxx_rx_xaui_ctl;
306 gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface));
307 gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface));
309 /* If the link shouldn't be up, then just return */
310 if (!link_info.s.link_up)
313 /* Do nothing if both RX and TX are happy */
314 if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0))
317 /* Bring the link up */
318 return __cvmx_helper_xaui_enable(interface);
324 * Configure a port for internal and/or external loopback. Internal loopback
325 * causes packets sent by the port to be received by Octeon. External loopback
326 * causes packets received from the wire to sent out again.
328 * @param ipd_port IPD/PKO port to loopback.
329 * @param enable_internal
330 * Non zero if you want internal loopback
331 * @param enable_external
332 * Non zero if you want external loopback
334 * @return Zero on success, negative on failure.
336 extern int __cvmx_helper_xaui_configure_loopback(int ipd_port, int enable_internal, int enable_external)
338 int interface = cvmx_helper_get_interface_num(ipd_port);
339 cvmx_pcsxx_control1_reg_t pcsxx_control1_reg;
340 cvmx_gmxx_xaui_ext_loopback_t gmxx_xaui_ext_loopback;
342 /* Set the internal loop */
343 pcsxx_control1_reg.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface));
344 pcsxx_control1_reg.s.loopbck1 = enable_internal;
345 cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), pcsxx_control1_reg.u64);
347 /* Set the external loop */
348 gmxx_xaui_ext_loopback.u64 = cvmx_read_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface));
349 gmxx_xaui_ext_loopback.s.en = enable_external;
350 cvmx_write_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface), gmxx_xaui_ext_loopback.u64);
352 /* Take the link through a reset */
353 return __cvmx_helper_xaui_enable(interface);
356 #endif /* CVMX_ENABLE_PKO_FUNCTIONS */