0001
0002
0003
0004
0005
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
0112 rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
0113 if (rsl_int_blocks.s.spx1)
0114 return_status = cvm_oct_spi_spx_int(1);
0115
0116 if (rsl_int_blocks.s.spx0)
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
0169
0170
0171
0172
0173
0174
0175 if (priv->port == spi4000_port) {
0176
0177
0178
0179
0180 cvmx_spi4000_check_speed(interface, priv->port);
0181
0182
0183
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 }