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

Cache object: 6dc6c723b8730880396930c34b83efef


[ 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.