]> CyberLeo.Net >> Repos - FreeBSD/releng/8.2.git/blob - sys/contrib/octeon-sdk/cvmx-helper-xaui.c
Copy stable/8 to releng/8.2 in preparation for FreeBSD-8.2 release.
[FreeBSD/releng/8.2.git] / sys / contrib / octeon-sdk / cvmx-helper-xaui.c
1 /***********************license start***************
2  *  Copyright (c) 2003-2008 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  *  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.
33  *
34  *
35  *  For any questions regarding licensing please contact marketing@caviumnetworks.com
36  *
37  ***********************license end**************************************/
38
39
40
41
42
43
44 /**
45  * @file
46  *
47  * Functions for XAUI initialization, configuration,
48  * and monitoring.
49  *
50  * <hr>$Revision: 42417 $<hr>
51  */
52 #include "cvmx.h"
53 #include "cvmx-helper.h"
54
55 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
56 /**
57  * @INTERNAL
58  * Probe a XAUI interface and determine the number of ports
59  * connected to it. The XAUI interface should still be down
60  * after this call.
61  *
62  * @param interface Interface to probe
63  *
64  * @return Number of ports on the interface. Zero to disable.
65  */
66 int __cvmx_helper_xaui_probe(int interface)
67 {
68     int i;
69     cvmx_gmxx_hg2_control_t gmx_hg2_control;
70     cvmx_gmxx_inf_mode_t mode;
71
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));
76     mode.s.en = 1;
77     cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64);
78
79     __cvmx_helper_setup_gmx(interface, 1);
80
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 */
84     for (i=0; i<16; i++)
85     {
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
89             fashion */
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);
96     }
97
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)
101         return 16;
102     else
103         return 1;
104 }
105
106
107 /**
108  * @INTERNAL
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.
112  *
113  * @param interface Interface to bring up
114  *
115  * @return Zero on success, negative on failure
116  */
117 int __cvmx_helper_xaui_enable(int interface)
118 {
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;
126
127     /* (1) Interface has already been enabled. */
128
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);
133
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);
141
142     /* (4) Bring up the PCSX and GMX reconciliation layer. */
143     /* (4)a Set polarity and lane swapping. */
144     /* (4)b */
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);
149
150     /* (4)c Aply reset sequence */
151     xauiCtl.u64 = cvmx_read_csr (CVMX_PCSXX_CONTROL1_REG(interface));
152     xauiCtl.s.lo_pwr = 0;
153     xauiCtl.s.reset  = 1;
154     cvmx_write_csr (CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64);
155
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))
158         return -1;
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))
161         return -1;
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))
164         return -1;
165
166     /* (6) Configure GMX */
167     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
168     gmx_cfg.s.en = 0;
169     cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
170
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))
173         return -1;
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))
176         return -1;
177
178     /* GMX configure */
179     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
180     gmx_cfg.s.speed = 1;
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);
187
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)));
192
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))
195         return -1;
196     if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, xmtflt, ==, 0, 10000))
197         return -1;
198     if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, rcvflt, ==, 0, 10000))
199         return -1;
200
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);
204
205     cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port(interface, 0));
206
207     /* (8) Enable packet reception */
208     xauiMiscCtl.s.gmxeno = 0;
209     cvmx_write_csr (CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64);
210
211     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
212     gmx_cfg.s.en = 1;
213     cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
214     return 0;
215 }
216
217 /**
218  * @INTERNAL
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().
223  *
224  * @param ipd_port IPD/PKO port to query
225  *
226  * @return Link state
227  */
228 cvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port)
229 {
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;
235
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));
239     result.u64 = 0;
240
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))
244     {
245         result.s.link_up = 1;
246         result.s.full_duplex = 1;
247         result.s.speed = 10000;
248     }
249     else
250     {
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);
255     }
256     return result;
257 }
258
259
260 /**
261  * @INTERNAL
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.
267  *
268  * @param ipd_port  IPD/PKO port to configure
269  * @param link_info The new link state
270  *
271  * @return Zero on success, negative on failure
272  */
273 int __cvmx_helper_xaui_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
274 {
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;
278
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));
281
282     /* If the link shouldn't be up, then just return */
283     if (!link_info.s.link_up)
284         return 0;
285
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))
288         return 0;
289
290     /* Bring the link up */
291     return __cvmx_helper_xaui_enable(interface);
292 }
293
294
295 /**
296  * @INTERNAL
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.
300  *
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
306  *
307  * @return Zero on success, negative on failure.
308  */
309 extern int __cvmx_helper_xaui_configure_loopback(int ipd_port, int enable_internal, int enable_external)
310 {
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;
314
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);
319
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);
324
325     /* Take the link through a reset */
326     return __cvmx_helper_xaui_enable(interface);
327 }
328
329 #endif /* CVMX_ENABLE_PKO_FUNCTIONS */
330