1af866496SDavid Daney /***********************license start***************
2af866496SDavid Daney * Author: Cavium Networks
3af866496SDavid Daney *
4af866496SDavid Daney * Contact: support@caviumnetworks.com
5af866496SDavid Daney * This file is part of the OCTEON SDK
6af866496SDavid Daney *
7840267e4SSteven J. Hill * Copyright (C) 2003-2018 Cavium, Inc.
8af866496SDavid Daney *
9af866496SDavid Daney * This file is free software; you can redistribute it and/or modify
10af866496SDavid Daney * it under the terms of the GNU General Public License, Version 2, as
11af866496SDavid Daney * published by the Free Software Foundation.
12af866496SDavid Daney *
13af866496SDavid Daney * This file is distributed in the hope that it will be useful, but
14af866496SDavid Daney * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15af866496SDavid Daney * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16af866496SDavid Daney * NONINFRINGEMENT. See the GNU General Public License for more
17af866496SDavid Daney * details.
18af866496SDavid Daney *
19af866496SDavid Daney * You should have received a copy of the GNU General Public License
20af866496SDavid Daney * along with this file; if not, write to the Free Software
21af866496SDavid Daney * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22af866496SDavid Daney * or visit http://www.gnu.org/licenses/.
23af866496SDavid Daney *
24af866496SDavid Daney * This file may also be available under a different license from Cavium.
25af866496SDavid Daney * Contact Cavium Networks for more information
26af866496SDavid Daney ***********************license end**************************************/
27af866496SDavid Daney
28af866496SDavid Daney /*
29af866496SDavid Daney * Functions for SPI initialization, configuration,
30af866496SDavid Daney * and monitoring.
31af866496SDavid Daney */
32af866496SDavid Daney #include <asm/octeon/octeon.h>
33af866496SDavid Daney
34af866496SDavid Daney #include <asm/octeon/cvmx-config.h>
35af866496SDavid Daney #include <asm/octeon/cvmx-spi.h>
36af866496SDavid Daney #include <asm/octeon/cvmx-helper.h>
37af866496SDavid Daney
38af866496SDavid Daney #include <asm/octeon/cvmx-pip-defs.h>
39af866496SDavid Daney #include <asm/octeon/cvmx-pko-defs.h>
40840267e4SSteven J. Hill #include <asm/octeon/cvmx-spxx-defs.h>
41840267e4SSteven J. Hill #include <asm/octeon/cvmx-stxx-defs.h>
42af866496SDavid Daney
43af866496SDavid Daney /*
44af866496SDavid Daney * CVMX_HELPER_SPI_TIMEOUT is used to determine how long the SPI
45af866496SDavid Daney * initialization routines wait for SPI training. You can override the
46af866496SDavid Daney * value using executive-config.h if necessary.
47af866496SDavid Daney */
48af866496SDavid Daney #ifndef CVMX_HELPER_SPI_TIMEOUT
49af866496SDavid Daney #define CVMX_HELPER_SPI_TIMEOUT 10
50af866496SDavid Daney #endif
51af866496SDavid Daney
__cvmx_helper_spi_enumerate(int interface)5237d3bfd9SDavid Daney int __cvmx_helper_spi_enumerate(int interface)
5337d3bfd9SDavid Daney {
5437d3bfd9SDavid Daney if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) &&
5537d3bfd9SDavid Daney cvmx_spi4000_is_present(interface)) {
5637d3bfd9SDavid Daney return 10;
5737d3bfd9SDavid Daney } else {
5837d3bfd9SDavid Daney return 16;
5937d3bfd9SDavid Daney }
6037d3bfd9SDavid Daney }
6137d3bfd9SDavid Daney
62af866496SDavid Daney /**
63af866496SDavid Daney * Probe a SPI interface and determine the number of ports
64af866496SDavid Daney * connected to it. The SPI interface should still be down after
65af866496SDavid Daney * this call.
66af866496SDavid Daney *
67af866496SDavid Daney * @interface: Interface to probe
68af866496SDavid Daney *
69af866496SDavid Daney * Returns Number of ports on the interface. Zero to disable.
70af866496SDavid Daney */
__cvmx_helper_spi_probe(int interface)71af866496SDavid Daney int __cvmx_helper_spi_probe(int interface)
72af866496SDavid Daney {
73af866496SDavid Daney int num_ports = 0;
74af866496SDavid Daney
75af866496SDavid Daney if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) &&
76af866496SDavid Daney cvmx_spi4000_is_present(interface)) {
77af866496SDavid Daney num_ports = 10;
78af866496SDavid Daney } else {
79af866496SDavid Daney union cvmx_pko_reg_crc_enable enable;
80af866496SDavid Daney num_ports = 16;
81af866496SDavid Daney /*
82af866496SDavid Daney * Unlike the SPI4000, most SPI devices don't
83af866496SDavid Daney * automatically put on the L2 CRC. For everything
84af866496SDavid Daney * except for the SPI4000 have PKO append the L2 CRC
85af866496SDavid Daney * to the packet.
86af866496SDavid Daney */
87af866496SDavid Daney enable.u64 = cvmx_read_csr(CVMX_PKO_REG_CRC_ENABLE);
88af866496SDavid Daney enable.s.enable |= 0xffff << (interface * 16);
89af866496SDavid Daney cvmx_write_csr(CVMX_PKO_REG_CRC_ENABLE, enable.u64);
90af866496SDavid Daney }
91af866496SDavid Daney __cvmx_helper_setup_gmx(interface, num_ports);
92af866496SDavid Daney return num_ports;
93af866496SDavid Daney }
94af866496SDavid Daney
95af866496SDavid Daney /**
96af866496SDavid Daney * Bringup and enable a SPI interface. After this call packet I/O
97af866496SDavid Daney * should be fully functional. This is called with IPD enabled but
98af866496SDavid Daney * PKO disabled.
99af866496SDavid Daney *
100af866496SDavid Daney * @interface: Interface to bring up
101af866496SDavid Daney *
102af866496SDavid Daney * Returns Zero on success, negative on failure
103af866496SDavid Daney */
__cvmx_helper_spi_enable(int interface)104af866496SDavid Daney int __cvmx_helper_spi_enable(int interface)
105af866496SDavid Daney {
106af866496SDavid Daney /*
107af866496SDavid Daney * Normally the ethernet L2 CRC is checked and stripped in the
108af866496SDavid Daney * GMX block. When you are using SPI, this isn' the case and
109af866496SDavid Daney * IPD needs to check the L2 CRC.
110af866496SDavid Daney */
111af866496SDavid Daney int num_ports = cvmx_helper_ports_on_interface(interface);
112af866496SDavid Daney int ipd_port;
113af866496SDavid Daney for (ipd_port = interface * 16; ipd_port < interface * 16 + num_ports;
114af866496SDavid Daney ipd_port++) {
115af866496SDavid Daney union cvmx_pip_prt_cfgx port_config;
116af866496SDavid Daney port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
117af866496SDavid Daney port_config.s.crc_en = 1;
118af866496SDavid Daney cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_config.u64);
119af866496SDavid Daney }
120af866496SDavid Daney
121af866496SDavid Daney if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) {
122af866496SDavid Daney cvmx_spi_start_interface(interface, CVMX_SPI_MODE_DUPLEX,
123af866496SDavid Daney CVMX_HELPER_SPI_TIMEOUT, num_ports);
124af866496SDavid Daney if (cvmx_spi4000_is_present(interface))
125af866496SDavid Daney cvmx_spi4000_initialize(interface);
126af866496SDavid Daney }
127af866496SDavid Daney __cvmx_interrupt_spxx_int_msk_enable(interface);
128af866496SDavid Daney __cvmx_interrupt_stxx_int_msk_enable(interface);
129af866496SDavid Daney __cvmx_interrupt_gmxx_enable(interface);
130af866496SDavid Daney return 0;
131af866496SDavid Daney }
132af866496SDavid Daney
133af866496SDavid Daney /**
134af866496SDavid Daney * Return the link state of an IPD/PKO port as returned by
135af866496SDavid Daney * auto negotiation. The result of this function may not match
136af866496SDavid Daney * Octeon's link config if auto negotiation has changed since
137af866496SDavid Daney * the last call to cvmx_helper_link_set().
138af866496SDavid Daney *
139af866496SDavid Daney * @ipd_port: IPD/PKO port to query
140af866496SDavid Daney *
141af866496SDavid Daney * Returns Link state
142af866496SDavid Daney */
__cvmx_helper_spi_link_get(int ipd_port)143*f7d2bdcbSChris Packham union cvmx_helper_link_info __cvmx_helper_spi_link_get(int ipd_port)
144af866496SDavid Daney {
145*f7d2bdcbSChris Packham union cvmx_helper_link_info result;
146af866496SDavid Daney int interface = cvmx_helper_get_interface_num(ipd_port);
147af866496SDavid Daney int index = cvmx_helper_get_interface_index_num(ipd_port);
148af866496SDavid Daney result.u64 = 0;
149af866496SDavid Daney
150af866496SDavid Daney if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) {
151af866496SDavid Daney /* The simulator gives you a simulated full duplex link */
152af866496SDavid Daney result.s.link_up = 1;
153af866496SDavid Daney result.s.full_duplex = 1;
154af866496SDavid Daney result.s.speed = 10000;
155af866496SDavid Daney } else if (cvmx_spi4000_is_present(interface)) {
156af866496SDavid Daney union cvmx_gmxx_rxx_rx_inbnd inband =
157af866496SDavid Daney cvmx_spi4000_check_speed(interface, index);
158af866496SDavid Daney result.s.link_up = inband.s.status;
159af866496SDavid Daney result.s.full_duplex = inband.s.duplex;
160af866496SDavid Daney switch (inband.s.speed) {
161af866496SDavid Daney case 0: /* 10 Mbps */
162af866496SDavid Daney result.s.speed = 10;
163af866496SDavid Daney break;
164af866496SDavid Daney case 1: /* 100 Mbps */
165af866496SDavid Daney result.s.speed = 100;
166af866496SDavid Daney break;
167af866496SDavid Daney case 2: /* 1 Gbps */
168af866496SDavid Daney result.s.speed = 1000;
169af866496SDavid Daney break;
170af866496SDavid Daney case 3: /* Illegal */
171af866496SDavid Daney result.s.speed = 0;
172af866496SDavid Daney result.s.link_up = 0;
173af866496SDavid Daney break;
174af866496SDavid Daney }
175af866496SDavid Daney } else {
176af866496SDavid Daney /* For generic SPI we can't determine the link, just return some
177af866496SDavid Daney sane results */
178af866496SDavid Daney result.s.link_up = 1;
179af866496SDavid Daney result.s.full_duplex = 1;
180af866496SDavid Daney result.s.speed = 10000;
181af866496SDavid Daney }
182af866496SDavid Daney return result;
183af866496SDavid Daney }
184af866496SDavid Daney
185af866496SDavid Daney /**
186af866496SDavid Daney * Configure an IPD/PKO port for the specified link state. This
187af866496SDavid Daney * function does not influence auto negotiation at the PHY level.
188af866496SDavid Daney * The passed link state must always match the link state returned
1892b58a76eSAaro Koskinen * by cvmx_helper_link_get().
190af866496SDavid Daney *
191af866496SDavid Daney * @ipd_port: IPD/PKO port to configure
192af866496SDavid Daney * @link_info: The new link state
193af866496SDavid Daney *
194af866496SDavid Daney * Returns Zero on success, negative on failure
195af866496SDavid Daney */
__cvmx_helper_spi_link_set(int ipd_port,union cvmx_helper_link_info link_info)196*f7d2bdcbSChris Packham int __cvmx_helper_spi_link_set(int ipd_port, union cvmx_helper_link_info link_info)
197af866496SDavid Daney {
198af866496SDavid Daney /* Nothing to do. If we have a SPI4000 then the setup was already performed
199af866496SDavid Daney by cvmx_spi4000_check_speed(). If not then there isn't any link
200af866496SDavid Daney info */
201af866496SDavid Daney return 0;
202af866496SDavid Daney }
203