Path: blob/master/arch/mips/cavium-octeon/executive/cvmx-helper.c
26481 views
/***********************license start***************1* Author: Cavium Networks2*3* Contact: [email protected]4* This file is part of the OCTEON SDK5*6* Copyright (c) 2003-2008 Cavium Networks7*8* This file is free software; you can redistribute it and/or modify9* it under the terms of the GNU General Public License, Version 2, as10* published by the Free Software Foundation.11*12* This file is distributed in the hope that it will be useful, but13* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty14* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or15* NONINFRINGEMENT. See the GNU General Public License for more16* details.17*18* You should have received a copy of the GNU General Public License19* along with this file; if not, write to the Free Software20* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA21* or visit http://www.gnu.org/licenses/.22*23* This file may also be available under a different license from Cavium.24* Contact Cavium Networks for more information25***********************license end**************************************/2627/*28*29* Helper functions for common, but complicated tasks.30*31*/32#include <linux/bug.h>33#include <asm/octeon/octeon.h>3435#include <asm/octeon/cvmx-config.h>3637#include <asm/octeon/cvmx-fpa.h>38#include <asm/octeon/cvmx-pip.h>39#include <asm/octeon/cvmx-pko.h>40#include <asm/octeon/cvmx-ipd.h>41#include <asm/octeon/cvmx-spi.h>42#include <asm/octeon/cvmx-helper.h>43#include <asm/octeon/cvmx-helper-board.h>4445#include <asm/octeon/cvmx-pip-defs.h>46#include <asm/octeon/cvmx-asxx-defs.h>4748/* Port count per interface */49static int interface_port_count[9];5051/**52* Return the number of interfaces the chip has. Each interface53* may have multiple ports. Most chips support two interfaces,54* but the CNX0XX and CNX1XX are exceptions. These only support55* one interface.56*57* Returns Number of interfaces on chip58*/59int cvmx_helper_get_number_of_interfaces(void)60{61if (OCTEON_IS_MODEL(OCTEON_CN68XX))62return 9;63if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {64if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0))65return 7;66else67return 8;68}69if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))70return 4;71if (OCTEON_IS_MODEL(OCTEON_CN7XXX))72return 5;73else74return 3;75}76EXPORT_SYMBOL_GPL(cvmx_helper_get_number_of_interfaces);7778/**79* Return the number of ports on an interface. Depending on the80* chip and configuration, this can be 1-16. A value of 081* specifies that the interface doesn't exist or isn't usable.82*83* @interface: Interface to get the port count for84*85* Returns Number of ports on interface. Can be Zero.86*/87int cvmx_helper_ports_on_interface(int interface)88{89return interface_port_count[interface];90}91EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);9293/**94* @INTERNAL95* Return interface mode for CN68xx.96*/97static cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface)98{99union cvmx_mio_qlmx_cfg qlm_cfg;100switch (interface) {101case 0:102qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));103/* QLM is disabled when QLM SPD is 15. */104if (qlm_cfg.s.qlm_spd == 15)105return CVMX_HELPER_INTERFACE_MODE_DISABLED;106107if (qlm_cfg.s.qlm_cfg == 2)108return CVMX_HELPER_INTERFACE_MODE_SGMII;109else if (qlm_cfg.s.qlm_cfg == 3)110return CVMX_HELPER_INTERFACE_MODE_XAUI;111else112return CVMX_HELPER_INTERFACE_MODE_DISABLED;113case 2:114case 3:115case 4:116qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface));117/* QLM is disabled when QLM SPD is 15. */118if (qlm_cfg.s.qlm_spd == 15)119return CVMX_HELPER_INTERFACE_MODE_DISABLED;120121if (qlm_cfg.s.qlm_cfg == 2)122return CVMX_HELPER_INTERFACE_MODE_SGMII;123else if (qlm_cfg.s.qlm_cfg == 3)124return CVMX_HELPER_INTERFACE_MODE_XAUI;125else126return CVMX_HELPER_INTERFACE_MODE_DISABLED;127case 7:128qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3));129/* QLM is disabled when QLM SPD is 15. */130if (qlm_cfg.s.qlm_spd == 15) {131return CVMX_HELPER_INTERFACE_MODE_DISABLED;132} else if (qlm_cfg.s.qlm_cfg != 0) {133qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));134if (qlm_cfg.s.qlm_cfg != 0)135return CVMX_HELPER_INTERFACE_MODE_DISABLED;136}137return CVMX_HELPER_INTERFACE_MODE_NPI;138case 8:139return CVMX_HELPER_INTERFACE_MODE_LOOP;140default:141return CVMX_HELPER_INTERFACE_MODE_DISABLED;142}143}144145/**146* @INTERNAL147* Return interface mode for an Octeon II148*/149static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)150{151union cvmx_gmxx_inf_mode mode;152153if (OCTEON_IS_MODEL(OCTEON_CN68XX))154return __cvmx_get_mode_cn68xx(interface);155156if (interface == 2)157return CVMX_HELPER_INTERFACE_MODE_NPI;158159if (interface == 3)160return CVMX_HELPER_INTERFACE_MODE_LOOP;161162/* Only present in CN63XX & CN66XX Octeon model */163if ((OCTEON_IS_MODEL(OCTEON_CN63XX) &&164(interface == 4 || interface == 5)) ||165(OCTEON_IS_MODEL(OCTEON_CN66XX) &&166interface >= 4 && interface <= 7)) {167return CVMX_HELPER_INTERFACE_MODE_DISABLED;168}169170if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {171union cvmx_mio_qlmx_cfg mio_qlm_cfg;172173/* QLM2 is SGMII0 and QLM1 is SGMII1 */174if (interface == 0)175mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));176else if (interface == 1)177mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));178else179return CVMX_HELPER_INTERFACE_MODE_DISABLED;180181if (mio_qlm_cfg.s.qlm_spd == 15)182return CVMX_HELPER_INTERFACE_MODE_DISABLED;183184if (mio_qlm_cfg.s.qlm_cfg == 9)185return CVMX_HELPER_INTERFACE_MODE_SGMII;186else if (mio_qlm_cfg.s.qlm_cfg == 11)187return CVMX_HELPER_INTERFACE_MODE_XAUI;188else189return CVMX_HELPER_INTERFACE_MODE_DISABLED;190} else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {191union cvmx_mio_qlmx_cfg qlm_cfg;192193if (interface == 0) {194qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));195if (qlm_cfg.s.qlm_cfg == 2)196return CVMX_HELPER_INTERFACE_MODE_SGMII;197else if (qlm_cfg.s.qlm_cfg == 3)198return CVMX_HELPER_INTERFACE_MODE_XAUI;199else200return CVMX_HELPER_INTERFACE_MODE_DISABLED;201} else if (interface == 1) {202qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));203if (qlm_cfg.s.qlm_cfg == 2)204return CVMX_HELPER_INTERFACE_MODE_SGMII;205else if (qlm_cfg.s.qlm_cfg == 3)206return CVMX_HELPER_INTERFACE_MODE_XAUI;207else208return CVMX_HELPER_INTERFACE_MODE_DISABLED;209}210} else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {211if (interface == 0) {212union cvmx_mio_qlmx_cfg qlm_cfg;213qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));214if (qlm_cfg.s.qlm_cfg == 2)215return CVMX_HELPER_INTERFACE_MODE_SGMII;216}217return CVMX_HELPER_INTERFACE_MODE_DISABLED;218}219220if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX))221return CVMX_HELPER_INTERFACE_MODE_DISABLED;222223mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));224225if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {226switch (mode.cn61xx.mode) {227case 0:228return CVMX_HELPER_INTERFACE_MODE_SGMII;229case 1:230return CVMX_HELPER_INTERFACE_MODE_XAUI;231default:232return CVMX_HELPER_INTERFACE_MODE_DISABLED;233}234} else {235if (!mode.s.en)236return CVMX_HELPER_INTERFACE_MODE_DISABLED;237238if (mode.s.type)239return CVMX_HELPER_INTERFACE_MODE_GMII;240else241return CVMX_HELPER_INTERFACE_MODE_RGMII;242}243}244245/**246* @INTERNAL247* Return interface mode for CN7XXX.248*/249static cvmx_helper_interface_mode_t __cvmx_get_mode_cn7xxx(int interface)250{251union cvmx_gmxx_inf_mode mode;252253mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));254255switch (interface) {256case 0:257case 1:258switch (mode.cn68xx.mode) {259case 0:260return CVMX_HELPER_INTERFACE_MODE_DISABLED;261case 1:262case 2:263return CVMX_HELPER_INTERFACE_MODE_SGMII;264case 3:265return CVMX_HELPER_INTERFACE_MODE_XAUI;266default:267return CVMX_HELPER_INTERFACE_MODE_SGMII;268}269case 2:270return CVMX_HELPER_INTERFACE_MODE_NPI;271case 3:272return CVMX_HELPER_INTERFACE_MODE_LOOP;273case 4:274/* TODO: Implement support for AGL (RGMII). */275return CVMX_HELPER_INTERFACE_MODE_DISABLED;276default:277return CVMX_HELPER_INTERFACE_MODE_DISABLED;278}279}280281/**282* Get the operating mode of an interface. Depending on the Octeon283* chip and configuration, this function returns an enumeration284* of the type of packet I/O supported by an interface.285*286* @interface: Interface to probe287*288* Returns Mode of the interface. Unknown or unsupported interfaces return289* DISABLED.290*/291cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)292{293union cvmx_gmxx_inf_mode mode;294295if (interface < 0 ||296interface >= cvmx_helper_get_number_of_interfaces())297return CVMX_HELPER_INTERFACE_MODE_DISABLED;298299/*300* OCTEON III models301*/302if (OCTEON_IS_MODEL(OCTEON_CN7XXX))303return __cvmx_get_mode_cn7xxx(interface);304305/*306* Octeon II models307*/308if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))309return __cvmx_get_mode_octeon2(interface);310311/*312* Octeon and Octeon Plus models313*/314if (interface == 2)315return CVMX_HELPER_INTERFACE_MODE_NPI;316317if (interface == 3) {318if (OCTEON_IS_MODEL(OCTEON_CN56XX)319|| OCTEON_IS_MODEL(OCTEON_CN52XX))320return CVMX_HELPER_INTERFACE_MODE_LOOP;321else322return CVMX_HELPER_INTERFACE_MODE_DISABLED;323}324325/* Interface 1 is always disabled on CN31XX and CN30XX */326if ((interface == 1)327&& (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)328|| OCTEON_IS_MODEL(OCTEON_CN50XX)329|| OCTEON_IS_MODEL(OCTEON_CN52XX)))330return CVMX_HELPER_INTERFACE_MODE_DISABLED;331332mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));333334if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {335switch (mode.cn52xx.mode) {336case 0:337return CVMX_HELPER_INTERFACE_MODE_DISABLED;338case 1:339return CVMX_HELPER_INTERFACE_MODE_XAUI;340case 2:341return CVMX_HELPER_INTERFACE_MODE_SGMII;342case 3:343return CVMX_HELPER_INTERFACE_MODE_PICMG;344default:345return CVMX_HELPER_INTERFACE_MODE_DISABLED;346}347} else {348if (!mode.s.en)349return CVMX_HELPER_INTERFACE_MODE_DISABLED;350351if (mode.s.type) {352if (OCTEON_IS_MODEL(OCTEON_CN38XX)353|| OCTEON_IS_MODEL(OCTEON_CN58XX))354return CVMX_HELPER_INTERFACE_MODE_SPI;355else356return CVMX_HELPER_INTERFACE_MODE_GMII;357} else358return CVMX_HELPER_INTERFACE_MODE_RGMII;359}360}361EXPORT_SYMBOL_GPL(cvmx_helper_interface_get_mode);362363/**364* Configure the IPD/PIP tagging and QoS options for a specific365* port. This function determines the POW work queue entry366* contents for a port. The setup performed here is controlled by367* the defines in executive-config.h.368*369* @ipd_port: Port to configure. This follows the IPD numbering, not the370* per interface numbering371*372* Returns Zero on success, negative on failure373*/374static int __cvmx_helper_port_setup_ipd(int ipd_port)375{376union cvmx_pip_prt_cfgx port_config;377union cvmx_pip_prt_tagx tag_config;378379port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));380tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));381382/* Have each port go to a different POW queue */383port_config.s.qos = ipd_port & 0x7;384385/* Process the headers and place the IP header in the work queue */386port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;387388tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;389tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;390tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;391tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;392tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;393tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;394tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;395tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;396tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;397tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;398tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;399tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;400tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;401tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;402tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;403tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;404/* Put all packets in group 0. Other groups can be used by the app */405tag_config.s.grp = 0;406407cvmx_pip_config_port(ipd_port, port_config, tag_config);408409return 0;410}411412/**413* This function sets the interface_port_count[interface] correctly,414* without modifying any hardware configuration. Hardware setup of415* the ports will be performed later.416*417* @interface: Interface to probe418*419* Returns Zero on success, negative on failure420*/421int cvmx_helper_interface_enumerate(int interface)422{423switch (cvmx_helper_interface_get_mode(interface)) {424/* These types don't support ports to IPD/PKO */425case CVMX_HELPER_INTERFACE_MODE_DISABLED:426case CVMX_HELPER_INTERFACE_MODE_PCIE:427interface_port_count[interface] = 0;428break;429/* XAUI is a single high speed port */430case CVMX_HELPER_INTERFACE_MODE_XAUI:431interface_port_count[interface] =432__cvmx_helper_xaui_enumerate(interface);433break;434/*435* RGMII/GMII/MII are all treated about the same. Most436* functions refer to these ports as RGMII.437*/438case CVMX_HELPER_INTERFACE_MODE_RGMII:439case CVMX_HELPER_INTERFACE_MODE_GMII:440interface_port_count[interface] =441__cvmx_helper_rgmii_enumerate(interface);442break;443/*444* SPI4 can have 1-16 ports depending on the device at445* the other end.446*/447case CVMX_HELPER_INTERFACE_MODE_SPI:448interface_port_count[interface] =449__cvmx_helper_spi_enumerate(interface);450break;451/*452* SGMII can have 1-4 ports depending on how many are453* hooked up.454*/455case CVMX_HELPER_INTERFACE_MODE_SGMII:456case CVMX_HELPER_INTERFACE_MODE_PICMG:457interface_port_count[interface] =458__cvmx_helper_sgmii_enumerate(interface);459break;460/* PCI target Network Packet Interface */461case CVMX_HELPER_INTERFACE_MODE_NPI:462interface_port_count[interface] =463__cvmx_helper_npi_enumerate(interface);464break;465/*466* Special loopback only ports. These are not the same467* as other ports in loopback mode.468*/469case CVMX_HELPER_INTERFACE_MODE_LOOP:470interface_port_count[interface] =471__cvmx_helper_loop_enumerate(interface);472break;473}474475interface_port_count[interface] =476__cvmx_helper_board_interface_probe(interface,477interface_port_count478[interface]);479480/* Make sure all global variables propagate to other cores */481CVMX_SYNCWS;482483return 0;484}485486/**487* This function probes an interface to determine the actual488* number of hardware ports connected to it. It doesn't setup the489* ports or enable them. The main goal here is to set the global490* interface_port_count[interface] correctly. Hardware setup of the491* ports will be performed later.492*493* @interface: Interface to probe494*495* Returns Zero on success, negative on failure496*/497int cvmx_helper_interface_probe(int interface)498{499cvmx_helper_interface_enumerate(interface);500/* At this stage in the game we don't want packets to be moving yet.501The following probe calls should perform hardware setup502needed to determine port counts. Receive must still be disabled */503switch (cvmx_helper_interface_get_mode(interface)) {504/* These types don't support ports to IPD/PKO */505case CVMX_HELPER_INTERFACE_MODE_DISABLED:506case CVMX_HELPER_INTERFACE_MODE_PCIE:507break;508/* XAUI is a single high speed port */509case CVMX_HELPER_INTERFACE_MODE_XAUI:510__cvmx_helper_xaui_probe(interface);511break;512/*513* RGMII/GMII/MII are all treated about the same. Most514* functions refer to these ports as RGMII.515*/516case CVMX_HELPER_INTERFACE_MODE_RGMII:517case CVMX_HELPER_INTERFACE_MODE_GMII:518__cvmx_helper_rgmii_probe(interface);519break;520/*521* SPI4 can have 1-16 ports depending on the device at522* the other end.523*/524case CVMX_HELPER_INTERFACE_MODE_SPI:525__cvmx_helper_spi_probe(interface);526break;527/*528* SGMII can have 1-4 ports depending on how many are529* hooked up.530*/531case CVMX_HELPER_INTERFACE_MODE_SGMII:532case CVMX_HELPER_INTERFACE_MODE_PICMG:533__cvmx_helper_sgmii_probe(interface);534break;535/* PCI target Network Packet Interface */536case CVMX_HELPER_INTERFACE_MODE_NPI:537__cvmx_helper_npi_probe(interface);538break;539/*540* Special loopback only ports. These are not the same541* as other ports in loopback mode.542*/543case CVMX_HELPER_INTERFACE_MODE_LOOP:544__cvmx_helper_loop_probe(interface);545break;546}547548/* Make sure all global variables propagate to other cores */549CVMX_SYNCWS;550551return 0;552}553554/**555* Setup the IPD/PIP for the ports on an interface. Packet556* classification and tagging are set for every port on the557* interface. The number of ports on the interface must already558* have been probed.559*560* @interface: Interface to setup IPD/PIP for561*562* Returns Zero on success, negative on failure563*/564static int __cvmx_helper_interface_setup_ipd(int interface)565{566int ipd_port = cvmx_helper_get_ipd_port(interface, 0);567int num_ports = interface_port_count[interface];568569while (num_ports--) {570__cvmx_helper_port_setup_ipd(ipd_port);571ipd_port++;572}573return 0;574}575576/**577* Setup global setting for IPD/PIP not related to a specific578* interface or port. This must be called before IPD is enabled.579*580* Returns Zero on success, negative on failure.581*/582static int __cvmx_helper_global_setup_ipd(void)583{584/* Setup the global packet input options */585cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,586CVMX_HELPER_FIRST_MBUFF_SKIP / 8,587CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8,588/* The +8 is to account for the next ptr */589(CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,590/* The +8 is to account for the next ptr */591(CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128,592CVMX_FPA_WQE_POOL,593CVMX_IPD_OPC_MODE_STT,594CVMX_HELPER_ENABLE_BACK_PRESSURE);595return 0;596}597598/**599* Setup the PKO for the ports on an interface. The number of600* queues per port and the priority of each PKO output queue601* is set here. PKO must be disabled when this function is called.602*603* @interface: Interface to setup PKO for604*605* Returns Zero on success, negative on failure606*/607static int __cvmx_helper_interface_setup_pko(int interface)608{609/*610* Each packet output queue has an associated priority. The611* higher the priority, the more often it can send a packet. A612* priority of 8 means it can send in all 8 rounds of613* contention. We're going to make each queue one less than614* the last. The vector of priorities has been extended to615* support CN5xxx CPUs, where up to 16 queues can be616* associated to a port. To keep backward compatibility we617* don't change the initial 8 priorities and replicate them in618* the second half. With per-core PKO queues (PKO lockless619* operation) all queues have the same priority.620*/621uint64_t priorities[16] =622{ 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };623624/*625* Setup the IPD/PIP and PKO for the ports discovered626* above. Here packet classification, tagging and output627* priorities are set.628*/629int ipd_port = cvmx_helper_get_ipd_port(interface, 0);630int num_ports = interface_port_count[interface];631while (num_ports--) {632cvmx_pko_config_port(ipd_port,633cvmx_pko_get_base_queue_per_core(ipd_port,6340),635cvmx_pko_get_num_queues(ipd_port),636priorities);637ipd_port++;638}639return 0;640}641642/**643* Setup global setting for PKO not related to a specific644* interface or port. This must be called before PKO is enabled.645*646* Returns Zero on success, negative on failure.647*/648static int __cvmx_helper_global_setup_pko(void)649{650/*651* Disable tagwait FAU timeout. This needs to be done before652* anyone might start packet output using tags.653*/654union cvmx_iob_fau_timeout fau_to;655fau_to.u64 = 0;656fau_to.s.tout_val = 0xfff;657fau_to.s.tout_enb = 0;658cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);659660if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {661union cvmx_pko_reg_min_pkt min_pkt;662663min_pkt.u64 = 0;664min_pkt.s.size1 = 59;665min_pkt.s.size2 = 59;666min_pkt.s.size3 = 59;667min_pkt.s.size4 = 59;668min_pkt.s.size5 = 59;669min_pkt.s.size6 = 59;670min_pkt.s.size7 = 59;671cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64);672}673674return 0;675}676677/**678* Setup global backpressure setting.679*680* Returns Zero on success, negative on failure681*/682static int __cvmx_helper_global_setup_backpressure(void)683{684#if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE685/* Disable backpressure if configured to do so */686/* Disable backpressure (pause frame) generation */687int num_interfaces = cvmx_helper_get_number_of_interfaces();688int interface;689for (interface = 0; interface < num_interfaces; interface++) {690switch (cvmx_helper_interface_get_mode(interface)) {691case CVMX_HELPER_INTERFACE_MODE_DISABLED:692case CVMX_HELPER_INTERFACE_MODE_PCIE:693case CVMX_HELPER_INTERFACE_MODE_NPI:694case CVMX_HELPER_INTERFACE_MODE_LOOP:695case CVMX_HELPER_INTERFACE_MODE_XAUI:696break;697case CVMX_HELPER_INTERFACE_MODE_RGMII:698case CVMX_HELPER_INTERFACE_MODE_GMII:699case CVMX_HELPER_INTERFACE_MODE_SPI:700case CVMX_HELPER_INTERFACE_MODE_SGMII:701case CVMX_HELPER_INTERFACE_MODE_PICMG:702cvmx_gmx_set_backpressure_override(interface, 0xf);703break;704}705}706#endif707708return 0;709}710711/**712* Enable packet input/output from the hardware. This function is713* called after all internal setup is complete and IPD is enabled.714* After this function completes, packets will be accepted from the715* hardware ports. PKO should still be disabled to make sure packets716* aren't sent out partially setup hardware.717*718* @interface: Interface to enable719*720* Returns Zero on success, negative on failure721*/722static int __cvmx_helper_packet_hardware_enable(int interface)723{724int result = 0;725switch (cvmx_helper_interface_get_mode(interface)) {726/* These types don't support ports to IPD/PKO */727case CVMX_HELPER_INTERFACE_MODE_DISABLED:728case CVMX_HELPER_INTERFACE_MODE_PCIE:729/* Nothing to do */730break;731/* XAUI is a single high speed port */732case CVMX_HELPER_INTERFACE_MODE_XAUI:733result = __cvmx_helper_xaui_enable(interface);734break;735/*736* RGMII/GMII/MII are all treated about the same. Most737* functions refer to these ports as RGMII738*/739case CVMX_HELPER_INTERFACE_MODE_RGMII:740case CVMX_HELPER_INTERFACE_MODE_GMII:741result = __cvmx_helper_rgmii_enable(interface);742break;743/*744* SPI4 can have 1-16 ports depending on the device at745* the other end746*/747case CVMX_HELPER_INTERFACE_MODE_SPI:748result = __cvmx_helper_spi_enable(interface);749break;750/*751* SGMII can have 1-4 ports depending on how many are752* hooked up753*/754case CVMX_HELPER_INTERFACE_MODE_SGMII:755case CVMX_HELPER_INTERFACE_MODE_PICMG:756result = __cvmx_helper_sgmii_enable(interface);757break;758/* PCI target Network Packet Interface */759case CVMX_HELPER_INTERFACE_MODE_NPI:760result = __cvmx_helper_npi_enable(interface);761break;762/*763* Special loopback only ports. These are not the same764* as other ports in loopback mode765*/766case CVMX_HELPER_INTERFACE_MODE_LOOP:767result = __cvmx_helper_loop_enable(interface);768break;769}770return result;771}772773/**774* Function to adjust internal IPD pointer alignments775*776* Returns 0 on success777* !0 on failure778*/779static int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)780{781#define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \782(CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)783#define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \784(CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)785#define FIX_IPD_OUTPORT 0786/* Ports 0-15 are interface 0, 16-31 are interface 1 */787#define INTERFACE(port) (port >> 4)788#define INDEX(port) (port & 0xf)789uint64_t *p64;790union cvmx_pko_command_word0 pko_command;791union cvmx_buf_ptr g_buffer, pkt_buffer;792struct cvmx_wqe *work;793int size, num_segs = 0, wqe_pcnt, pkt_pcnt;794union cvmx_gmxx_prtx_cfg gmx_cfg;795int retry_cnt;796int retry_loop_cnt;797int i;798799/* Save values for restore at end */800uint64_t prtx_cfg =801cvmx_read_csr(CVMX_GMXX_PRTX_CFG802(INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));803uint64_t tx_ptr_en =804cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));805uint64_t rx_ptr_en =806cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));807uint64_t rxx_jabber =808cvmx_read_csr(CVMX_GMXX_RXX_JABBER809(INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));810uint64_t frame_max =811cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX812(INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));813814/* Configure port to gig FDX as required for loopback mode */815cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);816817/*818* Disable reception on all ports so if traffic is present it819* will not interfere.820*/821cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);822823__delay(100000000ull);824825for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {826retry_cnt = 100000;827wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);828pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;829wqe_pcnt &= 0x7f;830831num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;832833if (num_segs == 0)834goto fix_ipd_exit;835836num_segs += 1;837838size =839FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +840((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -841(FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);842843cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),8441 << INDEX(FIX_IPD_OUTPORT));845CVMX_SYNC;846847g_buffer.u64 = 0;848g_buffer.s.addr =849cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));850if (g_buffer.s.addr == 0) {851cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "852"buffer allocation failure.\n");853goto fix_ipd_exit;854}855856g_buffer.s.pool = CVMX_FPA_WQE_POOL;857g_buffer.s.size = num_segs;858859pkt_buffer.u64 = 0;860pkt_buffer.s.addr =861cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));862if (pkt_buffer.s.addr == 0) {863cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "864"buffer allocation failure.\n");865goto fix_ipd_exit;866}867pkt_buffer.s.i = 1;868pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;869pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;870871p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);872p64[0] = 0xffffffffffff0000ull;873p64[1] = 0x08004510ull;874p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;875p64[3] = 0x3a5fc0a81073c0a8ull;876877for (i = 0; i < num_segs; i++) {878if (i > 0)879pkt_buffer.s.size =880FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;881882if (i == (num_segs - 1))883pkt_buffer.s.i = 0;884885*(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +8868 * i) = pkt_buffer.u64;887}888889/* Build the PKO command */890pko_command.u64 = 0;891pko_command.s.segs = num_segs;892pko_command.s.total_bytes = size;893pko_command.s.dontfree = 0;894pko_command.s.gather = 1;895896gmx_cfg.u64 =897cvmx_read_csr(CVMX_GMXX_PRTX_CFG898(INDEX(FIX_IPD_OUTPORT),899INTERFACE(FIX_IPD_OUTPORT)));900gmx_cfg.s.en = 1;901cvmx_write_csr(CVMX_GMXX_PRTX_CFG902(INDEX(FIX_IPD_OUTPORT),903INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);904cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),9051 << INDEX(FIX_IPD_OUTPORT));906cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),9071 << INDEX(FIX_IPD_OUTPORT));908909cvmx_write_csr(CVMX_GMXX_RXX_JABBER910(INDEX(FIX_IPD_OUTPORT),911INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);912cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX913(INDEX(FIX_IPD_OUTPORT),914INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);915916cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,917cvmx_pko_get_base_queue918(FIX_IPD_OUTPORT),919CVMX_PKO_LOCK_CMD_QUEUE);920cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,921cvmx_pko_get_base_queue922(FIX_IPD_OUTPORT), pko_command,923g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);924925CVMX_SYNC;926927do {928work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);929retry_cnt--;930} while ((work == NULL) && (retry_cnt > 0));931932if (!retry_cnt)933cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "934"get_work() timeout occurred.\n");935936/* Free packet */937if (work)938cvmx_helper_free_packet_data(work);939}940941fix_ipd_exit:942943/* Return CSR configs to saved values */944cvmx_write_csr(CVMX_GMXX_PRTX_CFG945(INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),946prtx_cfg);947cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),948tx_ptr_en);949cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),950rx_ptr_en);951cvmx_write_csr(CVMX_GMXX_RXX_JABBER952(INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),953rxx_jabber);954cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX955(INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),956frame_max);957cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);958959CVMX_SYNC;960if (num_segs)961cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");962963return !!num_segs;964965}966967/**968* Called after all internal packet IO paths are setup. This969* function enables IPD/PIP and begins packet input and output.970*971* Returns Zero on success, negative on failure972*/973int cvmx_helper_ipd_and_packet_input_enable(void)974{975int num_interfaces;976int interface;977978/* Enable IPD */979cvmx_ipd_enable();980981/*982* Time to enable hardware ports packet input and output. Note983* that at this point IPD/PIP must be fully functional and PKO984* must be disabled985*/986num_interfaces = cvmx_helper_get_number_of_interfaces();987for (interface = 0; interface < num_interfaces; interface++) {988if (cvmx_helper_ports_on_interface(interface) > 0)989__cvmx_helper_packet_hardware_enable(interface);990}991992/* Finally enable PKO now that the entire path is up and running */993cvmx_pko_enable();994995if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)996|| OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))997&& (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))998__cvmx_helper_errata_fix_ipd_ptr_alignment();999return 0;1000}1001EXPORT_SYMBOL_GPL(cvmx_helper_ipd_and_packet_input_enable);10021003/**1004* Initialize the PIP, IPD, and PKO hardware to support1005* simple priority based queues for the ethernet ports. Each1006* port is configured with a number of priority queues based1007* on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower1008* priority than the previous.1009*1010* Returns Zero on success, non-zero on failure1011*/1012int cvmx_helper_initialize_packet_io_global(void)1013{1014int result = 0;1015int interface;1016union cvmx_l2c_cfg l2c_cfg;1017const int num_interfaces = cvmx_helper_get_number_of_interfaces();10181019/*1020* CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to1021* be disabled.1022*/1023if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))1024__cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);10251026/*1027* Tell L2 to give the IOB statically higher priority compared1028* to the cores. This avoids conditions where IO blocks might1029* be starved under very high L2 loads.1030*/1031l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);1032l2c_cfg.s.lrf_arb_mode = 0;1033l2c_cfg.s.rfb_arb_mode = 0;1034cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);10351036cvmx_pko_initialize_global();1037for (interface = 0; interface < num_interfaces; interface++) {1038result |= cvmx_helper_interface_probe(interface);1039if (cvmx_helper_ports_on_interface(interface) > 0)1040cvmx_dprintf("Interface %d has %d ports (%s)\n",1041interface,1042cvmx_helper_ports_on_interface(interface),1043cvmx_helper_interface_mode_to_string1044(cvmx_helper_interface_get_mode1045(interface)));1046result |= __cvmx_helper_interface_setup_ipd(interface);1047result |= __cvmx_helper_interface_setup_pko(interface);1048}10491050result |= __cvmx_helper_global_setup_ipd();1051result |= __cvmx_helper_global_setup_pko();10521053/* Enable any flow control and backpressure */1054result |= __cvmx_helper_global_setup_backpressure();10551056#if CVMX_HELPER_ENABLE_IPD1057result |= cvmx_helper_ipd_and_packet_input_enable();1058#endif1059return result;1060}1061EXPORT_SYMBOL_GPL(cvmx_helper_initialize_packet_io_global);10621063/**1064* Return the link state of an IPD/PKO port as returned by1065* auto negotiation. The result of this function may not match1066* Octeon's link config if auto negotiation has changed since1067* the last call to cvmx_helper_link_set().1068*1069* @ipd_port: IPD/PKO port to query1070*1071* Returns Link state1072*/1073union cvmx_helper_link_info cvmx_helper_link_get(int ipd_port)1074{1075union cvmx_helper_link_info result;1076int interface = cvmx_helper_get_interface_num(ipd_port);1077int index = cvmx_helper_get_interface_index_num(ipd_port);10781079/* The default result will be a down link unless the code below1080changes it */1081result.u64 = 0;10821083if (index >= cvmx_helper_ports_on_interface(interface))1084return result;10851086switch (cvmx_helper_interface_get_mode(interface)) {1087case CVMX_HELPER_INTERFACE_MODE_DISABLED:1088case CVMX_HELPER_INTERFACE_MODE_PCIE:1089/* Network links are not supported */1090break;1091case CVMX_HELPER_INTERFACE_MODE_XAUI:1092result = __cvmx_helper_xaui_link_get(ipd_port);1093break;1094case CVMX_HELPER_INTERFACE_MODE_GMII:1095if (index == 0)1096result = __cvmx_helper_rgmii_link_get(ipd_port);1097else {1098WARN_ONCE(1, "Using deprecated link status - please update your DT");1099result.s.full_duplex = 1;1100result.s.link_up = 1;1101result.s.speed = 1000;1102}1103break;1104case CVMX_HELPER_INTERFACE_MODE_RGMII:1105result = __cvmx_helper_rgmii_link_get(ipd_port);1106break;1107case CVMX_HELPER_INTERFACE_MODE_SPI:1108result = __cvmx_helper_spi_link_get(ipd_port);1109break;1110case CVMX_HELPER_INTERFACE_MODE_SGMII:1111case CVMX_HELPER_INTERFACE_MODE_PICMG:1112result = __cvmx_helper_sgmii_link_get(ipd_port);1113break;1114case CVMX_HELPER_INTERFACE_MODE_NPI:1115case CVMX_HELPER_INTERFACE_MODE_LOOP:1116/* Network links are not supported */1117break;1118}1119return result;1120}1121EXPORT_SYMBOL_GPL(cvmx_helper_link_get);11221123/**1124* Configure an IPD/PKO port for the specified link state. This1125* function does not influence auto negotiation at the PHY level.1126* The passed link state must always match the link state returned1127* by cvmx_helper_link_get().1128*1129* @ipd_port: IPD/PKO port to configure1130* @link_info: The new link state1131*1132* Returns Zero on success, negative on failure1133*/1134int cvmx_helper_link_set(int ipd_port, union cvmx_helper_link_info link_info)1135{1136int result = -1;1137int interface = cvmx_helper_get_interface_num(ipd_port);1138int index = cvmx_helper_get_interface_index_num(ipd_port);11391140if (index >= cvmx_helper_ports_on_interface(interface))1141return -1;11421143switch (cvmx_helper_interface_get_mode(interface)) {1144case CVMX_HELPER_INTERFACE_MODE_DISABLED:1145case CVMX_HELPER_INTERFACE_MODE_PCIE:1146break;1147case CVMX_HELPER_INTERFACE_MODE_XAUI:1148result = __cvmx_helper_xaui_link_set(ipd_port, link_info);1149break;1150/*1151* RGMII/GMII/MII are all treated about the same. Most1152* functions refer to these ports as RGMII.1153*/1154case CVMX_HELPER_INTERFACE_MODE_RGMII:1155case CVMX_HELPER_INTERFACE_MODE_GMII:1156result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);1157break;1158case CVMX_HELPER_INTERFACE_MODE_SPI:1159result = __cvmx_helper_spi_link_set(ipd_port, link_info);1160break;1161case CVMX_HELPER_INTERFACE_MODE_SGMII:1162case CVMX_HELPER_INTERFACE_MODE_PICMG:1163result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);1164break;1165case CVMX_HELPER_INTERFACE_MODE_NPI:1166case CVMX_HELPER_INTERFACE_MODE_LOOP:1167break;1168}1169return result;1170}1171EXPORT_SYMBOL_GPL(cvmx_helper_link_set);117211731174