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/powerpc/mpc85xx/pci_mpc85xx.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 2006-2007 by Juniper Networks.
    3  * Copyright 2008 Semihalf.
    4  * Copyright 2010 The FreeBSD Foundation
    5  * All rights reserved.
    6  *
    7  * Portions of this software were developed by Semihalf
    8  * under sponsorship from the FreeBSD Foundation.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. The name of the author may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  * From: FreeBSD: src/sys/powerpc/mpc85xx/pci_ocp.c,v 1.9 2010/03/23 23:46:28 marcel
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD: releng/11.0/sys/powerpc/mpc85xx/pci_mpc85xx.c 297392 2016-03-29 15:19:56Z zbb $");
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/ktr.h>
   42 #include <sys/sockio.h>
   43 #include <sys/mbuf.h>
   44 #include <sys/malloc.h>
   45 #include <sys/kernel.h>
   46 #include <sys/module.h>
   47 #include <sys/socket.h>
   48 #include <sys/queue.h>
   49 #include <sys/bus.h>
   50 #include <sys/lock.h>
   51 #include <sys/mutex.h>
   52 #include <sys/rman.h>
   53 #include <sys/endian.h>
   54 
   55 #include <vm/vm.h>
   56 #include <vm/pmap.h>
   57 
   58 #include <dev/ofw/ofw_pci.h>
   59 #include <dev/ofw/ofw_bus.h>
   60 #include <dev/ofw/ofw_bus_subr.h>
   61 #include <dev/ofw/ofwpci.h>
   62 #include <dev/pci/pcivar.h>
   63 #include <dev/pci/pcireg.h>
   64 #include <dev/pci/pcib_private.h>
   65 
   66 #include "ofw_bus_if.h"
   67 #include "pcib_if.h"
   68 
   69 #include <machine/resource.h>
   70 #include <machine/bus.h>
   71 #include <machine/intr_machdep.h>
   72 
   73 #include <powerpc/mpc85xx/mpc85xx.h>
   74 
   75 #define REG_CFG_ADDR    0x0000
   76 #define CONFIG_ACCESS_ENABLE    0x80000000
   77 
   78 #define REG_CFG_DATA    0x0004
   79 #define REG_INT_ACK     0x0008
   80 
   81 #define REG_POTAR(n)    (0x0c00 + 0x20 * (n))
   82 #define REG_POTEAR(n)   (0x0c04 + 0x20 * (n))
   83 #define REG_POWBAR(n)   (0x0c08 + 0x20 * (n))
   84 #define REG_POWAR(n)    (0x0c10 + 0x20 * (n))
   85 
   86 #define REG_PITAR(n)    (0x0e00 - 0x20 * (n))
   87 #define REG_PIWBAR(n)   (0x0e08 - 0x20 * (n))
   88 #define REG_PIWBEAR(n)  (0x0e0c - 0x20 * (n))
   89 #define REG_PIWAR(n)    (0x0e10 - 0x20 * (n))
   90 
   91 #define REG_PEX_MES_DR  0x0020
   92 #define REG_PEX_MES_IER 0x0028
   93 #define REG_PEX_ERR_DR  0x0e00
   94 #define REG_PEX_ERR_EN  0x0e08
   95 
   96 #define REG_PEX_ERR_DR          0x0e00
   97 #define REG_PEX_ERR_DR_ME       0x80000000
   98 #define REG_PEX_ERR_DR_PCT      0x800000
   99 #define REG_PEX_ERR_DR_PAT      0x400000
  100 #define REG_PEX_ERR_DR_PCAC     0x200000
  101 #define REG_PEX_ERR_DR_PNM      0x100000
  102 #define REG_PEX_ERR_DR_CDNSC    0x80000
  103 #define REG_PEX_ERR_DR_CRSNC    0x40000
  104 #define REG_PEX_ERR_DR_ICCA     0x20000
  105 #define REG_PEX_ERR_DR_IACA     0x10000
  106 #define REG_PEX_ERR_DR_CRST     0x8000
  107 #define REG_PEX_ERR_DR_MIS      0x4000
  108 #define REG_PEX_ERR_DR_IOIS     0x2000
  109 #define REG_PEX_ERR_DR_CIS      0x1000
  110 #define REG_PEX_ERR_DR_CIEP     0x800
  111 #define REG_PEX_ERR_DR_IOIEP    0x400
  112 #define REG_PEX_ERR_DR_OAC      0x200
  113 #define REG_PEX_ERR_DR_IOIA     0x100
  114 #define REG_PEX_ERR_DR_IMBA     0x80
  115 #define REG_PEX_ERR_DR_IIOBA    0x40
  116 #define REG_PEX_ERR_DR_LDDE     0x20
  117 #define REG_PEX_ERR_EN          0x0e08
  118 
  119 #define PCIR_LTSSM      0x404
  120 #define LTSSM_STAT_L0   0x16
  121 
  122 #define DEVFN(b, s, f)  ((b << 16) | (s << 8) | f)
  123 
  124 struct fsl_pcib_softc {
  125         struct ofw_pci_softc pci_sc;
  126         device_t        sc_dev;
  127 
  128         int             sc_iomem_target;
  129         bus_addr_t      sc_iomem_start, sc_iomem_end;
  130         int             sc_ioport_target;
  131         bus_addr_t      sc_ioport_start, sc_ioport_end;
  132 
  133         struct resource *sc_res;
  134         bus_space_handle_t sc_bsh;
  135         bus_space_tag_t sc_bst;
  136         int             sc_rid;
  137 
  138         struct resource *sc_irq_res;
  139         void            *sc_ih;
  140 
  141         int             sc_busnr;
  142         int             sc_pcie;
  143         uint8_t         sc_pcie_capreg;         /* PCI-E Capability Reg Set */
  144 
  145         /* Devices that need special attention. */
  146         int             sc_devfn_tundra;
  147         int             sc_devfn_via_ide;
  148 };
  149 
  150 struct fsl_pcib_err_dr {
  151         const char      *msg;
  152         uint32_t        err_dr_mask;
  153 };
  154 
  155 static const struct fsl_pcib_err_dr pci_err[] = {
  156         {"ME",          REG_PEX_ERR_DR_ME},
  157         {"PCT",         REG_PEX_ERR_DR_PCT},
  158         {"PAT",         REG_PEX_ERR_DR_PAT},
  159         {"PCAC",        REG_PEX_ERR_DR_PCAC},
  160         {"PNM",         REG_PEX_ERR_DR_PNM},
  161         {"CDNSC",       REG_PEX_ERR_DR_CDNSC},
  162         {"CRSNC",       REG_PEX_ERR_DR_CRSNC},
  163         {"ICCA",        REG_PEX_ERR_DR_ICCA},
  164         {"IACA",        REG_PEX_ERR_DR_IACA},
  165         {"CRST",        REG_PEX_ERR_DR_CRST},
  166         {"MIS",         REG_PEX_ERR_DR_MIS},
  167         {"IOIS",        REG_PEX_ERR_DR_IOIS},
  168         {"CIS",         REG_PEX_ERR_DR_CIS},
  169         {"CIEP",        REG_PEX_ERR_DR_CIEP},
  170         {"IOIEP",       REG_PEX_ERR_DR_IOIEP},
  171         {"OAC",         REG_PEX_ERR_DR_OAC},
  172         {"IOIA",        REG_PEX_ERR_DR_IOIA},
  173         {"IMBA",        REG_PEX_ERR_DR_IMBA},
  174         {"IIOBA",       REG_PEX_ERR_DR_IIOBA},
  175         {"LDDE",        REG_PEX_ERR_DR_LDDE}
  176 };
  177 
  178 /* Local forward declerations. */
  179 static uint32_t fsl_pcib_cfgread(struct fsl_pcib_softc *, u_int, u_int, u_int,
  180     u_int, int);
  181 static void fsl_pcib_cfgwrite(struct fsl_pcib_softc *, u_int, u_int, u_int,
  182     u_int, uint32_t, int);
  183 static int fsl_pcib_decode_win(phandle_t, struct fsl_pcib_softc *);
  184 static void fsl_pcib_err_init(device_t);
  185 static void fsl_pcib_inbound(struct fsl_pcib_softc *, int, int, uint64_t,
  186     uint64_t, uint64_t);
  187 static int fsl_pcib_init(struct fsl_pcib_softc *, int, int);
  188 static void fsl_pcib_outbound(struct fsl_pcib_softc *, int, int, uint64_t,
  189     uint64_t, uint64_t);
  190 
  191 /* Forward declerations. */
  192 static int fsl_pcib_attach(device_t);
  193 static int fsl_pcib_detach(device_t);
  194 static int fsl_pcib_probe(device_t);
  195 
  196 static int fsl_pcib_maxslots(device_t);
  197 static uint32_t fsl_pcib_read_config(device_t, u_int, u_int, u_int, u_int, int);
  198 static void fsl_pcib_write_config(device_t, u_int, u_int, u_int, u_int,
  199     uint32_t, int);
  200 
  201 /* Configuration r/w mutex. */
  202 struct mtx pcicfg_mtx;
  203 static int mtx_initialized = 0;
  204 
  205 /*
  206  * Bus interface definitions.
  207  */
  208 static device_method_t fsl_pcib_methods[] = {
  209         /* Device interface */
  210         DEVMETHOD(device_probe,         fsl_pcib_probe),
  211         DEVMETHOD(device_attach,        fsl_pcib_attach),
  212         DEVMETHOD(device_detach,        fsl_pcib_detach),
  213 
  214         /* pcib interface */
  215         DEVMETHOD(pcib_maxslots,        fsl_pcib_maxslots),
  216         DEVMETHOD(pcib_read_config,     fsl_pcib_read_config),
  217         DEVMETHOD(pcib_write_config,    fsl_pcib_write_config),
  218 
  219         DEVMETHOD_END
  220 };
  221 
  222 static devclass_t fsl_pcib_devclass;
  223 
  224 DEFINE_CLASS_1(pcib, fsl_pcib_driver, fsl_pcib_methods,
  225     sizeof(struct fsl_pcib_softc), ofw_pci_driver);
  226 DRIVER_MODULE(pcib, ofwbus, fsl_pcib_driver, fsl_pcib_devclass, 0, 0);
  227 
  228 static int
  229 fsl_pcib_err_intr(void *v)
  230 {
  231         struct fsl_pcib_softc *sc;
  232         device_t dev;
  233         uint32_t err_reg, clear_reg;
  234         uint8_t i;
  235 
  236         dev = (device_t)v;
  237         sc = device_get_softc(dev);
  238 
  239         clear_reg = 0;
  240         err_reg = bus_space_read_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_DR);
  241 
  242         /* Check which one error occurred */
  243         for (i = 0; i < sizeof(pci_err)/sizeof(struct fsl_pcib_err_dr); i++) {
  244                 if (err_reg & pci_err[i].err_dr_mask) {
  245                         device_printf(dev, "PCI %d: report %s error\n",
  246                             device_get_unit(dev), pci_err[i].msg);
  247                         clear_reg |= pci_err[i].err_dr_mask;
  248                 }
  249         }
  250 
  251         /* Clear pending errors */
  252         bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_DR, clear_reg);
  253 
  254         return (0);
  255 }
  256 
  257 static int
  258 fsl_pcib_probe(device_t dev)
  259 {
  260 
  261         if (ofw_bus_get_type(dev) == NULL ||
  262             strcmp(ofw_bus_get_type(dev), "pci") != 0)
  263                 return (ENXIO);
  264 
  265         if (!(ofw_bus_is_compatible(dev, "fsl,mpc8540-pci") ||
  266             ofw_bus_is_compatible(dev, "fsl,mpc8540-pcie") ||
  267             ofw_bus_is_compatible(dev, "fsl,mpc8548-pcie") ||
  268             ofw_bus_is_compatible(dev, "fsl,p5020-pcie") ||
  269             ofw_bus_is_compatible(dev, "fsl,qoriq-pcie-v2.2") ||
  270             ofw_bus_is_compatible(dev, "fsl,qoriq-pcie")))
  271                 return (ENXIO);
  272 
  273         device_set_desc(dev, "Freescale Integrated PCI/PCI-E Controller");
  274         return (BUS_PROBE_DEFAULT);
  275 }
  276 
  277 static int
  278 fsl_pcib_attach(device_t dev)
  279 {
  280         struct fsl_pcib_softc *sc;
  281         phandle_t node;
  282         uint32_t cfgreg;
  283         int error, maxslot, rid;
  284         uint8_t ltssm, capptr;
  285 
  286         sc = device_get_softc(dev);
  287         sc->sc_dev = dev;
  288 
  289         sc->sc_rid = 0;
  290         sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
  291             RF_ACTIVE);
  292         if (sc->sc_res == NULL) {
  293                 device_printf(dev, "could not map I/O memory\n");
  294                 return (ENXIO);
  295         }
  296         sc->sc_bst = rman_get_bustag(sc->sc_res);
  297         sc->sc_bsh = rman_get_bushandle(sc->sc_res);
  298         sc->sc_busnr = 0;
  299 
  300         if (!mtx_initialized) {
  301                 mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
  302                 mtx_initialized = 1;
  303         }
  304 
  305         cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_VENDOR, 2);
  306         if (cfgreg != 0x1057 && cfgreg != 0x1957)
  307                 goto err;
  308 
  309         capptr = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_CAP_PTR, 1);
  310         while (capptr != 0) {
  311                 cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, capptr, 2);
  312                 switch (cfgreg & 0xff) {
  313                 case PCIY_PCIX:
  314                         break;
  315                 case PCIY_EXPRESS:
  316                         sc->sc_pcie = 1;
  317                         sc->sc_pcie_capreg = capptr;
  318                         break;
  319                 }
  320                 capptr = (cfgreg >> 8) & 0xff;
  321         }
  322 
  323         node = ofw_bus_get_node(dev);
  324 
  325         /*
  326          * Initialize generic OF PCI interface (ranges, etc.)
  327          */
  328 
  329         error = ofw_pci_init(dev);
  330         if (error)
  331                 return (error);
  332 
  333         /*
  334          * Configure decode windows for PCI(E) access.
  335          */
  336         if (fsl_pcib_decode_win(node, sc) != 0)
  337                 goto err;
  338 
  339         cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_COMMAND, 2);
  340         cfgreg |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
  341             PCIM_CMD_PORTEN;
  342         fsl_pcib_cfgwrite(sc, 0, 0, 0, PCIR_COMMAND, cfgreg, 2);
  343 
  344         sc->sc_devfn_tundra = -1;
  345         sc->sc_devfn_via_ide = -1;
  346 
  347 
  348         /*
  349          * Scan bus using firmware configured, 0 based bus numbering.
  350          */
  351         maxslot = (sc->sc_pcie) ? 0 : PCI_SLOTMAX;
  352         fsl_pcib_init(sc, sc->sc_busnr, maxslot);
  353 
  354         if (sc->sc_pcie) {
  355                 ltssm = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_LTSSM, 1);
  356                 if (ltssm < LTSSM_STAT_L0) {
  357                         if (bootverbose)
  358                                 printf("PCI %d: no PCIE link, skipping\n",
  359                                     device_get_unit(dev));
  360                         return (0);
  361                 }
  362         }
  363 
  364         /* Allocate irq */
  365         rid = 0;
  366         sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  367             RF_ACTIVE | RF_SHAREABLE);
  368         if (sc->sc_irq_res == NULL) {
  369                 error = fsl_pcib_detach(dev);
  370                 if (error != 0) {
  371                         device_printf(dev,
  372                             "Detach of the driver failed with error %d\n",
  373                             error);
  374                 }
  375                 return (ENXIO);
  376         }
  377 
  378         /* Setup interrupt handler */
  379         error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
  380             NULL, (driver_intr_t *)fsl_pcib_err_intr, dev, &sc->sc_ih);
  381         if (error != 0) {
  382                 device_printf(dev, "Could not setup irq, %d\n", error);
  383                 sc->sc_ih = NULL;
  384                 error = fsl_pcib_detach(dev);
  385                 if (error != 0) {
  386                         device_printf(dev,
  387                             "Detach of the driver failed with error %d\n",
  388                             error);
  389                 }
  390                 return (ENXIO);
  391         }
  392 
  393         fsl_pcib_err_init(dev);
  394 
  395         return (ofw_pci_attach(dev));
  396 
  397 err:
  398         return (ENXIO);
  399 }
  400 
  401 static uint32_t
  402 fsl_pcib_cfgread(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
  403     u_int reg, int bytes)
  404 {
  405         uint32_t addr, data;
  406 
  407         addr = CONFIG_ACCESS_ENABLE;
  408         addr |= (bus & 0xff) << 16;
  409         addr |= (slot & 0x1f) << 11;
  410         addr |= (func & 0x7) << 8;
  411         addr |= reg & 0xfc;
  412         if (sc->sc_pcie)
  413                 addr |= (reg & 0xf00) << 16;
  414 
  415         mtx_lock_spin(&pcicfg_mtx);
  416         bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr);
  417 
  418         switch (bytes) {
  419         case 1:
  420                 data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
  421                     REG_CFG_DATA + (reg & 3));
  422                 break;
  423         case 2:
  424                 data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh,
  425                     REG_CFG_DATA + (reg & 2)));
  426                 break;
  427         case 4:
  428                 data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
  429                     REG_CFG_DATA));
  430                 break;
  431         default:
  432                 data = ~0;
  433                 break;
  434         }
  435         mtx_unlock_spin(&pcicfg_mtx);
  436         return (data);
  437 }
  438 
  439 static void
  440 fsl_pcib_cfgwrite(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
  441     u_int reg, uint32_t data, int bytes)
  442 {
  443         uint32_t addr;
  444 
  445         addr = CONFIG_ACCESS_ENABLE;
  446         addr |= (bus & 0xff) << 16;
  447         addr |= (slot & 0x1f) << 11;
  448         addr |= (func & 0x7) << 8;
  449         addr |= reg & 0xfc;
  450         if (sc->sc_pcie)
  451                 addr |= (reg & 0xf00) << 16;
  452 
  453         mtx_lock_spin(&pcicfg_mtx);
  454         bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr);
  455 
  456         switch (bytes) {
  457         case 1:
  458                 bus_space_write_1(sc->sc_bst, sc->sc_bsh,
  459                     REG_CFG_DATA + (reg & 3), data);
  460                 break;
  461         case 2:
  462                 bus_space_write_2(sc->sc_bst, sc->sc_bsh,
  463                     REG_CFG_DATA + (reg & 2), htole16(data));
  464                 break;
  465         case 4:
  466                 bus_space_write_4(sc->sc_bst, sc->sc_bsh,
  467                     REG_CFG_DATA, htole32(data));
  468                 break;
  469         }
  470         mtx_unlock_spin(&pcicfg_mtx);
  471 }
  472 
  473 #if 0
  474 static void
  475 dump(struct fsl_pcib_softc *sc)
  476 {
  477         unsigned int i;
  478 
  479 #define RD(o)   bus_space_read_4(sc->sc_bst, sc->sc_bsh, o)
  480         for (i = 0; i < 5; i++) {
  481                 printf("POTAR%u  =0x%08x\n", i, RD(REG_POTAR(i)));
  482                 printf("POTEAR%u =0x%08x\n", i, RD(REG_POTEAR(i)));
  483                 printf("POWBAR%u =0x%08x\n", i, RD(REG_POWBAR(i)));
  484                 printf("POWAR%u  =0x%08x\n", i, RD(REG_POWAR(i)));
  485         }
  486         printf("\n");
  487         for (i = 1; i < 4; i++) {
  488                 printf("PITAR%u  =0x%08x\n", i, RD(REG_PITAR(i)));
  489                 printf("PIWBAR%u =0x%08x\n", i, RD(REG_PIWBAR(i)));
  490                 printf("PIWBEAR%u=0x%08x\n", i, RD(REG_PIWBEAR(i)));
  491                 printf("PIWAR%u  =0x%08x\n", i, RD(REG_PIWAR(i)));
  492         }
  493         printf("\n");
  494 #undef RD
  495 
  496         for (i = 0; i < 0x48; i += 4) {
  497                 printf("cfg%02x=0x%08x\n", i, fsl_pcib_cfgread(sc, 0, 0, 0,
  498                     i, 4));
  499         }
  500 }
  501 #endif
  502 
  503 static int
  504 fsl_pcib_maxslots(device_t dev)
  505 {
  506         struct fsl_pcib_softc *sc = device_get_softc(dev);
  507 
  508         return ((sc->sc_pcie) ? 0 : PCI_SLOTMAX);
  509 }
  510 
  511 static uint32_t
  512 fsl_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
  513     u_int reg, int bytes)
  514 {
  515         struct fsl_pcib_softc *sc = device_get_softc(dev);
  516         u_int devfn;
  517 
  518         if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10)
  519                 return (~0);
  520         devfn = DEVFN(bus, slot, func);
  521         if (devfn == sc->sc_devfn_tundra)
  522                 return (~0);
  523         if (devfn == sc->sc_devfn_via_ide && reg == PCIR_INTPIN)
  524                 return (1);
  525         return (fsl_pcib_cfgread(sc, bus, slot, func, reg, bytes));
  526 }
  527 
  528 static void
  529 fsl_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
  530     u_int reg, uint32_t val, int bytes)
  531 {
  532         struct fsl_pcib_softc *sc = device_get_softc(dev);
  533 
  534         if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10)
  535                 return;
  536         fsl_pcib_cfgwrite(sc, bus, slot, func, reg, val, bytes);
  537 }
  538 
  539 static void
  540 fsl_pcib_init_via(struct fsl_pcib_softc *sc, uint16_t device, int bus,
  541     int slot, int fn)
  542 {
  543 
  544         if (device == 0x0686) {
  545                 fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x52, 0x34, 1);
  546                 fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x77, 0x00, 1);
  547                 fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x83, 0x98, 1);
  548                 fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x85, 0x03, 1);
  549         } else if (device == 0x0571) {
  550                 sc->sc_devfn_via_ide = DEVFN(bus, slot, fn);
  551                 fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x40, 0x0b, 1);
  552         }
  553 }
  554 
  555 static int
  556 fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int maxslot)
  557 {
  558         int secbus;
  559         int old_pribus, old_secbus, old_subbus;
  560         int new_pribus, new_secbus, new_subbus;
  561         int slot, func, maxfunc;
  562         uint16_t vendor, device;
  563         uint8_t command, hdrtype, subclass;
  564 
  565         secbus = bus;
  566         for (slot = 0; slot <= maxslot; slot++) {
  567                 maxfunc = 0;
  568                 for (func = 0; func <= maxfunc; func++) {
  569                         hdrtype = fsl_pcib_read_config(sc->sc_dev, bus, slot,
  570                             func, PCIR_HDRTYPE, 1);
  571 
  572                         if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
  573                                 continue;
  574 
  575                         if (func == 0 && (hdrtype & PCIM_MFDEV))
  576                                 maxfunc = PCI_FUNCMAX;
  577 
  578                         vendor = fsl_pcib_read_config(sc->sc_dev, bus, slot,
  579                             func, PCIR_VENDOR, 2);
  580                         device = fsl_pcib_read_config(sc->sc_dev, bus, slot,
  581                             func, PCIR_DEVICE, 2);
  582 
  583                         if (vendor == 0x1957 && device == 0x3fff) {
  584                                 sc->sc_devfn_tundra = DEVFN(bus, slot, func);
  585                                 continue;
  586                         }
  587 
  588                         command = fsl_pcib_read_config(sc->sc_dev, bus, slot,
  589                             func, PCIR_COMMAND, 1);
  590                         command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
  591                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
  592                             PCIR_COMMAND, command, 1);
  593 
  594                         if (vendor == 0x1106)
  595                                 fsl_pcib_init_via(sc, device, bus, slot, func);
  596 
  597                         /*
  598                          * Handle PCI-PCI bridges
  599                          */
  600                         subclass = fsl_pcib_read_config(sc->sc_dev, bus, slot,
  601                             func, PCIR_SUBCLASS, 1);
  602 
  603                         /* Allow all DEVTYPE 1 devices */
  604                         if (hdrtype != PCIM_HDRTYPE_BRIDGE)
  605                                 continue;
  606 
  607                         secbus++;
  608 
  609                         /* Read currect bus register configuration */
  610                         old_pribus = fsl_pcib_read_config(sc->sc_dev, bus,
  611                             slot, func, PCIR_PRIBUS_1, 1);
  612                         old_secbus = fsl_pcib_read_config(sc->sc_dev, bus,
  613                             slot, func, PCIR_SECBUS_1, 1);
  614                         old_subbus = fsl_pcib_read_config(sc->sc_dev, bus,
  615                             slot, func, PCIR_SUBBUS_1, 1);
  616 
  617                         if (bootverbose)
  618                                 printf("PCI: reading firmware bus numbers for "
  619                                     "secbus = %d (bus/sec/sub) = (%d/%d/%d)\n",
  620                                     secbus, old_pribus, old_secbus, old_subbus);
  621 
  622                         new_pribus = bus;
  623                         new_secbus = secbus;
  624 
  625                         secbus = fsl_pcib_init(sc, secbus,
  626                             (subclass == PCIS_BRIDGE_PCI) ? PCI_SLOTMAX : 0);
  627 
  628                         new_subbus = secbus;
  629 
  630                         if (bootverbose)
  631                                 printf("PCI: translate firmware bus numbers "
  632                                     "for secbus %d (%d/%d/%d) -> (%d/%d/%d)\n",
  633                                     secbus, old_pribus, old_secbus, old_subbus,
  634                                     new_pribus, new_secbus, new_subbus);
  635 
  636                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
  637                             PCIR_PRIBUS_1, new_pribus, 1);
  638                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
  639                             PCIR_SECBUS_1, new_secbus, 1);
  640                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
  641                             PCIR_SUBBUS_1, new_subbus, 1);
  642                 }
  643         }
  644 
  645         return (secbus);
  646 }
  647 
  648 static void
  649 fsl_pcib_inbound(struct fsl_pcib_softc *sc, int wnd, int tgt, uint64_t start,
  650     uint64_t size, uint64_t pci_start)
  651 {
  652         uint32_t attr, bar, tar;
  653 
  654         KASSERT(wnd > 0, ("%s: inbound window 0 is invalid", __func__));
  655 
  656         switch (tgt) {
  657         /* XXX OCP85XX_TGTIF_RAM2, OCP85XX_TGTIF_RAM_INTL should be handled */
  658         case OCP85XX_TGTIF_RAM1:
  659                 attr = 0xa0f55000 | (ffsl(size) - 2);
  660                 break;
  661         default:
  662                 attr = 0;
  663                 break;
  664         }
  665         tar = start >> 12;
  666         bar = pci_start >> 12;
  667 
  668         bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PITAR(wnd), tar);
  669         bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBEAR(wnd), 0);
  670         bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBAR(wnd), bar);
  671         bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWAR(wnd), attr);
  672 }
  673 
  674 static void
  675 fsl_pcib_outbound(struct fsl_pcib_softc *sc, int wnd, int res, uint64_t start,
  676     uint64_t size, uint64_t pci_start)
  677 {
  678         uint32_t attr, bar, tar;
  679 
  680         switch (res) {
  681         case SYS_RES_MEMORY:
  682                 attr = 0x80044000 | (ffsll(size) - 2);
  683                 break;
  684         case SYS_RES_IOPORT:
  685                 attr = 0x80088000 | (ffsll(size) - 2);
  686                 break;
  687         default:
  688                 attr = 0x0004401f;
  689                 break;
  690         }
  691         bar = start >> 12;
  692         tar = pci_start >> 12;
  693 
  694         bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTAR(wnd), tar);
  695         bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTEAR(wnd), 0);
  696         bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWBAR(wnd), bar);
  697         bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWAR(wnd), attr);
  698 }
  699 
  700 
  701 static void
  702 fsl_pcib_err_init(device_t dev)
  703 {
  704         struct fsl_pcib_softc *sc;
  705         uint16_t sec_stat, dsr;
  706         uint32_t dcr, err_en;
  707 
  708         sc = device_get_softc(dev);
  709 
  710         sec_stat = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_SECSTAT_1, 2);
  711         if (sec_stat)
  712                 fsl_pcib_cfgwrite(sc, 0, 0, 0, PCIR_SECSTAT_1, 0xffff, 2);
  713         if (sc->sc_pcie) {
  714                 /* Clear error bits */
  715                 bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_MES_IER,
  716                     0xffffffff);
  717                 bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_MES_DR,
  718                     0xffffffff);
  719                 bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_DR,
  720                     0xffffffff);
  721 
  722                 dsr = fsl_pcib_cfgread(sc, 0, 0, 0,
  723                     sc->sc_pcie_capreg + PCIER_DEVICE_STA, 2);
  724                 if (dsr)
  725                         fsl_pcib_cfgwrite(sc, 0, 0, 0,
  726                             sc->sc_pcie_capreg + PCIER_DEVICE_STA,
  727                             0xffff, 2);
  728 
  729                 /* Enable all errors reporting */
  730                 err_en = 0x00bfff00;
  731                 bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_EN,
  732                     err_en);
  733 
  734                 /* Enable error reporting: URR, FER, NFER */
  735                 dcr = fsl_pcib_cfgread(sc, 0, 0, 0,
  736                     sc->sc_pcie_capreg + PCIER_DEVICE_CTL, 4);
  737                 dcr |= PCIEM_CTL_URR_ENABLE | PCIEM_CTL_FER_ENABLE |
  738                     PCIEM_CTL_NFER_ENABLE;
  739                 fsl_pcib_cfgwrite(sc, 0, 0, 0,
  740                     sc->sc_pcie_capreg + PCIER_DEVICE_CTL, dcr, 4);
  741         }
  742 }
  743 
  744 static int
  745 fsl_pcib_detach(device_t dev)
  746 {
  747 
  748         if (mtx_initialized) {
  749                 mtx_destroy(&pcicfg_mtx);
  750                 mtx_initialized = 0;
  751         }
  752         return (bus_generic_detach(dev));
  753 }
  754 
  755 static int
  756 fsl_pcib_decode_win(phandle_t node, struct fsl_pcib_softc *sc)
  757 {
  758         device_t dev;
  759         int error, i, trgt;
  760 
  761         dev = sc->sc_dev;
  762 
  763         fsl_pcib_outbound(sc, 0, -1, 0, 0, 0);
  764 
  765         /*
  766          * Configure LAW decode windows.
  767          */
  768         error = law_pci_target(sc->sc_res, &sc->sc_iomem_target,
  769             &sc->sc_ioport_target);
  770         if (error != 0) {
  771                 device_printf(dev, "could not retrieve PCI LAW target info\n");
  772                 return (error);
  773         }
  774 
  775         for (i = 0; i < sc->pci_sc.sc_nrange; i++) {
  776                 switch (sc->pci_sc.sc_range[i].pci_hi &
  777                     OFW_PCI_PHYS_HI_SPACEMASK) {
  778                 case OFW_PCI_PHYS_HI_SPACE_CONFIG:
  779                         continue;
  780                 case OFW_PCI_PHYS_HI_SPACE_IO:
  781                         trgt = sc->sc_ioport_target;
  782                         fsl_pcib_outbound(sc, 2, SYS_RES_IOPORT,
  783                             sc->pci_sc.sc_range[i].host,
  784                             sc->pci_sc.sc_range[i].size,
  785                             sc->pci_sc.sc_range[i].pci);
  786                         sc->sc_ioport_start = sc->pci_sc.sc_range[i].pci;
  787                         sc->sc_ioport_end = sc->pci_sc.sc_range[i].pci +
  788                             sc->pci_sc.sc_range[i].size - 1;
  789                         break;
  790                 case OFW_PCI_PHYS_HI_SPACE_MEM32:
  791                 case OFW_PCI_PHYS_HI_SPACE_MEM64:
  792                         trgt = sc->sc_iomem_target;
  793                         fsl_pcib_outbound(sc, 1, SYS_RES_MEMORY,
  794                             sc->pci_sc.sc_range[i].host,
  795                             sc->pci_sc.sc_range[i].size,
  796                             sc->pci_sc.sc_range[i].pci);
  797                         sc->sc_iomem_start = sc->pci_sc.sc_range[i].pci;
  798                         sc->sc_iomem_end = sc->pci_sc.sc_range[i].pci +
  799                             sc->pci_sc.sc_range[i].size - 1;
  800                         break;
  801                 default:
  802                         panic("Unknown range type %#x\n",
  803                             sc->pci_sc.sc_range[i].pci_hi &
  804                             OFW_PCI_PHYS_HI_SPACEMASK);
  805                 }
  806                 error = law_enable(trgt, sc->pci_sc.sc_range[i].host,
  807                     sc->pci_sc.sc_range[i].size);
  808                 if (error != 0) {
  809                         device_printf(dev, "could not program LAW for range "
  810                             "%d\n", i);
  811                         return (error);
  812                 }
  813         }
  814 
  815         /*
  816          * Set outbout and inbound windows.
  817          */
  818         fsl_pcib_outbound(sc, 3, -1, 0, 0, 0);
  819         fsl_pcib_outbound(sc, 4, -1, 0, 0, 0);
  820 
  821         fsl_pcib_inbound(sc, 1, -1, 0, 0, 0);
  822         fsl_pcib_inbound(sc, 2, -1, 0, 0, 0);
  823         fsl_pcib_inbound(sc, 3, OCP85XX_TGTIF_RAM1, 0,
  824             2U * 1024U * 1024U * 1024U, 0);
  825 
  826         return (0);
  827 }

Cache object: e4fe6aa59cd76753650d0d71350992f3


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