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/octopci.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD: releng/8.4/sys/mips/cavium/octopci.c 230714 2012-01-29 01:22:48Z marius $
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/8.4/sys/mips/cavium/octopci.c 230714 2012-01-29 01:22:48Z marius $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 
   35 #include <sys/bus.h>
   36 #include <sys/endian.h>
   37 #include <sys/interrupt.h>
   38 #include <sys/malloc.h>
   39 #include <sys/kernel.h>
   40 #include <sys/module.h>
   41 #include <sys/rman.h>
   42 
   43 #include <vm/vm.h>
   44 #include <vm/pmap.h>
   45 #include <vm/vm_extern.h>
   46 
   47 #include <machine/bus.h>
   48 #include <machine/cpu.h>
   49 #include <machine/pmap.h>
   50 
   51 #include <contrib/octeon-sdk/cvmx.h>
   52 #include <contrib/octeon-sdk/cvmx-interrupt.h>
   53 
   54 #include <dev/pci/pcireg.h>
   55 #include <dev/pci/pcivar.h>
   56 
   57 #include <dev/pci/pcib_private.h>
   58 
   59 #include <mips/cavium/octopcireg.h>
   60 #include <mips/cavium/octopcivar.h>
   61 
   62 #include "pcib_if.h"
   63 
   64 #define NPI_WRITE(addr, value)  cvmx_write64_uint32((addr) ^ 4, (value))
   65 #define NPI_READ(addr)          cvmx_read64_uint32((addr) ^ 4)
   66 
   67 struct octopci_softc {
   68         device_t sc_dev;
   69 
   70         unsigned sc_domain;
   71         unsigned sc_bus;
   72 
   73         unsigned sc_io_next;
   74         struct rman sc_io;
   75 
   76         unsigned sc_mem1_next;
   77         struct rman sc_mem1;
   78 };
   79 
   80 static void             octopci_identify(driver_t *, device_t);
   81 static int              octopci_probe(device_t);
   82 static int              octopci_attach(device_t);
   83 static int              octopci_read_ivar(device_t, device_t, int,
   84                                           uintptr_t *);
   85 static struct resource  *octopci_alloc_resource(device_t, device_t, int, int *,
   86                                                 u_long, u_long, u_long, u_int);
   87 static int              octopci_activate_resource(device_t, device_t, int, int,
   88                                                   struct resource *);
   89 static int      octopci_maxslots(device_t);
   90 static uint32_t octopci_read_config(device_t, u_int, u_int, u_int, u_int, int);
   91 static void     octopci_write_config(device_t, u_int, u_int, u_int, u_int,
   92                                      uint32_t, int);
   93 static int      octopci_route_interrupt(device_t, device_t, int);
   94 
   95 static void     octopci_init_bar(device_t, unsigned, unsigned, unsigned, unsigned, uint8_t *);
   96 static unsigned octopci_init_device(device_t, unsigned, unsigned, unsigned, unsigned);
   97 static unsigned octopci_init_bus(device_t, unsigned);
   98 static uint64_t octopci_cs_addr(unsigned, unsigned, unsigned, unsigned);
   99 
  100 static void
  101 octopci_identify(driver_t *drv, device_t parent)
  102 {
  103         BUS_ADD_CHILD(parent, 0, "pcib", 0);
  104 }
  105 
  106 static int
  107 octopci_probe(device_t dev)
  108 {
  109         if (device_get_unit(dev) != 0)
  110                 return (ENXIO);
  111         if (octeon_has_feature(OCTEON_FEATURE_PCIE))
  112                 return (ENXIO);
  113         /* XXX Check sysinfo flag.  */
  114         device_set_desc(dev, "Cavium Octeon PCI bridge");
  115         return (0);
  116 }
  117 
  118 static int
  119 octopci_attach(device_t dev)
  120 {
  121         struct octopci_softc *sc;
  122         cvmx_npi_mem_access_subid_t npi_mem_access_subid;
  123         cvmx_npi_pci_int_arb_cfg_t npi_pci_int_arb_cfg;
  124         cvmx_npi_ctl_status_t npi_ctl_status;
  125         cvmx_pci_ctl_status_2_t pci_ctl_status_2;
  126         cvmx_pci_cfg56_t pci_cfg56;
  127         cvmx_pci_cfg22_t pci_cfg22;
  128         cvmx_pci_cfg16_t pci_cfg16;
  129         cvmx_pci_cfg19_t pci_cfg19;
  130         cvmx_pci_cfg01_t pci_cfg01;
  131         unsigned subbus;
  132         unsigned i;
  133         int error;
  134 
  135         /*
  136          * Reset the PCI bus.
  137          */
  138         cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x1);
  139         cvmx_read_csr(CVMX_CIU_SOFT_PRST);
  140 
  141         DELAY(2000);
  142 
  143         npi_ctl_status.u64 = 0;
  144         npi_ctl_status.s.max_word = 1;
  145         npi_ctl_status.s.timer = 1;
  146         cvmx_write_csr(CVMX_NPI_CTL_STATUS, npi_ctl_status.u64);
  147 
  148         /*
  149          * Set host mode.
  150          */
  151         switch (cvmx_sysinfo_get()->board_type) {
  152 #if defined(OCTEON_VENDOR_LANNER)
  153         case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
  154         case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
  155                 /* 32-bit PCI-X */
  156                 cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x0);
  157                 break;
  158 #endif
  159         default:
  160                 /* 64-bit PCI-X */
  161                 cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x4);
  162                 break;
  163         }
  164         cvmx_read_csr(CVMX_CIU_SOFT_PRST);
  165 
  166         DELAY(2000);
  167 
  168         /*
  169          * Enable BARs and configure big BAR mode.
  170          */
  171         pci_ctl_status_2.u32 = 0;
  172         pci_ctl_status_2.s.bb1_hole = 5; /* 256MB hole in BAR1 */
  173         pci_ctl_status_2.s.bb1_siz = 1; /* BAR1 is 2GB */
  174         pci_ctl_status_2.s.bb_ca = 1; /* Bypass cache for big BAR */
  175         pci_ctl_status_2.s.bb_es = 1; /* Do big BAR byte-swapping */
  176         pci_ctl_status_2.s.bb1 = 1; /* BAR1 is big */
  177         pci_ctl_status_2.s.bb0 = 1; /* BAR0 is big */
  178         pci_ctl_status_2.s.bar2pres = 1; /* BAR2 present */
  179         pci_ctl_status_2.s.pmo_amod = 1; /* Round-robin priority */
  180         pci_ctl_status_2.s.tsr_hwm = 1;
  181         pci_ctl_status_2.s.bar2_enb = 1; /* Enable BAR2 */
  182         pci_ctl_status_2.s.bar2_esx = 1; /* Do BAR2 byte-swapping */
  183         pci_ctl_status_2.s.bar2_cax = 1; /* Bypass cache for BAR2 */
  184 
  185         NPI_WRITE(CVMX_NPI_PCI_CTL_STATUS_2, pci_ctl_status_2.u32);
  186 
  187         DELAY(2000);
  188 
  189         pci_ctl_status_2.u32 = NPI_READ(CVMX_NPI_PCI_CTL_STATUS_2);
  190 
  191         device_printf(dev, "%u-bit PCI%s bus.\n",
  192             pci_ctl_status_2.s.ap_64ad ? 64 : 32,
  193             pci_ctl_status_2.s.ap_pcix ? "-X" : "");
  194 
  195         /*
  196          * Set up transaction splitting, etc., parameters.
  197          */
  198         pci_cfg19.u32 = 0;
  199         pci_cfg19.s.mrbcm = 1;
  200         if (pci_ctl_status_2.s.ap_pcix) {
  201                 pci_cfg19.s.mdrrmc = 0;
  202                 pci_cfg19.s.tdomc = 4;
  203         } else {
  204                 pci_cfg19.s.mdrrmc = 2;
  205                 pci_cfg19.s.tdomc = 1;
  206         }
  207         NPI_WRITE(CVMX_NPI_PCI_CFG19, pci_cfg19.u32);
  208         NPI_READ(CVMX_NPI_PCI_CFG19);
  209 
  210         /*
  211          * Set up PCI error handling and memory access.
  212          */
  213         pci_cfg01.u32 = 0;
  214         pci_cfg01.s.fbbe = 1;
  215         pci_cfg01.s.see = 1;
  216         pci_cfg01.s.pee = 1;
  217         pci_cfg01.s.me = 1;
  218         pci_cfg01.s.msae = 1;
  219         if (pci_ctl_status_2.s.ap_pcix) {
  220                 pci_cfg01.s.fbb = 0;
  221         } else {
  222                 pci_cfg01.s.fbb = 1;
  223         }
  224         NPI_WRITE(CVMX_NPI_PCI_CFG01, pci_cfg01.u32);
  225         NPI_READ(CVMX_NPI_PCI_CFG01);
  226 
  227         /*
  228          * Enable the Octeon bus arbiter.
  229          */
  230         npi_pci_int_arb_cfg.u64 = 0;
  231         npi_pci_int_arb_cfg.s.en = 1;
  232         cvmx_write_csr(CVMX_NPI_PCI_INT_ARB_CFG, npi_pci_int_arb_cfg.u64);
  233 
  234         /*
  235          * Disable master latency timer.
  236          */
  237         pci_cfg16.u32 = 0;
  238         pci_cfg16.s.mltd = 1;
  239         NPI_WRITE(CVMX_NPI_PCI_CFG16, pci_cfg16.u32);
  240         NPI_READ(CVMX_NPI_PCI_CFG16);
  241 
  242         /*
  243          * Configure master arbiter.
  244          */
  245         pci_cfg22.u32 = 0;
  246         pci_cfg22.s.flush = 1;
  247         pci_cfg22.s.mrv = 255;
  248         NPI_WRITE(CVMX_NPI_PCI_CFG22, pci_cfg22.u32);
  249         NPI_READ(CVMX_NPI_PCI_CFG22);
  250 
  251         /*
  252          * Set up PCI-X capabilities.
  253          */
  254         if (pci_ctl_status_2.s.ap_pcix) {
  255                 pci_cfg56.u32 = 0;
  256                 pci_cfg56.s.most = 3;
  257                 pci_cfg56.s.roe = 1; /* Enable relaxed ordering */
  258                 pci_cfg56.s.dpere = 1;
  259                 pci_cfg56.s.ncp = 0xe8;
  260                 pci_cfg56.s.pxcid = 7;
  261                 NPI_WRITE(CVMX_NPI_PCI_CFG56, pci_cfg56.u32);
  262                 NPI_READ(CVMX_NPI_PCI_CFG56);
  263         }
  264 
  265         NPI_WRITE(CVMX_NPI_PCI_READ_CMD_6, 0x22);
  266         NPI_READ(CVMX_NPI_PCI_READ_CMD_6);
  267         NPI_WRITE(CVMX_NPI_PCI_READ_CMD_C, 0x33);
  268         NPI_READ(CVMX_NPI_PCI_READ_CMD_C);
  269         NPI_WRITE(CVMX_NPI_PCI_READ_CMD_E, 0x33);
  270         NPI_READ(CVMX_NPI_PCI_READ_CMD_E);
  271 
  272         /*
  273          * Configure MEM1 sub-DID access.
  274          */
  275         npi_mem_access_subid.u64 = 0;
  276         npi_mem_access_subid.s.esr = 1; /* Byte-swap on read */
  277         npi_mem_access_subid.s.esw = 1; /* Byte-swap on write */
  278         switch (cvmx_sysinfo_get()->board_type) {
  279 #if defined(OCTEON_VENDOR_LANNER)
  280         case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
  281                 npi_mem_access_subid.s.shortl = 1;
  282                 break;
  283 #endif
  284         default:
  285                 break;
  286         }
  287         cvmx_write_csr(CVMX_NPI_MEM_ACCESS_SUBID3, npi_mem_access_subid.u64);
  288 
  289         /*
  290          * Configure BAR2.  Linux says this has to come first.
  291          */
  292         NPI_WRITE(CVMX_NPI_PCI_CFG08, 0x00000000);
  293         NPI_READ(CVMX_NPI_PCI_CFG08);
  294         NPI_WRITE(CVMX_NPI_PCI_CFG09, 0x00000080);
  295         NPI_READ(CVMX_NPI_PCI_CFG09);
  296 
  297         /*
  298          * Disable BAR1 IndexX.
  299          */
  300         for (i = 0; i < 32; i++) {
  301                 NPI_WRITE(CVMX_NPI_PCI_BAR1_INDEXX(i), 0);
  302                 NPI_READ(CVMX_NPI_PCI_BAR1_INDEXX(i));
  303         }
  304 
  305         /*
  306          * Configure BAR0 and BAR1.
  307          */
  308         NPI_WRITE(CVMX_NPI_PCI_CFG04, 0x00000000);
  309         NPI_READ(CVMX_NPI_PCI_CFG04);
  310         NPI_WRITE(CVMX_NPI_PCI_CFG05, 0x00000000);
  311         NPI_READ(CVMX_NPI_PCI_CFG05);
  312 
  313         NPI_WRITE(CVMX_NPI_PCI_CFG06, 0x80000000);
  314         NPI_READ(CVMX_NPI_PCI_CFG06);
  315         NPI_WRITE(CVMX_NPI_PCI_CFG07, 0x00000000);
  316         NPI_READ(CVMX_NPI_PCI_CFG07);
  317 
  318         /*
  319          * Clear PCI interrupts.
  320          */
  321         cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, 0xffffffffffffffffull);
  322 
  323         sc = device_get_softc(dev);
  324         sc->sc_dev = dev;
  325         sc->sc_domain = 0;
  326         sc->sc_bus = 0;
  327 
  328         sc->sc_io.rm_type = RMAN_ARRAY;
  329         sc->sc_io.rm_descr = "Cavium Octeon PCI I/O Ports";
  330         error = rman_init(&sc->sc_io);
  331         if (error != 0)
  332                 return (error);
  333 
  334         error = rman_manage_region(&sc->sc_io, CVMX_OCT_PCI_IO_BASE,
  335             CVMX_OCT_PCI_IO_BASE + CVMX_OCT_PCI_IO_SIZE);
  336         if (error != 0)
  337                 return (error);
  338 
  339         sc->sc_mem1.rm_type = RMAN_ARRAY;
  340         sc->sc_mem1.rm_descr = "Cavium Octeon PCI Memory";
  341         error = rman_init(&sc->sc_mem1);
  342         if (error != 0)
  343                 return (error);
  344 
  345         error = rman_manage_region(&sc->sc_mem1, CVMX_OCT_PCI_MEM1_BASE,
  346             CVMX_OCT_PCI_MEM1_BASE + CVMX_OCT_PCI_MEM1_SIZE);
  347         if (error != 0)
  348                 return (error);
  349 
  350         /*
  351          * Next offsets for resource allocation in octopci_init_bar.
  352          */
  353         sc->sc_io_next = 0;
  354         sc->sc_mem1_next = 0;
  355 
  356         /*
  357          * Configure devices.
  358          */
  359         octopci_write_config(dev, 0, 0, 0, PCIR_SUBBUS_1, 0xff, 1);
  360         subbus = octopci_init_bus(dev, 0);
  361         octopci_write_config(dev, 0, 0, 0, PCIR_SUBBUS_1, subbus, 1);
  362 
  363         device_add_child(dev, "pci", 0);
  364 
  365         return (bus_generic_attach(dev));
  366 }
  367 
  368 static int
  369 octopci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
  370 {
  371         struct octopci_softc *sc;
  372         
  373         sc = device_get_softc(dev);
  374 
  375         switch (which) {
  376         case PCIB_IVAR_DOMAIN:
  377                 *result = sc->sc_domain;
  378                 return (0);
  379         case PCIB_IVAR_BUS:
  380                 *result = sc->sc_bus;
  381                 return (0);
  382                 
  383         }
  384         return (ENOENT);
  385 }
  386 
  387 static struct resource *
  388 octopci_alloc_resource(device_t bus, device_t child, int type, int *rid,
  389     u_long start, u_long end, u_long count, u_int flags)
  390 {
  391         struct octopci_softc *sc;
  392         struct resource *res;
  393         struct rman *rm;
  394         int error;
  395 
  396         sc = device_get_softc(bus);
  397 
  398         switch (type) {
  399         case SYS_RES_IRQ:
  400                 res = bus_generic_alloc_resource(bus, child, type, rid, start,
  401                     end, count, flags);
  402                 if (res != NULL)
  403                         return (res);
  404                 return (NULL);
  405         case SYS_RES_MEMORY:
  406                 rm = &sc->sc_mem1;
  407                 break;
  408         case SYS_RES_IOPORT:
  409                 rm = &sc->sc_io;
  410                 break;
  411         default:
  412                 return (NULL);
  413         }
  414 
  415         res = rman_reserve_resource(rm, start, end, count, flags, child);
  416         if (res == NULL)
  417                 return (NULL);
  418 
  419         rman_set_rid(res, *rid);
  420         rman_set_bustag(res, octopci_bus_space);
  421 
  422         switch (type) {
  423         case SYS_RES_MEMORY:
  424                 rman_set_bushandle(res, CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI, CVMX_OCT_SUBDID_PCI_MEM1)) + rman_get_start(res));
  425                 break;
  426         case SYS_RES_IOPORT:
  427                 rman_set_bushandle(res, CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI, CVMX_OCT_SUBDID_PCI_IO)) + rman_get_start(res));
  428 #if __mips_n64
  429                 rman_set_virtual(res, (void *)rman_get_bushandle(res));
  430 #else
  431                 /*
  432                  * XXX
  433                  * We can't access ports via a 32-bit pointer.
  434                  */
  435                 rman_set_virtual(res, NULL);
  436 #endif
  437                 break;
  438         }
  439 
  440         if ((flags & RF_ACTIVE) != 0) {
  441                 error = bus_activate_resource(child, type, *rid, res);
  442                 if (error != 0) {
  443                         rman_release_resource(res);
  444                         return (NULL);
  445                 }
  446         }
  447 
  448         return (res);
  449 }
  450 
  451 static int
  452 octopci_activate_resource(device_t bus, device_t child, int type, int rid,
  453     struct resource *res)
  454 {
  455         bus_space_handle_t bh;
  456         int error;
  457 
  458         switch (type) {
  459         case SYS_RES_IRQ:
  460                 error = bus_generic_activate_resource(bus, child, type, rid,
  461                                                       res);
  462                 if (error != 0)
  463                         return (error);
  464                 return (0);
  465         case SYS_RES_MEMORY:
  466         case SYS_RES_IOPORT:
  467                 error = bus_space_map(rman_get_bustag(res),
  468                     rman_get_bushandle(res), rman_get_size(res), 0, &bh);
  469                 if (error != 0)
  470                         return (error);
  471                 rman_set_bushandle(res, bh);
  472                 break;
  473         default:
  474                 return (ENXIO);
  475         }
  476 
  477         error = rman_activate_resource(res);
  478         if (error != 0)
  479                 return (error);
  480         return (0);
  481 }
  482 
  483 static int
  484 octopci_maxslots(device_t dev)
  485 {
  486         return (PCI_SLOTMAX);
  487 }
  488 
  489 static uint32_t
  490 octopci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
  491     int bytes)
  492 {
  493         struct octopci_softc *sc;
  494         uint64_t addr;
  495         uint32_t data;
  496 
  497         sc = device_get_softc(dev);
  498 
  499         addr = octopci_cs_addr(bus, slot, func, reg);
  500 
  501         switch (bytes) {
  502         case 4:
  503                 data = le32toh(cvmx_read64_uint32(addr));
  504                 return (data);
  505         case 2:
  506                 data = le16toh(cvmx_read64_uint16(addr));
  507                 return (data);
  508         case 1:
  509                 data = cvmx_read64_uint8(addr);
  510                 return (data);
  511         default:
  512                 return ((uint32_t)-1);
  513         }
  514 }
  515 
  516 static void
  517 octopci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
  518     u_int reg, uint32_t data, int bytes)
  519 {
  520         struct octopci_softc *sc;
  521         uint64_t addr;
  522 
  523         sc = device_get_softc(dev);
  524 
  525         addr = octopci_cs_addr(bus, slot, func, reg);
  526 
  527         switch (bytes) {
  528         case 4:
  529                 cvmx_write64_uint32(addr, htole32(data));
  530                 return;
  531         case 2:
  532                 cvmx_write64_uint16(addr, htole16(data));
  533                 return;
  534         case 1:
  535                 cvmx_write64_uint8(addr, data);
  536                 return;
  537         default:
  538                 return;
  539         }
  540 }
  541 
  542 static int
  543 octopci_route_interrupt(device_t dev, device_t child, int pin)
  544 {
  545         struct octopci_softc *sc;
  546         unsigned bus, slot, func;
  547         unsigned irq;
  548 
  549         sc = device_get_softc(dev);
  550 
  551         bus = pci_get_bus(child);
  552         slot = pci_get_slot(child);
  553         func = pci_get_function(child);
  554 
  555         /*
  556          * Board types we have to know at compile-time.
  557          */
  558 #if defined(OCTEON_BOARD_CAPK_0100ND)
  559         if (bus == 0 && slot == 12 && func == 0)
  560                 return (CVMX_IRQ_PCI_INT2);
  561 #endif
  562 
  563         /*
  564          * For board types we can determine at runtime.
  565          */
  566         switch (cvmx_sysinfo_get()->board_type) {
  567 #if defined(OCTEON_VENDOR_LANNER)
  568         case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
  569                 return (CVMX_IRQ_PCI_INT0 + pin - 1);
  570         case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
  571                 if (slot < 32) {
  572                         if (slot == 3 || slot == 9)
  573                                 irq = pin;
  574                         else
  575                                 irq = pin - 1;
  576                         return (CVMX_IRQ_PCI_INT0 + (irq & 3));
  577                 }
  578                 break;
  579 #endif
  580         default:
  581                 break;
  582         }
  583 
  584         irq = slot + pin - 3;
  585 
  586         return (CVMX_IRQ_PCI_INT0 + (irq & 3));
  587 }
  588 
  589 static void
  590 octopci_init_bar(device_t dev, unsigned b, unsigned s, unsigned f, unsigned barnum, uint8_t *commandp)
  591 {
  592         struct octopci_softc *sc;
  593         uint32_t bar;
  594         unsigned size;
  595 
  596         sc = device_get_softc(dev);
  597 
  598         octopci_write_config(dev, b, s, f, PCIR_BAR(barnum), 0xffffffff, 4);
  599         bar = octopci_read_config(dev, b, s, f, PCIR_BAR(barnum), 4);
  600 
  601         if (bar == 0) {
  602                 /* Bar not implemented.  */
  603                 return;
  604         }
  605 
  606         /* XXX Some of this is wrong for 64-bit busses.  */
  607 
  608         if (PCI_BAR_IO(bar)) {
  609                 size = ~(bar & PCIM_BAR_IO_BASE) + 1;
  610 
  611                 sc->sc_io_next = (sc->sc_io_next + size - 1) & ~(size - 1);
  612                 if (sc->sc_io_next + size > CVMX_OCT_PCI_IO_SIZE) {
  613                         device_printf(dev, "%02x.%02x:%02x: no ports for BAR%u.\n",
  614                             b, s, f, barnum);
  615                         return;
  616                 }
  617                 octopci_write_config(dev, b, s, f, PCIR_BAR(barnum),
  618                     CVMX_OCT_PCI_IO_BASE + sc->sc_io_next, 4);
  619                 sc->sc_io_next += size;
  620 
  621                 /*
  622                  * Enable I/O ports.
  623                  */
  624                 *commandp |= PCIM_CMD_PORTEN;
  625         } else {
  626                 size = ~(bar & (uint32_t)PCIM_BAR_MEM_BASE) + 1;
  627 
  628                 sc->sc_mem1_next = (sc->sc_mem1_next + size - 1) & ~(size - 1);
  629                 if (sc->sc_mem1_next + size > CVMX_OCT_PCI_MEM1_SIZE) {
  630                         device_printf(dev, "%02x.%02x:%02x: no memory for BAR%u.\n",
  631                             b, s, f, barnum);
  632                         return;
  633                 }
  634                 octopci_write_config(dev, b, s, f, PCIR_BAR(barnum),
  635                     CVMX_OCT_PCI_MEM1_BASE + sc->sc_mem1_next, 4);
  636                 sc->sc_mem1_next += size;
  637 
  638                 /*
  639                  * Enable memory access.
  640                  */
  641                 *commandp |= PCIM_CMD_MEMEN;
  642         }
  643 }
  644 
  645 static unsigned
  646 octopci_init_device(device_t dev, unsigned b, unsigned s, unsigned f, unsigned secbus)
  647 {
  648         unsigned barnum, bars;
  649         uint8_t brctl;
  650         uint8_t class, subclass;
  651         uint8_t command;
  652         uint8_t hdrtype;
  653 
  654         /* Read header type (again.)  */
  655         hdrtype = octopci_read_config(dev, b, s, f, PCIR_HDRTYPE, 1);
  656 
  657         /*
  658          * Disable memory and I/O while programming BARs.
  659          */
  660         command = octopci_read_config(dev, b, s, f, PCIR_COMMAND, 1);
  661         command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
  662         octopci_write_config(dev, b, s, f, PCIR_COMMAND, command, 1);
  663 
  664         DELAY(10000);
  665 
  666         /* Program BARs.  */
  667         switch (hdrtype & PCIM_HDRTYPE) {
  668         case PCIM_HDRTYPE_NORMAL:
  669                 bars = 6;
  670                 break;
  671         case PCIM_HDRTYPE_BRIDGE:
  672                 bars = 2;
  673                 break;
  674         case PCIM_HDRTYPE_CARDBUS:
  675                 bars = 0;
  676                 break;
  677         default:
  678                 device_printf(dev, "%02x.%02x:%02x: invalid header type %#x\n",
  679                     b, s, f, hdrtype);
  680                 return (secbus);
  681         }
  682 
  683         for (barnum = 0; barnum < bars; barnum++)
  684                 octopci_init_bar(dev, b, s, f, barnum, &command);
  685 
  686         /* Enable bus mastering.  */
  687         command |= PCIM_CMD_BUSMASTEREN;
  688 
  689         /* Enable whatever facilities the BARs require.  */
  690         octopci_write_config(dev, b, s, f, PCIR_COMMAND, command, 1);
  691 
  692         DELAY(10000);
  693 
  694         /* 
  695          * Set cache line size.  On Octeon it should be 128 bytes,
  696          * but according to Linux some Intel bridges have trouble
  697          * with values over 64 bytes, so use 64 bytes.
  698          */
  699         octopci_write_config(dev, b, s, f, PCIR_CACHELNSZ, 16, 1);
  700 
  701         /* Set latency timer.  */
  702         octopci_write_config(dev, b, s, f, PCIR_LATTIMER, 48, 1);
  703 
  704         /* Board-specific or device-specific fixups and workarounds.  */
  705         switch (cvmx_sysinfo_get()->board_type) {
  706 #if defined(OCTEON_VENDOR_LANNER)
  707         case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
  708                 if (b == 1 && s == 7 && f == 0) {
  709                         bus_addr_t busaddr, unitbusaddr;
  710                         uint32_t bar;
  711                         uint32_t tmp;
  712                         unsigned unit;
  713 
  714                         /*
  715                          * Set Tx DMA power.
  716                          */
  717                         bar = octopci_read_config(dev, b, s, f,
  718                             PCIR_BAR(3), 4);
  719                         busaddr = CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI,
  720                             CVMX_OCT_SUBDID_PCI_MEM1));
  721                         busaddr += (bar & (uint32_t)PCIM_BAR_MEM_BASE);
  722                         for (unit = 0; unit < 4; unit++) {
  723                                 unitbusaddr = busaddr + 0x430 + (unit << 8);
  724                                 tmp = le32toh(cvmx_read64_uint32(unitbusaddr));
  725                                 tmp &= ~0x700;
  726                                 tmp |= 0x300;
  727                                 cvmx_write64_uint32(unitbusaddr, htole32(tmp));
  728                         }
  729                 }
  730                 break;
  731 #endif
  732         default:
  733                 break;
  734         }
  735 
  736         /* Configure PCI-PCI bridges.  */
  737         class = octopci_read_config(dev, b, s, f, PCIR_CLASS, 1);
  738         if (class != PCIC_BRIDGE)
  739                 return (secbus);
  740 
  741         subclass = octopci_read_config(dev, b, s, f, PCIR_SUBCLASS, 1);
  742         if (subclass != PCIS_BRIDGE_PCI)
  743                 return (secbus);
  744 
  745         /* Enable memory and I/O access.  */
  746         command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
  747         octopci_write_config(dev, b, s, f, PCIR_COMMAND, command, 1);
  748 
  749         /* Enable errors and parity checking.  Do a bus reset.  */
  750         brctl = octopci_read_config(dev, b, s, f, PCIR_BRIDGECTL_1, 1);
  751         brctl |= PCIB_BCR_PERR_ENABLE | PCIB_BCR_SERR_ENABLE;
  752 
  753         /* Perform a secondary bus reset.  */
  754         brctl |= PCIB_BCR_SECBUS_RESET;
  755         octopci_write_config(dev, b, s, f, PCIR_BRIDGECTL_1, brctl, 1);
  756         DELAY(100000);
  757         brctl &= ~PCIB_BCR_SECBUS_RESET;
  758         octopci_write_config(dev, b, s, f, PCIR_BRIDGECTL_1, brctl, 1);
  759 
  760         secbus++;
  761 
  762         /* Program memory and I/O ranges.  */
  763         octopci_write_config(dev, b, s, f, PCIR_MEMBASE_1,
  764             CVMX_OCT_PCI_MEM1_BASE >> 16, 2);
  765         octopci_write_config(dev, b, s, f, PCIR_MEMLIMIT_1,
  766             (CVMX_OCT_PCI_MEM1_BASE + CVMX_OCT_PCI_MEM1_SIZE - 1) >> 16, 2);
  767 
  768         octopci_write_config(dev, b, s, f, PCIR_IOBASEL_1,
  769             CVMX_OCT_PCI_IO_BASE >> 8, 1);
  770         octopci_write_config(dev, b, s, f, PCIR_IOBASEH_1,
  771             CVMX_OCT_PCI_IO_BASE >> 16, 2);
  772 
  773         octopci_write_config(dev, b, s, f, PCIR_IOLIMITL_1,
  774             (CVMX_OCT_PCI_IO_BASE + CVMX_OCT_PCI_IO_SIZE - 1) >> 8, 1);
  775         octopci_write_config(dev, b, s, f, PCIR_IOLIMITH_1,
  776             (CVMX_OCT_PCI_IO_BASE + CVMX_OCT_PCI_IO_SIZE - 1) >> 16, 2);
  777 
  778         /* Program prefetchable memory decoder.  */
  779         /* XXX */
  780 
  781         /* Probe secondary/subordinate buses.  */
  782         octopci_write_config(dev, b, s, f, PCIR_PRIBUS_1, b, 1);
  783         octopci_write_config(dev, b, s, f, PCIR_SECBUS_1, secbus, 1);
  784         octopci_write_config(dev, b, s, f, PCIR_SUBBUS_1, 0xff, 1);
  785 
  786         /* Perform a secondary bus reset.  */
  787         brctl |= PCIB_BCR_SECBUS_RESET;
  788         octopci_write_config(dev, b, s, f, PCIR_BRIDGECTL_1, brctl, 1);
  789         DELAY(100000);
  790         brctl &= ~PCIB_BCR_SECBUS_RESET;
  791         octopci_write_config(dev, b, s, f, PCIR_BRIDGECTL_1, brctl, 1);
  792 
  793         /* Give the bus time to settle now before reading configspace.  */
  794         DELAY(100000);
  795 
  796         secbus = octopci_init_bus(dev, secbus);
  797 
  798         octopci_write_config(dev, b, s, f, PCIR_SUBBUS_1, secbus, 1);
  799 
  800         return (secbus);
  801 }
  802 
  803 static unsigned
  804 octopci_init_bus(device_t dev, unsigned b)
  805 {
  806         unsigned s, f;
  807         uint8_t hdrtype;
  808         unsigned secbus;
  809 
  810         secbus = b;
  811 
  812         for (s = 0; s <= PCI_SLOTMAX; s++) {
  813                 for (f = 0; f <= PCI_FUNCMAX; f++) {
  814                         hdrtype = octopci_read_config(dev, b, s, f, PCIR_HDRTYPE, 1);
  815 
  816                         if (hdrtype == 0xff) {
  817                                 if (f == 0)
  818                                         break; /* Next slot.  */
  819                                 continue; /* Next function.  */
  820                         }
  821 
  822                         secbus = octopci_init_device(dev, b, s, f, secbus);
  823 
  824                         if (f == 0 && (hdrtype & PCIM_MFDEV) == 0)
  825                                 break; /* Next slot.  */
  826                 }
  827         }
  828 
  829         return (secbus);
  830 }
  831 
  832 static uint64_t
  833 octopci_cs_addr(unsigned bus, unsigned slot, unsigned func, unsigned reg)
  834 {
  835         octeon_pci_config_space_address_t pci_addr;
  836 
  837         pci_addr.u64 = 0;
  838         pci_addr.s.upper = 2;
  839         pci_addr.s.io = 1;
  840         pci_addr.s.did = 3;
  841         pci_addr.s.subdid = CVMX_OCT_SUBDID_PCI_CFG;
  842         pci_addr.s.endian_swap = 1;
  843         pci_addr.s.bus = bus;
  844         pci_addr.s.dev = slot;
  845         pci_addr.s.func = func;
  846         pci_addr.s.reg = reg;
  847 
  848         return (pci_addr.u64);
  849 }
  850 
  851 static device_method_t octopci_methods[] = {
  852         /* Device interface */
  853         DEVMETHOD(device_identify,      octopci_identify),
  854         DEVMETHOD(device_probe,         octopci_probe),
  855         DEVMETHOD(device_attach,        octopci_attach),
  856 
  857         /* Bus interface */
  858         DEVMETHOD(bus_read_ivar,        octopci_read_ivar),
  859         DEVMETHOD(bus_alloc_resource,   octopci_alloc_resource),
  860         DEVMETHOD(bus_release_resource, bus_generic_release_resource),
  861         DEVMETHOD(bus_activate_resource,octopci_activate_resource),
  862         DEVMETHOD(bus_deactivate_resource,bus_generic_deactivate_resource),
  863         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
  864         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
  865 
  866         DEVMETHOD(bus_add_child,        bus_generic_add_child),
  867 
  868         /* pcib interface */
  869         DEVMETHOD(pcib_maxslots,        octopci_maxslots),
  870         DEVMETHOD(pcib_read_config,     octopci_read_config),
  871         DEVMETHOD(pcib_write_config,    octopci_write_config),
  872         DEVMETHOD(pcib_route_interrupt, octopci_route_interrupt),
  873 
  874         DEVMETHOD_END
  875 };
  876 
  877 static driver_t octopci_driver = {
  878         "pcib",
  879         octopci_methods,
  880         sizeof(struct octopci_softc),
  881 };
  882 static devclass_t octopci_devclass;
  883 DRIVER_MODULE(octopci, ciu, octopci_driver, octopci_devclass, 0, 0);

Cache object: e9056e85d4d30fd1ca77585b8981cf9d


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