cvmx-helper-srio.c revision 215976
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 SRIO initialization, configuration,
50 * and monitoring.
51 *
52 * <hr>$Revision: 41586 $<hr>
53 */
54#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
55#include <asm/octeon/cvmx.h>
56#include <asm/octeon/cvmx-config.h>
57#include <asm/octeon/cvmx-clock.h>
58#include <asm/octeon/cvmx-helper.h>
59#include <asm/octeon/cvmx-srio.h>
60#include <asm/octeon/cvmx-pip-defs.h>
61#include <asm/octeon/cvmx-sriox-defs.h>
62#include <asm/octeon/cvmx-sriomaintx-defs.h>
63#include <asm/octeon/cvmx-dpi-defs.h>
64#else
65#include "executive-config.h"
66#include "cvmx-config.h"
67#ifdef CVMX_ENABLE_PKO_FUNCTIONS
68
69#include "cvmx.h"
70#include "cvmx-helper.h"
71#include "cvmx-srio.h"
72#endif
73#endif
74
75#ifdef CVMX_ENABLE_PKO_FUNCTIONS
76
77/**
78 * @INTERNAL
79 * Probe a SRIO interface and determine the number of ports
80 * connected to it. The SRIO interface should still be down
81 * after this call.
82 *
83 * @param interface Interface to probe
84 *
85 * @return Number of ports on the interface. Zero to disable.
86 */
87int __cvmx_helper_srio_probe(int interface)
88{
89    cvmx_sriox_status_reg_t srio0_status_reg;
90    cvmx_sriox_status_reg_t srio1_status_reg;
91
92    if (!OCTEON_IS_MODEL(OCTEON_CN63XX))
93        return 0;
94
95    srio0_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(0));
96    srio1_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(1));
97    if (srio0_status_reg.s.srio || srio1_status_reg.s.srio)
98        return 2;
99    else
100        return 0;
101}
102
103
104/**
105 * @INTERNAL
106 * Bringup and enable SRIO interface. After this call packet
107 * I/O should be fully functional. This is called with IPD
108 * enabled but PKO disabled.
109 *
110 * @param interface Interface to bring up
111 *
112 * @return Zero on success, negative on failure
113 */
114int __cvmx_helper_srio_enable(int interface)
115{
116    int num_ports = cvmx_helper_ports_on_interface(interface);
117    int index;
118    cvmx_sriomaintx_core_enables_t sriomaintx_core_enables;
119    cvmx_sriox_imsg_ctrl_t sriox_imsg_ctrl;
120    cvmx_dpi_ctl_t dpi_ctl;
121
122    /* All SRIO ports have a cvmx_srio_rx_message_header_t header
123        on them that must be skipped by IPD */
124    for (index=0; index<num_ports; index++)
125    {
126        cvmx_pip_prt_cfgx_t port_config;
127        cvmx_sriox_omsg_portx_t sriox_omsg_portx;
128        cvmx_sriox_omsg_sp_mrx_t sriox_omsg_sp_mrx;
129        cvmx_sriox_omsg_fmp_mrx_t sriox_omsg_fmp_mrx;
130        cvmx_sriox_omsg_nmp_mrx_t sriox_omsg_nmp_mrx;
131        int ipd_port = cvmx_helper_get_ipd_port(interface, index);
132        port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
133        /* Only change the skip if the user hasn't already set it */
134        if (!port_config.s.skip)
135        {
136            port_config.s.skip = sizeof(cvmx_srio_rx_message_header_t);
137            cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_config.u64);
138        }
139
140        /* Enable TX with PKO */
141        sriox_omsg_portx.u64 = cvmx_read_csr(CVMX_SRIOX_OMSG_PORTX(index, interface - 4));
142        sriox_omsg_portx.s.port = (interface - 4) * 2 + index;
143        sriox_omsg_portx.s.enable = 1;
144        cvmx_write_csr(CVMX_SRIOX_OMSG_PORTX(index, interface - 4), sriox_omsg_portx.u64);
145
146        /* Allow OMSG controller to send regardless of the state of any other
147            controller. Allow messages to different IDs and MBOXes to go in
148            parallel */
149        sriox_omsg_sp_mrx.u64 = 0;
150        sriox_omsg_sp_mrx.s.xmbox_sp = 1;
151        sriox_omsg_sp_mrx.s.ctlr_sp = 1;
152        sriox_omsg_sp_mrx.s.ctlr_fmp = 1;
153        sriox_omsg_sp_mrx.s.ctlr_nmp = 1;
154        sriox_omsg_sp_mrx.s.id_sp = 1;
155        sriox_omsg_sp_mrx.s.id_fmp = 1;
156        sriox_omsg_sp_mrx.s.id_nmp = 1;
157        sriox_omsg_sp_mrx.s.mbox_sp = 1;
158        sriox_omsg_sp_mrx.s.mbox_fmp = 1;
159        sriox_omsg_sp_mrx.s.mbox_nmp = 1;
160        sriox_omsg_sp_mrx.s.all_psd = 1;
161        cvmx_write_csr(CVMX_SRIOX_OMSG_SP_MRX(index, interface-4), sriox_omsg_sp_mrx.u64);
162
163        /* Allow OMSG controller to send regardless of the state of any other
164            controller. Allow messages to different IDs and MBOXes to go in
165            parallel */
166        sriox_omsg_fmp_mrx.u64 = 0;
167        sriox_omsg_fmp_mrx.s.ctlr_sp = 1;
168        sriox_omsg_fmp_mrx.s.ctlr_fmp = 1;
169        sriox_omsg_fmp_mrx.s.ctlr_nmp = 1;
170        sriox_omsg_fmp_mrx.s.id_sp = 1;
171        sriox_omsg_fmp_mrx.s.id_fmp = 1;
172        sriox_omsg_fmp_mrx.s.id_nmp = 1;
173        sriox_omsg_fmp_mrx.s.mbox_sp = 1;
174        sriox_omsg_fmp_mrx.s.mbox_fmp = 1;
175        sriox_omsg_fmp_mrx.s.mbox_nmp = 1;
176        sriox_omsg_fmp_mrx.s.all_psd = 1;
177        cvmx_write_csr(CVMX_SRIOX_OMSG_FMP_MRX(index, interface-4), sriox_omsg_fmp_mrx.u64);
178
179        /* Once the first part of a message is accepted, always acept the rest
180            of the message */
181        sriox_omsg_nmp_mrx.u64 = 0;
182        sriox_omsg_nmp_mrx.s.all_sp = 1;
183        sriox_omsg_nmp_mrx.s.all_fmp = 1;
184        sriox_omsg_nmp_mrx.s.all_nmp = 1;
185        cvmx_write_csr(CVMX_SRIOX_OMSG_NMP_MRX(index, interface-4), sriox_omsg_nmp_mrx.u64);
186
187    }
188
189    /* Choose the receive controller based on the mailbox */
190    sriox_imsg_ctrl.u64 = cvmx_read_csr(CVMX_SRIOX_IMSG_CTRL(interface - 4));
191    sriox_imsg_ctrl.s.prt_sel = 0;
192    sriox_imsg_ctrl.s.mbox = 0xa;
193    cvmx_write_csr(CVMX_SRIOX_IMSG_CTRL(interface - 4), sriox_imsg_ctrl.u64);
194
195    /* DPI must be enabled for us to RX messages */
196    dpi_ctl.u64 = cvmx_read_csr(CVMX_DPI_CTL);
197    dpi_ctl.s.clk = 1;
198    dpi_ctl.s.en = 1;
199    cvmx_write_csr(CVMX_DPI_CTL, dpi_ctl.u64);
200
201    /* Enable RX */
202    if (!cvmx_srio_config_read32(interface - 4, 0, -1, 0, 0,
203        CVMX_SRIOMAINTX_CORE_ENABLES(interface-4), &sriomaintx_core_enables.u32))
204    {
205        sriomaintx_core_enables.s.imsg0 = 1;
206        sriomaintx_core_enables.s.imsg1 = 1;
207        cvmx_srio_config_write32(interface - 4, 0, -1, 0, 0,
208            CVMX_SRIOMAINTX_CORE_ENABLES(interface-4), sriomaintx_core_enables.u32);
209    }
210
211    return 0;
212}
213
214/**
215 * @INTERNAL
216 * Return the link state of an IPD/PKO port as returned by SRIO link status.
217 *
218 * @param ipd_port IPD/PKO port to query
219 *
220 * @return Link state
221 */
222cvmx_helper_link_info_t __cvmx_helper_srio_link_get(int ipd_port)
223{
224    int interface = cvmx_helper_get_interface_num(ipd_port);
225    int srio_port = interface - 4;
226    cvmx_helper_link_info_t result;
227    cvmx_sriox_status_reg_t srio_status_reg;
228    cvmx_sriomaintx_port_0_err_stat_t sriomaintx_port_0_err_stat;
229    cvmx_sriomaintx_port_0_ctl_t sriomaintx_port_0_ctl;
230    cvmx_sriomaintx_port_0_ctl2_t sriomaintx_port_0_ctl2;
231
232    result.u64 = 0;
233
234    /* Make sure register access is allowed */
235    srio_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(srio_port));
236    if (!srio_status_reg.s.access)
237        return result;
238
239    /* Read the port link status */
240    if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0,
241        CVMX_SRIOMAINTX_PORT_0_ERR_STAT(srio_port),
242        &sriomaintx_port_0_err_stat.u32))
243        return result;
244
245    /* Return if link is down */
246    if (!sriomaintx_port_0_err_stat.s.pt_ok)
247        return result;
248
249    /* Read the port link width and speed */
250    if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0,
251        CVMX_SRIOMAINTX_PORT_0_CTL(srio_port),
252        &sriomaintx_port_0_ctl.u32))
253        return result;
254    if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0,
255        CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port),
256        &sriomaintx_port_0_ctl2.u32))
257        return result;
258
259    /* Link is up */
260    result.s.full_duplex = 1;
261    result.s.link_up = 1;
262    switch (sriomaintx_port_0_ctl2.s.sel_baud)
263    {
264        case 1:
265            result.s.speed = 1250;
266            break;
267        case 2:
268            result.s.speed = 2500;
269            break;
270        case 3:
271            result.s.speed = 3125;
272            break;
273        case 4:
274            result.s.speed = 5000;
275            break;
276        case 5:
277            result.s.speed = 6250;
278            break;
279        default:
280            result.s.speed = 0;
281            break;
282    }
283    switch (sriomaintx_port_0_ctl.s.it_width)
284    {
285        case 2: /* Four lanes */
286            result.s.speed += 40000;
287            break;
288        case 3: /* Two lanes */
289            result.s.speed += 20000;
290            break;
291        default: /* One lane */
292            result.s.speed += 10000;
293            break;
294    }
295    return result;
296}
297
298/**
299 * @INTERNAL
300 * Configure an IPD/PKO port for the specified link state. This
301 * function does not influence auto negotiation at the PHY level.
302 * The passed link state must always match the link state returned
303 * by cvmx_helper_link_get(). It is normally best to use
304 * cvmx_helper_link_autoconf() instead.
305 *
306 * @param ipd_port  IPD/PKO port to configure
307 * @param link_info The new link state
308 *
309 * @return Zero on success, negative on failure
310 */
311int __cvmx_helper_srio_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
312{
313    return 0;
314}
315
316#endif /* CVMX_ENABLE_PKO_FUNCTIONS */
317
318