]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/octeon-sdk/cvmx-helper-xaui.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / octeon-sdk / cvmx-helper-xaui.c
1 /***********************license start***************
2  * Copyright (c) 2003-2010  Cavium Networks (support@cavium.com). All rights
3  * reserved.
4  *
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *   * Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  *
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.
17
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
21  *     permission.
22
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
26  * countries.
27
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**************************************/
39
40
41
42
43
44
45
46 /**
47  * @file
48  *
49  * Functions for XAUI initialization, configuration,
50  * and monitoring.
51  *
52  * <hr>$Revision: 52004 $<hr>
53  */
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>
59 #endif
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>
64 #else
65 #if !defined(__FreeBSD__) || !defined(_KERNEL)
66 #include "executive-config.h"
67 #include "cvmx-config.h"
68
69 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
70
71 #include "cvmx.h"
72 #include "cvmx-helper.h"
73 #endif
74 #else
75 #include "cvmx.h"
76 #include "cvmx-helper.h"
77 #endif
78 #endif
79
80 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
81
82
83 /**
84  * @INTERNAL
85  * Probe a XAUI interface and determine the number of ports
86  * connected to it. The XAUI interface should still be down
87  * after this call.
88  *
89  * @param interface Interface to probe
90  *
91  * @return Number of ports on the interface. Zero to disable.
92  */
93 int __cvmx_helper_xaui_probe(int interface)
94 {
95     int i;
96     cvmx_gmxx_hg2_control_t gmx_hg2_control;
97     cvmx_gmxx_inf_mode_t mode;
98
99     /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be programmed */
100     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0))
101     {
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);
108     }
109
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));
114     mode.s.en = 1;
115     cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64);
116
117     __cvmx_helper_setup_gmx(interface, 1);
118
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 */
122     for (i=0; i<16; i++)
123     {
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
127             fashion */
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);
134     }
135
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)
139         return 16;
140     else
141         return 1;
142 }
143
144
145 /**
146  * @INTERNAL
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.
150  *
151  * @param interface Interface to bring up
152  *
153  * @return Zero on success, negative on failure
154  */
155 int __cvmx_helper_xaui_enable(int interface)
156 {
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;
162
163     /* (1) Interface has already been enabled. */
164
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);
169
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);
174
175     /* (4) Bring up the PCSX and GMX reconciliation layer. */
176     /* (4)a Set polarity and lane swapping. */
177     /* (4)b */
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);
182
183     /* (4)c Aply reset sequence */
184     xauiCtl.u64 = cvmx_read_csr (CVMX_PCSXX_CONTROL1_REG(interface));
185     xauiCtl.s.lo_pwr = 0;
186     xauiCtl.s.reset  = 1;
187     cvmx_write_csr (CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64);
188
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))
191         return -1;
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))
194         return -1;
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))
197         return -1;
198
199     /* (6) Configure GMX */
200     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
201     gmx_cfg.s.en = 0;
202     cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
203
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))
206         return -1;
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))
209         return -1;
210
211     /* GMX configure */
212     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
213     gmx_cfg.s.speed = 1;
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);
220
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))
223         return -1;
224     if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, xmtflt, ==, 0, 10000))
225         return -1;
226     if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, rcvflt, ==, 0, 10000))
227         return -1;
228
229     /* (8) Enable packet reception */
230     xauiMiscCtl.s.gmxeno = 0;
231     cvmx_write_csr (CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64);
232
233     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
234     gmx_cfg.s.en = 1;
235     cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
236
237     link_info = cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port(interface, 0));
238     if (!link_info.s.link_up)
239         return -1;
240
241     return 0;
242 }
243
244 /**
245  * @INTERNAL
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().
250  *
251  * @param ipd_port IPD/PKO port to query
252  *
253  * @return Link state
254  */
255 cvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port)
256 {
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;
262
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));
266     result.u64 = 0;
267
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))
271     {
272         result.s.link_up = 1;
273         result.s.full_duplex = 1;
274         result.s.speed = 10000;
275     }
276     else
277     {
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);
282     }
283     return result;
284 }
285
286
287 /**
288  * @INTERNAL
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.
294  *
295  * @param ipd_port  IPD/PKO port to configure
296  * @param link_info The new link state
297  *
298  * @return Zero on success, negative on failure
299  */
300 int __cvmx_helper_xaui_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
301 {
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;
305
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));
308
309     /* If the link shouldn't be up, then just return */
310     if (!link_info.s.link_up)
311         return 0;
312
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))
315         return 0;
316
317     /* Bring the link up */
318     return __cvmx_helper_xaui_enable(interface);
319 }
320
321
322 /**
323  * @INTERNAL
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.
327  *
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
333  *
334  * @return Zero on success, negative on failure.
335  */
336 extern int __cvmx_helper_xaui_configure_loopback(int ipd_port, int enable_internal, int enable_external)
337 {
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;
341
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);
346
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);
351
352     /* Take the link through a reset */
353     return __cvmx_helper_xaui_enable(interface);
354 }
355
356 #endif /* CVMX_ENABLE_PKO_FUNCTIONS */
357