]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/octeon-sdk/cvmx-helper-xaui.c
Import the Cavium Simple Executive from the Cavium Octeon SDK. The Simple
[FreeBSD/FreeBSD.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 "executive-config.h"
53 #include "cvmx-config.h"
54 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
55
56 #include "cvmx.h"
57 #include "cvmx-helper.h"
58
59
60 /**
61  * @INTERNAL
62  * Probe a XAUI interface and determine the number of ports
63  * connected to it. The XAUI interface should still be down
64  * after this call.
65  *
66  * @param interface Interface to probe
67  *
68  * @return Number of ports on the interface. Zero to disable.
69  */
70 int __cvmx_helper_xaui_probe(int interface)
71 {
72     int i;
73     cvmx_gmxx_hg2_control_t gmx_hg2_control;
74     cvmx_gmxx_inf_mode_t mode;
75
76     /* Due to errata GMX-700 on CN56XXp1.x and CN52XXp1.x, the interface
77         needs to be enabled before IPD otherwise per port backpressure
78         may not work properly */
79     mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
80     mode.s.en = 1;
81     cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64);
82
83     __cvmx_helper_setup_gmx(interface, 1);
84
85     /* Setup PKO to support 16 ports for HiGig2 virtual ports. We're pointing
86         all of the PKO packet ports for this interface to the XAUI. This allows
87         us to use HiGig2 backpressure per port */
88     for (i=0; i<16; i++)
89     {
90         cvmx_pko_mem_port_ptrs_t pko_mem_port_ptrs;
91         pko_mem_port_ptrs.u64 = 0;
92         /* We set each PKO port to have equal priority in a round robin
93             fashion */
94         pko_mem_port_ptrs.s.static_p = 0;
95         pko_mem_port_ptrs.s.qos_mask = 0xff;
96         /* All PKO ports map to the same XAUI hardware port */
97         pko_mem_port_ptrs.s.eid = interface*4;
98         pko_mem_port_ptrs.s.pid = interface*16 + i;
99         cvmx_write_csr(CVMX_PKO_MEM_PORT_PTRS, pko_mem_port_ptrs.u64);
100     }
101
102     /* If HiGig2 is enabled return 16 ports, otherwise return 1 port */
103     gmx_hg2_control.u64 = cvmx_read_csr(CVMX_GMXX_HG2_CONTROL(interface));
104     if (gmx_hg2_control.s.hg2tx_en)
105         return 16;
106     else
107         return 1;
108 }
109
110
111 /**
112  * @INTERNAL
113  * Bringup and enable a XAUI interface. After this call packet
114  * I/O should be fully functional. This is called with IPD
115  * enabled but PKO disabled.
116  *
117  * @param interface Interface to bring up
118  *
119  * @return Zero on success, negative on failure
120  */
121 int __cvmx_helper_xaui_enable(int interface)
122 {
123     cvmx_gmxx_prtx_cfg_t          gmx_cfg;
124     cvmx_pcsxx_control1_reg_t     xauiCtl;
125     cvmx_pcsxx_misc_ctl_reg_t     xauiMiscCtl;
126     cvmx_gmxx_tx_xaui_ctl_t       gmxXauiTxCtl;
127     cvmx_gmxx_rxx_int_en_t        gmx_rx_int_en;
128     cvmx_gmxx_tx_int_en_t         gmx_tx_int_en;
129     cvmx_pcsxx_int_en_reg_t       pcsx_int_en_reg;
130
131     /* (1) Interface has already been enabled. */
132
133     /* (2) Disable GMX. */
134     xauiMiscCtl.u64 = cvmx_read_csr(CVMX_PCSXX_MISC_CTL_REG(interface));
135     xauiMiscCtl.s.gmxeno = 1;
136     cvmx_write_csr (CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64);
137
138     /* (3) Disable GMX and PCSX interrupts. */
139     gmx_rx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(0,interface));
140     cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0,interface), 0x0);
141     gmx_tx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_TX_INT_EN(interface));
142     cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0x0);
143     pcsx_int_en_reg.u64 = cvmx_read_csr(CVMX_PCSXX_INT_EN_REG(interface));
144     cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), 0x0);
145
146     /* (4) Bring up the PCSX and GMX reconciliation layer. */
147     /* (4)a Set polarity and lane swapping. */
148     /* (4)b */
149     gmxXauiTxCtl.u64 = cvmx_read_csr (CVMX_GMXX_TX_XAUI_CTL(interface));
150     gmxXauiTxCtl.s.dic_en = 1; /* Enable better IFG packing and improves performance */
151     gmxXauiTxCtl.s.uni_en = 0;
152     cvmx_write_csr (CVMX_GMXX_TX_XAUI_CTL(interface), gmxXauiTxCtl.u64);
153
154     /* (4)c Aply reset sequence */
155     xauiCtl.u64 = cvmx_read_csr (CVMX_PCSXX_CONTROL1_REG(interface));
156     xauiCtl.s.lo_pwr = 0;
157     xauiCtl.s.reset  = 1;
158     cvmx_write_csr (CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64);
159
160     /* Wait for PCS to come out of reset */
161     if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_CONTROL1_REG(interface), cvmx_pcsxx_control1_reg_t, reset, ==, 0, 10000))
162         return -1;
163     /* Wait for PCS to be aligned */
164     if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_10GBX_STATUS_REG(interface), cvmx_pcsxx_10gbx_status_reg_t, alignd, ==, 1, 10000))
165         return -1;
166     /* Wait for RX to be ready */
167     if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_RX_XAUI_CTL(interface), cvmx_gmxx_rx_xaui_ctl_t, status, ==, 0, 10000))
168         return -1;
169
170     /* (6) Configure GMX */
171     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
172     gmx_cfg.s.en = 0;
173     cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
174
175     /* Wait for GMX RX to be idle */
176     if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(0, interface), cvmx_gmxx_prtx_cfg_t, rx_idle, ==, 1, 10000))
177         return -1;
178     /* Wait for GMX TX to be idle */
179     if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(0, interface), cvmx_gmxx_prtx_cfg_t, tx_idle, ==, 1, 10000))
180         return -1;
181
182     /* GMX configure */
183     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
184     gmx_cfg.s.speed = 1;
185     gmx_cfg.s.speed_msb = 0;
186     gmx_cfg.s.slottime = 1;
187     cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), 1);
188     cvmx_write_csr(CVMX_GMXX_TXX_SLOT(0, interface), 512);
189     cvmx_write_csr(CVMX_GMXX_TXX_BURST(0, interface), 8192);
190     cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
191
192     /* (7) Clear out any error state */
193     cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(0,interface), cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(0,interface)));
194     cvmx_write_csr(CVMX_GMXX_TX_INT_REG(interface), cvmx_read_csr(CVMX_GMXX_TX_INT_REG(interface)));
195     cvmx_write_csr(CVMX_PCSXX_INT_REG(interface), cvmx_read_csr(CVMX_PCSXX_INT_REG(interface)));
196
197     /* Wait for receive link */
198     if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS1_REG(interface), cvmx_pcsxx_status1_reg_t, rcv_lnk, ==, 1, 10000))
199         return -1;
200     if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, xmtflt, ==, 0, 10000))
201         return -1;
202     if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, rcvflt, ==, 0, 10000))
203         return -1;
204
205     cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0,interface), gmx_rx_int_en.u64);
206     cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), gmx_tx_int_en.u64);
207     cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), pcsx_int_en_reg.u64);
208
209     cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port(interface, 0));
210
211     /* (8) Enable packet reception */
212     xauiMiscCtl.s.gmxeno = 0;
213     cvmx_write_csr (CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64);
214
215     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
216     gmx_cfg.s.en = 1;
217     cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
218     return 0;
219 }
220
221 /**
222  * @INTERNAL
223  * Return the link state of an IPD/PKO port as returned by
224  * auto negotiation. The result of this function may not match
225  * Octeon's link config if auto negotiation has changed since
226  * the last call to cvmx_helper_link_set().
227  *
228  * @param ipd_port IPD/PKO port to query
229  *
230  * @return Link state
231  */
232 cvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port)
233 {
234     int interface = cvmx_helper_get_interface_num(ipd_port);
235     cvmx_gmxx_tx_xaui_ctl_t gmxx_tx_xaui_ctl;
236     cvmx_gmxx_rx_xaui_ctl_t gmxx_rx_xaui_ctl;
237     cvmx_pcsxx_status1_reg_t pcsxx_status1_reg;
238     cvmx_helper_link_info_t result;
239
240     gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface));
241     gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface));
242     pcsxx_status1_reg.u64 = cvmx_read_csr(CVMX_PCSXX_STATUS1_REG(interface));
243     result.u64 = 0;
244
245     /* Only return a link if both RX and TX are happy */
246     if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0) &&
247         (pcsxx_status1_reg.s.rcv_lnk == 1))
248     {
249         result.s.link_up = 1;
250         result.s.full_duplex = 1;
251         result.s.speed = 10000;
252     }
253     else
254     {
255         /* Disable GMX and PCSX interrupts. */
256         cvmx_write_csr (CVMX_GMXX_RXX_INT_EN(0,interface), 0x0);
257         cvmx_write_csr (CVMX_GMXX_TX_INT_EN(interface), 0x0);
258         cvmx_write_csr (CVMX_PCSXX_INT_EN_REG(interface), 0x0);
259     }
260     return result;
261 }
262
263
264 /**
265  * @INTERNAL
266  * Configure an IPD/PKO port for the specified link state. This
267  * function does not influence auto negotiation at the PHY level.
268  * The passed link state must always match the link state returned
269  * by cvmx_helper_link_get(). It is normally best to use
270  * cvmx_helper_link_autoconf() instead.
271  *
272  * @param ipd_port  IPD/PKO port to configure
273  * @param link_info The new link state
274  *
275  * @return Zero on success, negative on failure
276  */
277 int __cvmx_helper_xaui_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
278 {
279     int interface = cvmx_helper_get_interface_num(ipd_port);
280     cvmx_gmxx_tx_xaui_ctl_t gmxx_tx_xaui_ctl;
281     cvmx_gmxx_rx_xaui_ctl_t gmxx_rx_xaui_ctl;
282
283     gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface));
284     gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface));
285
286     /* If the link shouldn't be up, then just return */
287     if (!link_info.s.link_up)
288         return 0;
289
290     /* Do nothing if both RX and TX are happy */
291     if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0))
292         return 0;
293
294     /* Bring the link up */
295     return __cvmx_helper_xaui_enable(interface);
296 }
297
298
299 /**
300  * @INTERNAL
301  * Configure a port for internal and/or external loopback. Internal loopback
302  * causes packets sent by the port to be received by Octeon. External loopback
303  * causes packets received from the wire to sent out again.
304  *
305  * @param ipd_port IPD/PKO port to loopback.
306  * @param enable_internal
307  *                 Non zero if you want internal loopback
308  * @param enable_external
309  *                 Non zero if you want external loopback
310  *
311  * @return Zero on success, negative on failure.
312  */
313 extern int __cvmx_helper_xaui_configure_loopback(int ipd_port, int enable_internal, int enable_external)
314 {
315     int interface = cvmx_helper_get_interface_num(ipd_port);
316     cvmx_pcsxx_control1_reg_t pcsxx_control1_reg;
317     cvmx_gmxx_xaui_ext_loopback_t gmxx_xaui_ext_loopback;
318
319     /* Set the internal loop */
320     pcsxx_control1_reg.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface));
321     pcsxx_control1_reg.s.loopbck1 = enable_internal;
322     cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), pcsxx_control1_reg.u64);
323
324     /* Set the external loop */
325     gmxx_xaui_ext_loopback.u64 = cvmx_read_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface));
326     gmxx_xaui_ext_loopback.s.en = enable_external;
327     cvmx_write_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface), gmxx_xaui_ext_loopback.u64);
328
329     /* Take the link through a reset */
330     return __cvmx_helper_xaui_enable(interface);
331 }
332
333 #endif /* CVMX_ENABLE_PKO_FUNCTIONS */
334