1215976Sjmallett/***********************license start***************
2232812Sjmallett * Copyright (c) 2003-2010  Cavium Inc. (support@cavium.com). All rights
3215976Sjmallett * reserved.
4215976Sjmallett *
5215976Sjmallett *
6215976Sjmallett * Redistribution and use in source and binary forms, with or without
7215976Sjmallett * modification, are permitted provided that the following conditions are
8215976Sjmallett * met:
9215976Sjmallett *
10215976Sjmallett *   * Redistributions of source code must retain the above copyright
11215976Sjmallett *     notice, this list of conditions and the following disclaimer.
12215976Sjmallett *
13215976Sjmallett *   * Redistributions in binary form must reproduce the above
14215976Sjmallett *     copyright notice, this list of conditions and the following
15215976Sjmallett *     disclaimer in the documentation and/or other materials provided
16215976Sjmallett *     with the distribution.
17215976Sjmallett
18232812Sjmallett *   * Neither the name of Cavium Inc. nor the names of
19215976Sjmallett *     its contributors may be used to endorse or promote products
20215976Sjmallett *     derived from this software without specific prior written
21215976Sjmallett *     permission.
22215976Sjmallett
23215976Sjmallett * This Software, including technical data, may be subject to U.S. export  control
24215976Sjmallett * laws, including the U.S. Export Administration Act and its  associated
25215976Sjmallett * regulations, and may be subject to export or import  regulations in other
26215976Sjmallett * countries.
27215976Sjmallett
28215976Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30215976Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31215976Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32215976Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33215976Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34215976Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35215976Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36215976Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
37215976Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38215976Sjmallett ***********************license end**************************************/
39215976Sjmallett
40215976Sjmallett
41215976Sjmallett
42215976Sjmallett
43215976Sjmallett
44215976Sjmallett
45215976Sjmallett
46215976Sjmallett/**
47215976Sjmallett * @file
48215976Sjmallett *
49215976Sjmallett * Functions for SRIO initialization, configuration,
50215976Sjmallett * and monitoring.
51215976Sjmallett *
52215976Sjmallett * <hr>$Revision: 41586 $<hr>
53215976Sjmallett */
54215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
55215976Sjmallett#include <asm/octeon/cvmx.h>
56215976Sjmallett#include <asm/octeon/cvmx-config.h>
57215976Sjmallett#include <asm/octeon/cvmx-clock.h>
58215976Sjmallett#include <asm/octeon/cvmx-helper.h>
59232812Sjmallett#include <asm/octeon/cvmx-qlm.h>
60215976Sjmallett#include <asm/octeon/cvmx-srio.h>
61215976Sjmallett#include <asm/octeon/cvmx-pip-defs.h>
62215976Sjmallett#include <asm/octeon/cvmx-sriox-defs.h>
63215976Sjmallett#include <asm/octeon/cvmx-sriomaintx-defs.h>
64215976Sjmallett#include <asm/octeon/cvmx-dpi-defs.h>
65215976Sjmallett#else
66215990Sjmallett#if !defined(__FreeBSD__) || !defined(_KERNEL)
67215976Sjmallett#include "executive-config.h"
68215976Sjmallett#include "cvmx-config.h"
69215976Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS
70215976Sjmallett
71215976Sjmallett#include "cvmx.h"
72215976Sjmallett#include "cvmx-helper.h"
73215976Sjmallett#include "cvmx-srio.h"
74215976Sjmallett#endif
75232812Sjmallett#include "cvmx-qlm.h"
76215990Sjmallett#else
77215990Sjmallett#include "cvmx.h"
78215990Sjmallett#include "cvmx-helper.h"
79232812Sjmallett#include "cvmx-qlm.h"
80215990Sjmallett#include "cvmx-srio.h"
81215976Sjmallett#endif
82215990Sjmallett#endif
83215976Sjmallett
84215976Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS
85215976Sjmallett
86215976Sjmallett/**
87215976Sjmallett * @INTERNAL
88215976Sjmallett * Probe a SRIO interface and determine the number of ports
89215976Sjmallett * connected to it. The SRIO interface should still be down
90215976Sjmallett * after this call.
91215976Sjmallett *
92215976Sjmallett * @param interface Interface to probe
93215976Sjmallett *
94215976Sjmallett * @return Number of ports on the interface. Zero to disable.
95215976Sjmallett */
96215976Sjmallettint __cvmx_helper_srio_probe(int interface)
97215976Sjmallett{
98215976Sjmallett    cvmx_sriox_status_reg_t srio0_status_reg;
99215976Sjmallett    cvmx_sriox_status_reg_t srio1_status_reg;
100215976Sjmallett
101232812Sjmallett    if (!octeon_has_feature(OCTEON_FEATURE_SRIO))
102215976Sjmallett        return 0;
103215976Sjmallett
104232812Sjmallett    /* Read MIO_QLMX_CFG CSRs to find SRIO status. */
105232812Sjmallett    if (OCTEON_IS_MODEL(OCTEON_CN66XX))
106232812Sjmallett    {
107232812Sjmallett        int status = cvmx_qlm_get_status(0);
108232812Sjmallett        int srio_port = interface - 4;
109232812Sjmallett        switch(srio_port)
110232812Sjmallett        {
111232812Sjmallett            case 0:  /* 1x4 lane */
112232812Sjmallett                if (status == 4)
113232812Sjmallett                    return 2;
114232812Sjmallett                break;
115232812Sjmallett            case 2:  /* 2x2 lane */
116232812Sjmallett                if (status == 5)
117232812Sjmallett                    return 2;
118232812Sjmallett                break;
119232812Sjmallett            case 1: /* 4x1 long/short */
120232812Sjmallett            case 3: /* 4x1 long/short */
121232812Sjmallett                if (status == 6)
122232812Sjmallett                    return 2;
123232812Sjmallett                break;
124232812Sjmallett        }
125232812Sjmallett        return 0;
126232812Sjmallett    }
127232812Sjmallett
128215976Sjmallett    srio0_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(0));
129215976Sjmallett    srio1_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(1));
130215976Sjmallett    if (srio0_status_reg.s.srio || srio1_status_reg.s.srio)
131215976Sjmallett        return 2;
132215976Sjmallett    else
133215976Sjmallett        return 0;
134215976Sjmallett}
135215976Sjmallett
136215976Sjmallett
137215976Sjmallett/**
138215976Sjmallett * @INTERNAL
139215976Sjmallett * Bringup and enable SRIO interface. After this call packet
140215976Sjmallett * I/O should be fully functional. This is called with IPD
141215976Sjmallett * enabled but PKO disabled.
142215976Sjmallett *
143215976Sjmallett * @param interface Interface to bring up
144215976Sjmallett *
145215976Sjmallett * @return Zero on success, negative on failure
146215976Sjmallett */
147215976Sjmallettint __cvmx_helper_srio_enable(int interface)
148215976Sjmallett{
149215976Sjmallett    int num_ports = cvmx_helper_ports_on_interface(interface);
150215976Sjmallett    int index;
151215976Sjmallett    cvmx_sriomaintx_core_enables_t sriomaintx_core_enables;
152215976Sjmallett    cvmx_sriox_imsg_ctrl_t sriox_imsg_ctrl;
153232812Sjmallett    cvmx_sriox_status_reg_t srio_status_reg;
154215976Sjmallett    cvmx_dpi_ctl_t dpi_ctl;
155232812Sjmallett    int srio_port = interface - 4;
156215976Sjmallett
157215976Sjmallett    /* All SRIO ports have a cvmx_srio_rx_message_header_t header
158215976Sjmallett        on them that must be skipped by IPD */
159215976Sjmallett    for (index=0; index<num_ports; index++)
160215976Sjmallett    {
161215976Sjmallett        cvmx_pip_prt_cfgx_t port_config;
162215976Sjmallett        cvmx_sriox_omsg_portx_t sriox_omsg_portx;
163215976Sjmallett        cvmx_sriox_omsg_sp_mrx_t sriox_omsg_sp_mrx;
164215976Sjmallett        cvmx_sriox_omsg_fmp_mrx_t sriox_omsg_fmp_mrx;
165215976Sjmallett        cvmx_sriox_omsg_nmp_mrx_t sriox_omsg_nmp_mrx;
166215976Sjmallett        int ipd_port = cvmx_helper_get_ipd_port(interface, index);
167215976Sjmallett        port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
168215976Sjmallett        /* Only change the skip if the user hasn't already set it */
169215976Sjmallett        if (!port_config.s.skip)
170215976Sjmallett        {
171215976Sjmallett            port_config.s.skip = sizeof(cvmx_srio_rx_message_header_t);
172215976Sjmallett            cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_config.u64);
173215976Sjmallett        }
174215976Sjmallett
175215976Sjmallett        /* Enable TX with PKO */
176232812Sjmallett        sriox_omsg_portx.u64 = cvmx_read_csr(CVMX_SRIOX_OMSG_PORTX(index, srio_port));
177232812Sjmallett        sriox_omsg_portx.s.port = (srio_port) * 2 + index;
178215976Sjmallett        sriox_omsg_portx.s.enable = 1;
179232812Sjmallett        cvmx_write_csr(CVMX_SRIOX_OMSG_PORTX(index, srio_port), sriox_omsg_portx.u64);
180215976Sjmallett
181215976Sjmallett        /* Allow OMSG controller to send regardless of the state of any other
182215976Sjmallett            controller. Allow messages to different IDs and MBOXes to go in
183215976Sjmallett            parallel */
184215976Sjmallett        sriox_omsg_sp_mrx.u64 = 0;
185215976Sjmallett        sriox_omsg_sp_mrx.s.xmbox_sp = 1;
186215976Sjmallett        sriox_omsg_sp_mrx.s.ctlr_sp = 1;
187215976Sjmallett        sriox_omsg_sp_mrx.s.ctlr_fmp = 1;
188215976Sjmallett        sriox_omsg_sp_mrx.s.ctlr_nmp = 1;
189215976Sjmallett        sriox_omsg_sp_mrx.s.id_sp = 1;
190215976Sjmallett        sriox_omsg_sp_mrx.s.id_fmp = 1;
191215976Sjmallett        sriox_omsg_sp_mrx.s.id_nmp = 1;
192215976Sjmallett        sriox_omsg_sp_mrx.s.mbox_sp = 1;
193215976Sjmallett        sriox_omsg_sp_mrx.s.mbox_fmp = 1;
194215976Sjmallett        sriox_omsg_sp_mrx.s.mbox_nmp = 1;
195215976Sjmallett        sriox_omsg_sp_mrx.s.all_psd = 1;
196232812Sjmallett        cvmx_write_csr(CVMX_SRIOX_OMSG_SP_MRX(index, srio_port), sriox_omsg_sp_mrx.u64);
197215976Sjmallett
198215976Sjmallett        /* Allow OMSG controller to send regardless of the state of any other
199215976Sjmallett            controller. Allow messages to different IDs and MBOXes to go in
200215976Sjmallett            parallel */
201215976Sjmallett        sriox_omsg_fmp_mrx.u64 = 0;
202215976Sjmallett        sriox_omsg_fmp_mrx.s.ctlr_sp = 1;
203215976Sjmallett        sriox_omsg_fmp_mrx.s.ctlr_fmp = 1;
204215976Sjmallett        sriox_omsg_fmp_mrx.s.ctlr_nmp = 1;
205215976Sjmallett        sriox_omsg_fmp_mrx.s.id_sp = 1;
206215976Sjmallett        sriox_omsg_fmp_mrx.s.id_fmp = 1;
207215976Sjmallett        sriox_omsg_fmp_mrx.s.id_nmp = 1;
208215976Sjmallett        sriox_omsg_fmp_mrx.s.mbox_sp = 1;
209215976Sjmallett        sriox_omsg_fmp_mrx.s.mbox_fmp = 1;
210215976Sjmallett        sriox_omsg_fmp_mrx.s.mbox_nmp = 1;
211215976Sjmallett        sriox_omsg_fmp_mrx.s.all_psd = 1;
212232812Sjmallett        cvmx_write_csr(CVMX_SRIOX_OMSG_FMP_MRX(index, srio_port), sriox_omsg_fmp_mrx.u64);
213215976Sjmallett
214215976Sjmallett        /* Once the first part of a message is accepted, always acept the rest
215215976Sjmallett            of the message */
216215976Sjmallett        sriox_omsg_nmp_mrx.u64 = 0;
217215976Sjmallett        sriox_omsg_nmp_mrx.s.all_sp = 1;
218215976Sjmallett        sriox_omsg_nmp_mrx.s.all_fmp = 1;
219215976Sjmallett        sriox_omsg_nmp_mrx.s.all_nmp = 1;
220232812Sjmallett        cvmx_write_csr(CVMX_SRIOX_OMSG_NMP_MRX(index, srio_port), sriox_omsg_nmp_mrx.u64);
221215976Sjmallett
222215976Sjmallett    }
223215976Sjmallett
224215976Sjmallett    /* Choose the receive controller based on the mailbox */
225232812Sjmallett    sriox_imsg_ctrl.u64 = cvmx_read_csr(CVMX_SRIOX_IMSG_CTRL(srio_port));
226215976Sjmallett    sriox_imsg_ctrl.s.prt_sel = 0;
227215976Sjmallett    sriox_imsg_ctrl.s.mbox = 0xa;
228232812Sjmallett    cvmx_write_csr(CVMX_SRIOX_IMSG_CTRL(srio_port), sriox_imsg_ctrl.u64);
229215976Sjmallett
230215976Sjmallett    /* DPI must be enabled for us to RX messages */
231215976Sjmallett    dpi_ctl.u64 = cvmx_read_csr(CVMX_DPI_CTL);
232215976Sjmallett    dpi_ctl.s.clk = 1;
233215976Sjmallett    dpi_ctl.s.en = 1;
234215976Sjmallett    cvmx_write_csr(CVMX_DPI_CTL, dpi_ctl.u64);
235215976Sjmallett
236232812Sjmallett    /* Make sure register access is allowed */
237232812Sjmallett    srio_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(srio_port));
238232812Sjmallett    if (!srio_status_reg.s.access)
239232812Sjmallett        return 0;
240232812Sjmallett
241215976Sjmallett    /* Enable RX */
242232812Sjmallett    if (!cvmx_srio_config_read32(srio_port, 0, -1, 0, 0,
243232812Sjmallett        CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), &sriomaintx_core_enables.u32))
244215976Sjmallett    {
245215976Sjmallett        sriomaintx_core_enables.s.imsg0 = 1;
246215976Sjmallett        sriomaintx_core_enables.s.imsg1 = 1;
247232812Sjmallett        cvmx_srio_config_write32(srio_port, 0, -1, 0, 0,
248232812Sjmallett            CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), sriomaintx_core_enables.u32);
249215976Sjmallett    }
250215976Sjmallett
251215976Sjmallett    return 0;
252215976Sjmallett}
253215976Sjmallett
254215976Sjmallett/**
255215976Sjmallett * @INTERNAL
256215976Sjmallett * Return the link state of an IPD/PKO port as returned by SRIO link status.
257215976Sjmallett *
258215976Sjmallett * @param ipd_port IPD/PKO port to query
259215976Sjmallett *
260215976Sjmallett * @return Link state
261215976Sjmallett */
262215976Sjmallettcvmx_helper_link_info_t __cvmx_helper_srio_link_get(int ipd_port)
263215976Sjmallett{
264215976Sjmallett    int interface = cvmx_helper_get_interface_num(ipd_port);
265215976Sjmallett    int srio_port = interface - 4;
266215976Sjmallett    cvmx_helper_link_info_t result;
267215976Sjmallett    cvmx_sriox_status_reg_t srio_status_reg;
268215976Sjmallett    cvmx_sriomaintx_port_0_err_stat_t sriomaintx_port_0_err_stat;
269215976Sjmallett    cvmx_sriomaintx_port_0_ctl_t sriomaintx_port_0_ctl;
270215976Sjmallett    cvmx_sriomaintx_port_0_ctl2_t sriomaintx_port_0_ctl2;
271215976Sjmallett
272215976Sjmallett    result.u64 = 0;
273215976Sjmallett
274215976Sjmallett    /* Make sure register access is allowed */
275215976Sjmallett    srio_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(srio_port));
276215976Sjmallett    if (!srio_status_reg.s.access)
277215976Sjmallett        return result;
278215976Sjmallett
279215976Sjmallett    /* Read the port link status */
280215976Sjmallett    if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0,
281215976Sjmallett        CVMX_SRIOMAINTX_PORT_0_ERR_STAT(srio_port),
282215976Sjmallett        &sriomaintx_port_0_err_stat.u32))
283215976Sjmallett        return result;
284215976Sjmallett
285215976Sjmallett    /* Return if link is down */
286215976Sjmallett    if (!sriomaintx_port_0_err_stat.s.pt_ok)
287215976Sjmallett        return result;
288215976Sjmallett
289215976Sjmallett    /* Read the port link width and speed */
290215976Sjmallett    if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0,
291215976Sjmallett        CVMX_SRIOMAINTX_PORT_0_CTL(srio_port),
292215976Sjmallett        &sriomaintx_port_0_ctl.u32))
293215976Sjmallett        return result;
294215976Sjmallett    if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0,
295215976Sjmallett        CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port),
296215976Sjmallett        &sriomaintx_port_0_ctl2.u32))
297215976Sjmallett        return result;
298215976Sjmallett
299215976Sjmallett    /* Link is up */
300215976Sjmallett    result.s.full_duplex = 1;
301215976Sjmallett    result.s.link_up = 1;
302215976Sjmallett    switch (sriomaintx_port_0_ctl2.s.sel_baud)
303215976Sjmallett    {
304215976Sjmallett        case 1:
305215976Sjmallett            result.s.speed = 1250;
306215976Sjmallett            break;
307215976Sjmallett        case 2:
308215976Sjmallett            result.s.speed = 2500;
309215976Sjmallett            break;
310215976Sjmallett        case 3:
311215976Sjmallett            result.s.speed = 3125;
312215976Sjmallett            break;
313215976Sjmallett        case 4:
314215976Sjmallett            result.s.speed = 5000;
315215976Sjmallett            break;
316215976Sjmallett        case 5:
317215976Sjmallett            result.s.speed = 6250;
318215976Sjmallett            break;
319215976Sjmallett        default:
320215976Sjmallett            result.s.speed = 0;
321215976Sjmallett            break;
322215976Sjmallett    }
323215976Sjmallett    switch (sriomaintx_port_0_ctl.s.it_width)
324215976Sjmallett    {
325215976Sjmallett        case 2: /* Four lanes */
326215976Sjmallett            result.s.speed += 40000;
327215976Sjmallett            break;
328215976Sjmallett        case 3: /* Two lanes */
329215976Sjmallett            result.s.speed += 20000;
330215976Sjmallett            break;
331215976Sjmallett        default: /* One lane */
332215976Sjmallett            result.s.speed += 10000;
333215976Sjmallett            break;
334215976Sjmallett    }
335215976Sjmallett    return result;
336215976Sjmallett}
337215976Sjmallett
338215976Sjmallett/**
339215976Sjmallett * @INTERNAL
340215976Sjmallett * Configure an IPD/PKO port for the specified link state. This
341215976Sjmallett * function does not influence auto negotiation at the PHY level.
342215976Sjmallett * The passed link state must always match the link state returned
343215976Sjmallett * by cvmx_helper_link_get(). It is normally best to use
344215976Sjmallett * cvmx_helper_link_autoconf() instead.
345215976Sjmallett *
346215976Sjmallett * @param ipd_port  IPD/PKO port to configure
347215976Sjmallett * @param link_info The new link state
348215976Sjmallett *
349215976Sjmallett * @return Zero on success, negative on failure
350215976Sjmallett */
351215976Sjmallettint __cvmx_helper_srio_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
352215976Sjmallett{
353215976Sjmallett    return 0;
354215976Sjmallett}
355215976Sjmallett
356215976Sjmallett#endif /* CVMX_ENABLE_PKO_FUNCTIONS */
357215976Sjmallett
358