The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mips/cavium/octe/ethernet-spi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*************************************************************************
    2 SPDX-License-Identifier: BSD-3-Clause
    3 
    4 Copyright (c) 2003-2007  Cavium Networks (support@cavium.com). All rights
    5 reserved.
    6 
    7 
    8 Redistribution and use in source and binary forms, with or without
    9 modification, are permitted provided that the following conditions are
   10 met:
   11 
   12     * Redistributions of source code must retain the above copyright
   13       notice, this list of conditions and the following disclaimer.
   14 
   15     * Redistributions in binary form must reproduce the above
   16       copyright notice, this list of conditions and the following
   17       disclaimer in the documentation and/or other materials provided
   18       with the distribution.
   19 
   20     * Neither the name of Cavium Networks nor the names of
   21       its contributors may be used to endorse or promote products
   22       derived from this software without specific prior written
   23       permission.
   24 
   25 This Software, including technical data, may be subject to U.S. export  control laws, including the U.S. Export Administration Act and its  associated regulations, and may be subject to export or import  regulations in other countries.
   26 
   27 TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
   28 AND WITH ALL FAULTS AND CAVIUM  NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
   29 
   30 *************************************************************************/
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/bus.h>
   38 #include <sys/endian.h>
   39 #include <sys/kernel.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/rman.h>
   42 #include <sys/socket.h>
   43 
   44 #include <net/ethernet.h>
   45 #include <net/if.h>
   46 #include <net/if_var.h>
   47 
   48 #include "wrapper-cvmx-includes.h"
   49 #include "ethernet-headers.h"
   50 
   51 #include "octebusvar.h"
   52 
   53 static int number_spi_ports;
   54 static int need_retrain[2] = {0, 0};
   55 
   56 static int cvm_oct_spi_rml_interrupt(void *dev_id)
   57 {
   58         int return_status = FILTER_STRAY;
   59         cvmx_npi_rsl_int_blocks_t rsl_int_blocks;
   60 
   61         /* Check and see if this interrupt was caused by the GMX block */
   62         rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
   63         if (rsl_int_blocks.s.spx1) { /* 19 - SPX1_INT_REG & STX1_INT_REG */
   64 
   65                 cvmx_spxx_int_reg_t spx_int_reg;
   66                 cvmx_stxx_int_reg_t stx_int_reg;
   67 
   68                 spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(1));
   69                 cvmx_write_csr(CVMX_SPXX_INT_REG(1), spx_int_reg.u64);
   70                 if (!need_retrain[1]) {
   71 
   72                         spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(1));
   73                         if (spx_int_reg.s.spf)
   74                                 printf("SPI1: SRX Spi4 interface down\n");
   75                         if (spx_int_reg.s.calerr)
   76                                 printf("SPI1: SRX Spi4 Calendar table parity error\n");
   77                         if (spx_int_reg.s.syncerr)
   78                                 printf("SPI1: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n");
   79                         if (spx_int_reg.s.diperr)
   80                                 printf("SPI1: SRX Spi4 DIP4 error\n");
   81                         if (spx_int_reg.s.tpaovr)
   82                                 printf("SPI1: SRX Selected port has hit TPA overflow\n");
   83                         if (spx_int_reg.s.rsverr)
   84                                 printf("SPI1: SRX Spi4 reserved control word detected\n");
   85                         if (spx_int_reg.s.drwnng)
   86                                 printf("SPI1: SRX Spi4 receive FIFO drowning/overflow\n");
   87                         if (spx_int_reg.s.clserr)
   88                                 printf("SPI1: SRX Spi4 packet closed on non-16B alignment without EOP\n");
   89                         if (spx_int_reg.s.spiovr)
   90                                 printf("SPI1: SRX Spi4 async FIFO overflow\n");
   91                         if (spx_int_reg.s.abnorm)
   92                                 printf("SPI1: SRX Abnormal packet termination (ERR bit)\n");
   93                         if (spx_int_reg.s.prtnxa)
   94                                 printf("SPI1: SRX Port out of range\n");
   95                 }
   96 
   97                 stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(1));
   98                 cvmx_write_csr(CVMX_STXX_INT_REG(1), stx_int_reg.u64);
   99                 if (!need_retrain[1]) {
  100 
  101                         stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(1));
  102                         if (stx_int_reg.s.syncerr)
  103                                 printf("SPI1: STX Interface encountered a fatal error\n");
  104                         if (stx_int_reg.s.frmerr)
  105                                 printf("SPI1: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n");
  106                         if (stx_int_reg.s.unxfrm)
  107                                 printf("SPI1: STX Unexpected framing sequence\n");
  108                         if (stx_int_reg.s.nosync)
  109                                 printf("SPI1: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n");
  110                         if (stx_int_reg.s.diperr)
  111                                 printf("SPI1: STX DIP2 error on the Spi4 Status channel\n");
  112                         if (stx_int_reg.s.datovr)
  113                                 printf("SPI1: STX Spi4 FIFO overflow error\n");
  114                         if (stx_int_reg.s.ovrbst)
  115                                 printf("SPI1: STX Transmit packet burst too big\n");
  116                         if (stx_int_reg.s.calpar1)
  117                                 printf("SPI1: STX Calendar Table Parity Error Bank1\n");
  118                         if (stx_int_reg.s.calpar0)
  119                                 printf("SPI1: STX Calendar Table Parity Error Bank0\n");
  120                 }
  121 
  122                 cvmx_write_csr(CVMX_SPXX_INT_MSK(1), 0);
  123                 cvmx_write_csr(CVMX_STXX_INT_MSK(1), 0);
  124                 need_retrain[1] = 1;
  125                 return_status = FILTER_HANDLED;
  126         }
  127 
  128         if (rsl_int_blocks.s.spx0) { /* 18 - SPX0_INT_REG & STX0_INT_REG */
  129                 cvmx_spxx_int_reg_t spx_int_reg;
  130                 cvmx_stxx_int_reg_t stx_int_reg;
  131 
  132                 spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(0));
  133                 cvmx_write_csr(CVMX_SPXX_INT_REG(0), spx_int_reg.u64);
  134                 if (!need_retrain[0]) {
  135 
  136                         spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(0));
  137                         if (spx_int_reg.s.spf)
  138                                 printf("SPI0: SRX Spi4 interface down\n");
  139                         if (spx_int_reg.s.calerr)
  140                                 printf("SPI0: SRX Spi4 Calendar table parity error\n");
  141                         if (spx_int_reg.s.syncerr)
  142                                 printf("SPI0: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n");
  143                         if (spx_int_reg.s.diperr)
  144                                 printf("SPI0: SRX Spi4 DIP4 error\n");
  145                         if (spx_int_reg.s.tpaovr)
  146                                 printf("SPI0: SRX Selected port has hit TPA overflow\n");
  147                         if (spx_int_reg.s.rsverr)
  148                                 printf("SPI0: SRX Spi4 reserved control word detected\n");
  149                         if (spx_int_reg.s.drwnng)
  150                                 printf("SPI0: SRX Spi4 receive FIFO drowning/overflow\n");
  151                         if (spx_int_reg.s.clserr)
  152                                 printf("SPI0: SRX Spi4 packet closed on non-16B alignment without EOP\n");
  153                         if (spx_int_reg.s.spiovr)
  154                                 printf("SPI0: SRX Spi4 async FIFO overflow\n");
  155                         if (spx_int_reg.s.abnorm)
  156                                 printf("SPI0: SRX Abnormal packet termination (ERR bit)\n");
  157                         if (spx_int_reg.s.prtnxa)
  158                                 printf("SPI0: SRX Port out of range\n");
  159                 }
  160 
  161                 stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(0));
  162                 cvmx_write_csr(CVMX_STXX_INT_REG(0), stx_int_reg.u64);
  163                 if (!need_retrain[0]) {
  164 
  165                         stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(0));
  166                         if (stx_int_reg.s.syncerr)
  167                                 printf("SPI0: STX Interface encountered a fatal error\n");
  168                         if (stx_int_reg.s.frmerr)
  169                                 printf("SPI0: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n");
  170                         if (stx_int_reg.s.unxfrm)
  171                                 printf("SPI0: STX Unexpected framing sequence\n");
  172                         if (stx_int_reg.s.nosync)
  173                                 printf("SPI0: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n");
  174                         if (stx_int_reg.s.diperr)
  175                                 printf("SPI0: STX DIP2 error on the Spi4 Status channel\n");
  176                         if (stx_int_reg.s.datovr)
  177                                 printf("SPI0: STX Spi4 FIFO overflow error\n");
  178                         if (stx_int_reg.s.ovrbst)
  179                                 printf("SPI0: STX Transmit packet burst too big\n");
  180                         if (stx_int_reg.s.calpar1)
  181                                 printf("SPI0: STX Calendar Table Parity Error Bank1\n");
  182                         if (stx_int_reg.s.calpar0)
  183                                 printf("SPI0: STX Calendar Table Parity Error Bank0\n");
  184                 }
  185 
  186                 cvmx_write_csr(CVMX_SPXX_INT_MSK(0), 0);
  187                 cvmx_write_csr(CVMX_STXX_INT_MSK(0), 0);
  188                 need_retrain[0] = 1;
  189                 return_status = FILTER_HANDLED;
  190         }
  191 
  192         return return_status;
  193 }
  194 
  195 static void cvm_oct_spi_enable_error_reporting(int interface)
  196 {
  197         cvmx_spxx_int_msk_t spxx_int_msk;
  198         cvmx_stxx_int_msk_t stxx_int_msk;
  199 
  200         spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface));
  201         spxx_int_msk.s.calerr = 1;
  202         spxx_int_msk.s.syncerr = 1;
  203         spxx_int_msk.s.diperr = 1;
  204         spxx_int_msk.s.tpaovr = 1;
  205         spxx_int_msk.s.rsverr = 1;
  206         spxx_int_msk.s.drwnng = 1;
  207         spxx_int_msk.s.clserr = 1;
  208         spxx_int_msk.s.spiovr = 1;
  209         spxx_int_msk.s.abnorm = 1;
  210         spxx_int_msk.s.prtnxa = 1;
  211         cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64);
  212 
  213         stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface));
  214         stxx_int_msk.s.frmerr = 1;
  215         stxx_int_msk.s.unxfrm = 1;
  216         stxx_int_msk.s.nosync = 1;
  217         stxx_int_msk.s.diperr = 1;
  218         stxx_int_msk.s.datovr = 1;
  219         stxx_int_msk.s.ovrbst = 1;
  220         stxx_int_msk.s.calpar1 = 1;
  221         stxx_int_msk.s.calpar0 = 1;
  222         cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64);
  223 }
  224 
  225 static void cvm_oct_spi_poll(struct ifnet *ifp)
  226 {
  227         static int spi4000_port;
  228         cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
  229         int interface;
  230 
  231         for (interface = 0; interface < 2; interface++) {
  232 
  233                 if ((priv->port == interface*16) && need_retrain[interface]) {
  234 
  235                         if (cvmx_spi_restart_interface(interface, CVMX_SPI_MODE_DUPLEX, 10) == 0) {
  236                                 need_retrain[interface] = 0;
  237                                 cvm_oct_spi_enable_error_reporting(interface);
  238                         }
  239                 }
  240 
  241                 /* The SPI4000 TWSI interface is very slow. In order not to
  242                    bring the system to a crawl, we only poll a single port
  243                    every second. This means negotiation speed changes
  244                    take up to 10 seconds, but at least we don't waste
  245                    absurd amounts of time waiting for TWSI */
  246                 if (priv->port == spi4000_port) {
  247                         /* This function does nothing if it is called on an
  248                            interface without a SPI4000 */
  249                         cvmx_spi4000_check_speed(interface, priv->port);
  250                         /* Normal ordering increments. By decrementing
  251                            we only match once per iteration */
  252                         spi4000_port--;
  253                         if (spi4000_port < 0)
  254                                 spi4000_port = 10;
  255                 }
  256         }
  257 }
  258 
  259 
  260 int cvm_oct_spi_init(struct ifnet *ifp)
  261 {
  262         struct octebus_softc *sc;
  263         cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
  264         int error;
  265         int rid;
  266 
  267         if (number_spi_ports == 0) {
  268                 sc = device_get_softc(device_get_parent(priv->dev));
  269 
  270                 rid = 0;
  271                 sc->sc_spi_irq = bus_alloc_resource(sc->sc_dev, SYS_RES_IRQ,
  272                                                     &rid, OCTEON_IRQ_RML,
  273                                                     OCTEON_IRQ_RML, 1,
  274                                                     RF_ACTIVE);
  275                 if (sc->sc_spi_irq == NULL) {
  276                         device_printf(sc->sc_dev, "could not allocate SPI irq");
  277                         return ENXIO;
  278                 }
  279 
  280                 error = bus_setup_intr(sc->sc_dev, sc->sc_spi_irq,
  281                                        INTR_TYPE_NET | INTR_MPSAFE,
  282                                        cvm_oct_spi_rml_interrupt, NULL,
  283                                        &number_spi_ports, NULL);
  284                 if (error != 0) {
  285                         device_printf(sc->sc_dev, "could not setup SPI irq");
  286                         return error;
  287                 }
  288         }
  289         number_spi_ports++;
  290 
  291         if ((priv->port == 0) || (priv->port == 16)) {
  292                 cvm_oct_spi_enable_error_reporting(INTERFACE(priv->port));
  293                 priv->poll = cvm_oct_spi_poll;
  294         }
  295         if (cvm_oct_common_init(ifp) != 0)
  296             return ENXIO;
  297         return 0;
  298 }
  299 
  300 void cvm_oct_spi_uninit(struct ifnet *ifp)
  301 {
  302         int interface;
  303 
  304         cvm_oct_common_uninit(ifp);
  305         number_spi_ports--;
  306         if (number_spi_ports == 0) {
  307                 for (interface = 0; interface < 2; interface++) {
  308                         cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0);
  309                         cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0);
  310                 }
  311                 panic("%s: IRQ release not yet implemented.", __func__);
  312         }
  313 }

Cache object: ff1b7d65e86abd55ee73370a236e618e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.