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

Cache object: 882ef462238403df2e61003bd8633ed6


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