Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * This file is based on code from OCTEON SDK by Cavium Networks.
0004  *
0005  * Copyright (c) 2003-2007 Cavium Networks
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/netdevice.h>
0010 #include <linux/interrupt.h>
0011 #include <net/dst.h>
0012 
0013 #include "octeon-ethernet.h"
0014 #include "ethernet-defines.h"
0015 #include "ethernet-util.h"
0016 
0017 static int number_spi_ports;
0018 static int need_retrain[2] = { 0, 0 };
0019 
0020 static void cvm_oct_spxx_int_pr(union cvmx_spxx_int_reg spx_int_reg, int index)
0021 {
0022     if (spx_int_reg.s.spf)
0023         pr_err("SPI%d: SRX Spi4 interface down\n", index);
0024     if (spx_int_reg.s.calerr)
0025         pr_err("SPI%d: SRX Spi4 Calendar table parity error\n", index);
0026     if (spx_int_reg.s.syncerr)
0027         pr_err("SPI%d: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n",
0028                index);
0029     if (spx_int_reg.s.diperr)
0030         pr_err("SPI%d: SRX Spi4 DIP4 error\n", index);
0031     if (spx_int_reg.s.tpaovr)
0032         pr_err("SPI%d: SRX Selected port has hit TPA overflow\n",
0033                index);
0034     if (spx_int_reg.s.rsverr)
0035         pr_err("SPI%d: SRX Spi4 reserved control word detected\n",
0036                index);
0037     if (spx_int_reg.s.drwnng)
0038         pr_err("SPI%d: SRX Spi4 receive FIFO drowning/overflow\n",
0039                index);
0040     if (spx_int_reg.s.clserr)
0041         pr_err("SPI%d: SRX Spi4 packet closed on non-16B alignment without EOP\n",
0042                index);
0043     if (spx_int_reg.s.spiovr)
0044         pr_err("SPI%d: SRX Spi4 async FIFO overflow\n", index);
0045     if (spx_int_reg.s.abnorm)
0046         pr_err("SPI%d: SRX Abnormal packet termination (ERR bit)\n",
0047                index);
0048     if (spx_int_reg.s.prtnxa)
0049         pr_err("SPI%d: SRX Port out of range\n", index);
0050 }
0051 
0052 static void cvm_oct_stxx_int_pr(union cvmx_stxx_int_reg stx_int_reg, int index)
0053 {
0054     if (stx_int_reg.s.syncerr)
0055         pr_err("SPI%d: STX Interface encountered a fatal error\n",
0056                index);
0057     if (stx_int_reg.s.frmerr)
0058         pr_err("SPI%d: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n",
0059                index);
0060     if (stx_int_reg.s.unxfrm)
0061         pr_err("SPI%d: STX Unexpected framing sequence\n", index);
0062     if (stx_int_reg.s.nosync)
0063         pr_err("SPI%d: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n",
0064                index);
0065     if (stx_int_reg.s.diperr)
0066         pr_err("SPI%d: STX DIP2 error on the Spi4 Status channel\n",
0067                index);
0068     if (stx_int_reg.s.datovr)
0069         pr_err("SPI%d: STX Spi4 FIFO overflow error\n", index);
0070     if (stx_int_reg.s.ovrbst)
0071         pr_err("SPI%d: STX Transmit packet burst too big\n", index);
0072     if (stx_int_reg.s.calpar1)
0073         pr_err("SPI%d: STX Calendar Table Parity Error Bank%d\n",
0074                index, 1);
0075     if (stx_int_reg.s.calpar0)
0076         pr_err("SPI%d: STX Calendar Table Parity Error Bank%d\n",
0077                index, 0);
0078 }
0079 
0080 static irqreturn_t cvm_oct_spi_spx_int(int index)
0081 {
0082     union cvmx_spxx_int_reg spx_int_reg;
0083     union cvmx_stxx_int_reg stx_int_reg;
0084 
0085     spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(index));
0086     cvmx_write_csr(CVMX_SPXX_INT_REG(index), spx_int_reg.u64);
0087     if (!need_retrain[index]) {
0088         spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(index));
0089         cvm_oct_spxx_int_pr(spx_int_reg, index);
0090     }
0091 
0092     stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(index));
0093     cvmx_write_csr(CVMX_STXX_INT_REG(index), stx_int_reg.u64);
0094     if (!need_retrain[index]) {
0095         stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(index));
0096         cvm_oct_stxx_int_pr(stx_int_reg, index);
0097     }
0098 
0099     cvmx_write_csr(CVMX_SPXX_INT_MSK(index), 0);
0100     cvmx_write_csr(CVMX_STXX_INT_MSK(index), 0);
0101     need_retrain[index] = 1;
0102 
0103     return IRQ_HANDLED;
0104 }
0105 
0106 static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id)
0107 {
0108     irqreturn_t return_status = IRQ_NONE;
0109     union cvmx_npi_rsl_int_blocks rsl_int_blocks;
0110 
0111     /* Check and see if this interrupt was caused by the GMX block */
0112     rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
0113     if (rsl_int_blocks.s.spx1) /* 19 - SPX1_INT_REG & STX1_INT_REG */
0114         return_status = cvm_oct_spi_spx_int(1);
0115 
0116     if (rsl_int_blocks.s.spx0) /* 18 - SPX0_INT_REG & STX0_INT_REG */
0117         return_status = cvm_oct_spi_spx_int(0);
0118 
0119     return return_status;
0120 }
0121 
0122 static void cvm_oct_spi_enable_error_reporting(int interface)
0123 {
0124     union cvmx_spxx_int_msk spxx_int_msk;
0125     union cvmx_stxx_int_msk stxx_int_msk;
0126 
0127     spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface));
0128     spxx_int_msk.s.calerr = 1;
0129     spxx_int_msk.s.syncerr = 1;
0130     spxx_int_msk.s.diperr = 1;
0131     spxx_int_msk.s.tpaovr = 1;
0132     spxx_int_msk.s.rsverr = 1;
0133     spxx_int_msk.s.drwnng = 1;
0134     spxx_int_msk.s.clserr = 1;
0135     spxx_int_msk.s.spiovr = 1;
0136     spxx_int_msk.s.abnorm = 1;
0137     spxx_int_msk.s.prtnxa = 1;
0138     cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64);
0139 
0140     stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface));
0141     stxx_int_msk.s.frmerr = 1;
0142     stxx_int_msk.s.unxfrm = 1;
0143     stxx_int_msk.s.nosync = 1;
0144     stxx_int_msk.s.diperr = 1;
0145     stxx_int_msk.s.datovr = 1;
0146     stxx_int_msk.s.ovrbst = 1;
0147     stxx_int_msk.s.calpar1 = 1;
0148     stxx_int_msk.s.calpar0 = 1;
0149     cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64);
0150 }
0151 
0152 static void cvm_oct_spi_poll(struct net_device *dev)
0153 {
0154     static int spi4000_port;
0155     struct octeon_ethernet *priv = netdev_priv(dev);
0156     int interface;
0157 
0158     for (interface = 0; interface < 2; interface++) {
0159         if ((priv->port == interface * 16) && need_retrain[interface]) {
0160             if (cvmx_spi_restart_interface
0161                 (interface, CVMX_SPI_MODE_DUPLEX, 10) == 0) {
0162                 need_retrain[interface] = 0;
0163                 cvm_oct_spi_enable_error_reporting(interface);
0164             }
0165         }
0166 
0167         /*
0168          * The SPI4000 TWSI interface is very slow. In order
0169          * not to bring the system to a crawl, we only poll a
0170          * single port every second. This means negotiation
0171          * speed changes take up to 10 seconds, but at least
0172          * we don't waste absurd amounts of time waiting for
0173          * TWSI.
0174          */
0175         if (priv->port == spi4000_port) {
0176             /*
0177              * This function does nothing if it is called on an
0178              * interface without a SPI4000.
0179              */
0180             cvmx_spi4000_check_speed(interface, priv->port);
0181             /*
0182              * Normal ordering increments. By decrementing
0183              * we only match once per iteration.
0184              */
0185             spi4000_port--;
0186             if (spi4000_port < 0)
0187                 spi4000_port = 10;
0188         }
0189     }
0190 }
0191 
0192 int cvm_oct_spi_init(struct net_device *dev)
0193 {
0194     int r;
0195     struct octeon_ethernet *priv = netdev_priv(dev);
0196 
0197     if (number_spi_ports == 0) {
0198         r = request_irq(OCTEON_IRQ_RML, cvm_oct_spi_rml_interrupt,
0199                 IRQF_SHARED, "SPI", &number_spi_ports);
0200         if (r)
0201             return r;
0202     }
0203     number_spi_ports++;
0204 
0205     if (priv->port == 0 || priv->port == 16) {
0206         cvm_oct_spi_enable_error_reporting(INTERFACE(priv->port));
0207         priv->poll = cvm_oct_spi_poll;
0208     }
0209     cvm_oct_common_init(dev);
0210     return 0;
0211 }
0212 
0213 void cvm_oct_spi_uninit(struct net_device *dev)
0214 {
0215     int interface;
0216 
0217     cvm_oct_common_uninit(dev);
0218     number_spi_ports--;
0219     if (number_spi_ports == 0) {
0220         for (interface = 0; interface < 2; interface++) {
0221             cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0);
0222             cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0);
0223         }
0224         free_irq(OCTEON_IRQ_RML, &number_spi_ports);
0225     }
0226 }