]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/octeon-sdk/cvmx-helper-spi.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / octeon-sdk / cvmx-helper-spi.c
1 /***********************license start***************
2  * Copyright (c) 2003-2010  Cavium Inc. (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 Inc. 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 INC. 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  * @file
46  *
47  * Functions for SPI initialization, configuration,
48  * and monitoring.
49  *
50  * <hr>$Revision: 70030 $<hr>
51  */
52 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
53 #include <asm/octeon/cvmx.h>
54 #include <asm/octeon/cvmx-config.h>
55 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
56 #include <asm/octeon/cvmx-spi.h>
57 #include <asm/octeon/cvmx-helper.h>
58 #endif
59 #include <asm/octeon/cvmx-pko-defs.h>
60 #include <asm/octeon/cvmx-pip-defs.h>
61 #else
62 #if !defined(__FreeBSD__) || !defined(_KERNEL)
63 #include "executive-config.h"
64 #include "cvmx-config.h"
65 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
66
67 #include "cvmx.h"
68 #include "cvmx-spi.h"
69 #include "cvmx-sysinfo.h"
70 #include "cvmx-helper.h"
71 #endif
72 #else
73 #include "cvmx.h"
74 #include "cvmx-spi.h"
75 #include "cvmx-sysinfo.h"
76 #include "cvmx-helper.h"
77 #endif
78 #endif
79
80 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
81
82 /* CVMX_HELPER_SPI_TIMEOUT is used to determine how long the SPI initialization
83     routines wait for SPI training. You can override the value using
84     executive-config.h if necessary */
85 #ifndef CVMX_HELPER_SPI_TIMEOUT
86 #define CVMX_HELPER_SPI_TIMEOUT 10
87 #endif
88
89 int __cvmx_helper_spi_enumerate(int interface)
90 {
91 #if defined(OCTEON_VENDOR_LANNER)
92     if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_LANNER_MR955)
93     {
94         cvmx_pko_reg_crc_enable_t enable;
95
96         enable.u64 = cvmx_read_csr(CVMX_PKO_REG_CRC_ENABLE);
97         enable.s.enable &= 0xffff << (16 - (interface*16));
98         cvmx_write_csr(CVMX_PKO_REG_CRC_ENABLE, enable.u64);
99
100         if (interface == 1)
101             return 12;
102         /* XXX This is not entirely true.  */
103         return 0;
104     }
105 #endif
106
107 #if defined(OCTEON_VENDOR_RADISYS)
108     if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE) {
109             if (interface == 0)
110                     return 13;
111             if (interface == 1)
112                     return 8;
113             return 0;
114     }
115 #endif
116
117         if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) &&
118             cvmx_spi4000_is_present(interface))
119                 return 10;
120         else
121                 return 16;
122 }
123
124 /**
125  * @INTERNAL
126  * Probe a SPI interface and determine the number of ports
127  * connected to it. The SPI interface should still be down after
128  * this call.
129  *
130  * @param interface Interface to probe
131  *
132  * @return Number of ports on the interface. Zero to disable.
133  */
134 int __cvmx_helper_spi_probe(int interface)
135 {
136         int num_ports = __cvmx_helper_spi_enumerate(interface);
137
138         if (num_ports == 16) {
139                 cvmx_pko_reg_crc_enable_t enable;
140                 /*
141                  * Unlike the SPI4000, most SPI devices don't
142                  * automatically put on the L2 CRC. For everything
143                  * except for the SPI4000 have PKO append the L2 CRC
144                  * to the packet
145                  */
146                 enable.u64 = cvmx_read_csr(CVMX_PKO_REG_CRC_ENABLE);
147                 enable.s.enable |= 0xffff << (interface*16);
148                 cvmx_write_csr(CVMX_PKO_REG_CRC_ENABLE, enable.u64);
149         }
150         __cvmx_helper_setup_gmx(interface, num_ports);
151         return num_ports;
152 }
153
154
155 /**
156  * @INTERNAL
157  * Bringup and enable a SPI interface. After this call packet I/O
158  * should be fully functional. This is called with IPD enabled but
159  * PKO disabled.
160  *
161  * @param interface Interface to bring up
162  *
163  * @return Zero on success, negative on failure
164  */
165 int __cvmx_helper_spi_enable(int interface)
166 {
167     /* Normally the ethernet L2 CRC is checked and stripped in the GMX block.
168         When you are using SPI, this isn' the case and IPD needs to check
169         the L2 CRC */
170     int num_ports = cvmx_helper_ports_on_interface(interface);
171     int ipd_port;
172     for (ipd_port=interface*16; ipd_port<interface*16+num_ports; ipd_port++)
173     {
174         cvmx_pip_prt_cfgx_t port_config;
175         port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
176         port_config.s.crc_en = 1;
177 #ifdef OCTEON_VENDOR_RADISYS
178         /*
179          * Incoming packets on the RSYS4GBE have the FCS stripped.
180          */
181         if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE)
182                 port_config.s.crc_en = 0;
183 #endif
184         cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_config.u64);
185     }
186
187     if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)
188     {
189         cvmx_spi_start_interface(interface, CVMX_SPI_MODE_DUPLEX, CVMX_HELPER_SPI_TIMEOUT, num_ports);
190         if (cvmx_spi4000_is_present(interface))
191             cvmx_spi4000_initialize(interface);
192     }
193     return 0;
194 }
195
196 /**
197  * @INTERNAL
198  * Return the link state of an IPD/PKO port as returned by
199  * auto negotiation. The result of this function may not match
200  * Octeon's link config if auto negotiation has changed since
201  * the last call to cvmx_helper_link_set().
202  *
203  * @param ipd_port IPD/PKO port to query
204  *
205  * @return Link state
206  */
207 cvmx_helper_link_info_t __cvmx_helper_spi_link_get(int ipd_port)
208 {
209     cvmx_helper_link_info_t result;
210     int interface = cvmx_helper_get_interface_num(ipd_port);
211     int index = cvmx_helper_get_interface_index_num(ipd_port);
212     result.u64 = 0;
213
214     if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
215     {
216         /* The simulator gives you a simulated full duplex link */
217         result.s.link_up = 1;
218         result.s.full_duplex = 1;
219         result.s.speed = 10000;
220     }
221     else if (cvmx_spi4000_is_present(interface))
222     {
223         cvmx_gmxx_rxx_rx_inbnd_t inband = cvmx_spi4000_check_speed(interface, index);
224         result.s.link_up = inband.s.status;
225         result.s.full_duplex = inband.s.duplex;
226         switch (inband.s.speed)
227         {
228             case 0: /* 10 Mbps */
229                 result.s.speed = 10;
230                 break;
231             case 1: /* 100 Mbps */
232                 result.s.speed = 100;
233                 break;
234             case 2: /* 1 Gbps */
235                 result.s.speed = 1000;
236                 break;
237             case 3: /* Illegal */
238                 result.s.speed = 0;
239                 result.s.link_up = 0;
240                 break;
241         }
242     }
243     else
244     {
245         /* For generic SPI we can't determine the link, just return some
246             sane results */
247         result.s.link_up = 1;
248         result.s.full_duplex = 1;
249         result.s.speed = 10000;
250     }
251     return result;
252 }
253
254
255 /**
256  * @INTERNAL
257  * Configure an IPD/PKO port for the specified link state. This
258  * function does not influence auto negotiation at the PHY level.
259  * The passed link state must always match the link state returned
260  * by cvmx_helper_link_get(). It is normally best to use
261  * cvmx_helper_link_autoconf() instead.
262  *
263  * @param ipd_port  IPD/PKO port to configure
264  * @param link_info The new link state
265  *
266  * @return Zero on success, negative on failure
267  */
268 int __cvmx_helper_spi_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
269 {
270     /* Nothing to do. If we have a SPI4000 then the setup was already performed
271         by cvmx_spi4000_check_speed(). If not then there isn't any link
272         info */
273     return 0;
274 }
275
276 #endif /* CVMX_ENABLE_PKO_FUNCTIONS */
277