Author: jmallett
Date: Tue Jan 11 02:37:58 2011
New Revision: 217254
URL: http://svn.freebsd.org/changeset/base/217254

Log:
  Initialize PCIe buses and add preliminary support for 64-bit BARs.

Modified:
  head/sys/mips/cavium/octopci.c

Modified: head/sys/mips/cavium/octopci.c
==============================================================================
--- head/sys/mips/cavium/octopci.c      Tue Jan 11 01:57:02 2011        
(r217253)
+++ head/sys/mips/cavium/octopci.c      Tue Jan 11 02:37:58 2011        
(r217254)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2010 Juli Mallett <[email protected]>
+ * Copyright (c) 2010-2011 Juli Mallett <[email protected]>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
 
 #include <contrib/octeon-sdk/cvmx.h>
 #include <contrib/octeon-sdk/cvmx-interrupt.h>
+#include <contrib/octeon-sdk/cvmx-pcie.h>
 
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
@@ -70,9 +71,11 @@ struct octopci_softc {
        unsigned sc_domain;
        unsigned sc_bus;
 
+       bus_addr_t sc_io_base;
        unsigned sc_io_next;
        struct rman sc_io;
 
+       bus_addr_t sc_mem1_base;
        unsigned sc_mem1_next;
        struct rman sc_mem1;
 };
@@ -92,25 +95,33 @@ static void octopci_write_config(device_
                                     uint32_t, int);
 static int     octopci_route_interrupt(device_t, device_t, int);
 
-static void    octopci_init_bar(device_t, unsigned, unsigned, unsigned, 
unsigned, uint8_t *);
+static unsigned        octopci_init_bar(device_t, unsigned, unsigned, 
unsigned, unsigned, uint8_t *);
 static unsigned        octopci_init_device(device_t, unsigned, unsigned, 
unsigned, unsigned);
 static unsigned        octopci_init_bus(device_t, unsigned);
+static void    octopci_init_pci(device_t);
 static uint64_t        octopci_cs_addr(unsigned, unsigned, unsigned, unsigned);
 
 static void
 octopci_identify(driver_t *drv, device_t parent)
 {
+       /* XXX Check sysinfo flag.  */
+
        BUS_ADD_CHILD(parent, 0, "pcib", 0);
+       if (octeon_has_feature(OCTEON_FEATURE_PCIE))
+               BUS_ADD_CHILD(parent, 0, "pcib", 1);
 }
 
 static int
 octopci_probe(device_t dev)
 {
+       if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+               device_set_desc(dev, "Cavium Octeon PCIe bridge");
+               return (0);
+       }
+
        if (device_get_unit(dev) != 0)
                return (ENXIO);
-       if (octeon_has_feature(OCTEON_FEATURE_PCIE))
-               return (ENXIO);
-       /* XXX Check sysinfo flag.  */
+
        device_set_desc(dev, "Cavium Octeon PCI bridge");
        return (0);
 }
@@ -119,214 +130,47 @@ static int
 octopci_attach(device_t dev)
 {
        struct octopci_softc *sc;
-       cvmx_npi_mem_access_subid_t npi_mem_access_subid;
-       cvmx_npi_pci_int_arb_cfg_t npi_pci_int_arb_cfg;
-       cvmx_npi_ctl_status_t npi_ctl_status;
-       cvmx_pci_ctl_status_2_t pci_ctl_status_2;
-       cvmx_pci_cfg56_t pci_cfg56;
-       cvmx_pci_cfg22_t pci_cfg22;
-       cvmx_pci_cfg16_t pci_cfg16;
-       cvmx_pci_cfg19_t pci_cfg19;
-       cvmx_pci_cfg01_t pci_cfg01;
        unsigned subbus;
-       unsigned i;
        int error;
 
-       /*
-        * Reset the PCI bus.
-        */
-       cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x1);
-       cvmx_read_csr(CVMX_CIU_SOFT_PRST);
-
-       DELAY(2000);
-
-       npi_ctl_status.u64 = 0;
-       npi_ctl_status.s.max_word = 1;
-       npi_ctl_status.s.timer = 1;
-       cvmx_write_csr(CVMX_NPI_CTL_STATUS, npi_ctl_status.u64);
-
-       /*
-        * Set host mode.
-        */
-       switch (cvmx_sysinfo_get()->board_type) {
-#if defined(OCTEON_VENDOR_LANNER)
-       case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
-       case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
-               /* 32-bit PCI-X */
-               cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x0);
-               break;
-#endif
-       default:
-               /* 64-bit PCI-X */
-               cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x4);
-               break;
-       }
-       cvmx_read_csr(CVMX_CIU_SOFT_PRST);
-
-       DELAY(2000);
-
-       /*
-        * Enable BARs and configure big BAR mode.
-        */
-       pci_ctl_status_2.u32 = 0;
-       pci_ctl_status_2.s.bb1_hole = 5; /* 256MB hole in BAR1 */
-       pci_ctl_status_2.s.bb1_siz = 1; /* BAR1 is 2GB */
-       pci_ctl_status_2.s.bb_ca = 1; /* Bypass cache for big BAR */
-       pci_ctl_status_2.s.bb_es = 1; /* Do big BAR byte-swapping */
-       pci_ctl_status_2.s.bb1 = 1; /* BAR1 is big */
-       pci_ctl_status_2.s.bb0 = 1; /* BAR0 is big */
-       pci_ctl_status_2.s.bar2pres = 1; /* BAR2 present */
-       pci_ctl_status_2.s.pmo_amod = 1; /* Round-robin priority */
-       pci_ctl_status_2.s.tsr_hwm = 1;
-       pci_ctl_status_2.s.bar2_enb = 1; /* Enable BAR2 */
-       pci_ctl_status_2.s.bar2_esx = 1; /* Do BAR2 byte-swapping */
-       pci_ctl_status_2.s.bar2_cax = 1; /* Bypass cache for BAR2 */
+       sc = device_get_softc(dev);
+       sc->sc_dev = dev;
 
-       NPI_WRITE(CVMX_NPI_PCI_CTL_STATUS_2, pci_ctl_status_2.u32);
+       if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+               sc->sc_domain = device_get_unit(dev);
 
-       DELAY(2000);
+               error = cvmx_pcie_rc_initialize(sc->sc_domain);
+               if (error != 0) {
+                       device_printf(dev, "Failed to put PCIe bus in host 
mode.\n");
+                       return (ENXIO);
+               }
 
-       pci_ctl_status_2.u32 = NPI_READ(CVMX_NPI_PCI_CTL_STATUS_2);
+               /*
+                * In RC mode, the Simple Executive programs the first bus to
+                * be numbered as bus 1, because some IDT bridges used in
+                * Octeon systems object to being attached to bus 0.
+                */
+               sc->sc_bus = 1;
 
-       device_printf(dev, "%u-bit PCI%s bus.\n",
-           pci_ctl_status_2.s.ap_64ad ? 64 : 32,
-           pci_ctl_status_2.s.ap_pcix ? "-X" : "");
+               sc->sc_io_base = 
CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(sc->sc_domain));
+               sc->sc_io.rm_descr = "Cavium Octeon PCIe I/O Ports";
 
-       /*
-        * Set up transaction splitting, etc., parameters.
-        */
-       pci_cfg19.u32 = 0;
-       pci_cfg19.s.mrbcm = 1;
-       if (pci_ctl_status_2.s.ap_pcix) {
-               pci_cfg19.s.mdrrmc = 0;
-               pci_cfg19.s.tdomc = 4;
+               sc->sc_mem1_base = 
CVMX_ADD_IO_SEG(cvmx_pcie_get_mem_base_address(sc->sc_domain));
+               sc->sc_mem1.rm_descr = "Cavium Octeon PCIe Memory";
        } else {
-               pci_cfg19.s.mdrrmc = 2;
-               pci_cfg19.s.tdomc = 1;
-       }
-       NPI_WRITE(CVMX_NPI_PCI_CFG19, pci_cfg19.u32);
-       NPI_READ(CVMX_NPI_PCI_CFG19);
+               octopci_init_pci(dev);
 
-       /*
-        * Set up PCI error handling and memory access.
-        */
-       pci_cfg01.u32 = 0;
-       pci_cfg01.s.fbbe = 1;
-       pci_cfg01.s.see = 1;
-       pci_cfg01.s.pee = 1;
-       pci_cfg01.s.me = 1;
-       pci_cfg01.s.msae = 1;
-       if (pci_ctl_status_2.s.ap_pcix) {
-               pci_cfg01.s.fbb = 0;
-       } else {
-               pci_cfg01.s.fbb = 1;
-       }
-       NPI_WRITE(CVMX_NPI_PCI_CFG01, pci_cfg01.u32);
-       NPI_READ(CVMX_NPI_PCI_CFG01);
-
-       /*
-        * Enable the Octeon bus arbiter.
-        */
-       npi_pci_int_arb_cfg.u64 = 0;
-       npi_pci_int_arb_cfg.s.en = 1;
-       cvmx_write_csr(CVMX_NPI_PCI_INT_ARB_CFG, npi_pci_int_arb_cfg.u64);
-
-       /*
-        * Disable master latency timer.
-        */
-       pci_cfg16.u32 = 0;
-       pci_cfg16.s.mltd = 1;
-       NPI_WRITE(CVMX_NPI_PCI_CFG16, pci_cfg16.u32);
-       NPI_READ(CVMX_NPI_PCI_CFG16);
-
-       /*
-        * Configure master arbiter.
-        */
-       pci_cfg22.u32 = 0;
-       pci_cfg22.s.flush = 1;
-       pci_cfg22.s.mrv = 255;
-       NPI_WRITE(CVMX_NPI_PCI_CFG22, pci_cfg22.u32);
-       NPI_READ(CVMX_NPI_PCI_CFG22);
-
-       /*
-        * Set up PCI-X capabilities.
-        */
-       if (pci_ctl_status_2.s.ap_pcix) {
-               pci_cfg56.u32 = 0;
-               pci_cfg56.s.most = 3;
-               pci_cfg56.s.roe = 1; /* Enable relaxed ordering */
-               pci_cfg56.s.dpere = 1;
-               pci_cfg56.s.ncp = 0xe8;
-               pci_cfg56.s.pxcid = 7;
-               NPI_WRITE(CVMX_NPI_PCI_CFG56, pci_cfg56.u32);
-               NPI_READ(CVMX_NPI_PCI_CFG56);
-       }
-
-       NPI_WRITE(CVMX_NPI_PCI_READ_CMD_6, 0x22);
-       NPI_READ(CVMX_NPI_PCI_READ_CMD_6);
-       NPI_WRITE(CVMX_NPI_PCI_READ_CMD_C, 0x33);
-       NPI_READ(CVMX_NPI_PCI_READ_CMD_C);
-       NPI_WRITE(CVMX_NPI_PCI_READ_CMD_E, 0x33);
-       NPI_READ(CVMX_NPI_PCI_READ_CMD_E);
-
-       /*
-        * Configure MEM1 sub-DID access.
-        */
-       npi_mem_access_subid.u64 = 0;
-       npi_mem_access_subid.s.esr = 1; /* Byte-swap on read */
-       npi_mem_access_subid.s.esw = 1; /* Byte-swap on write */
-       switch (cvmx_sysinfo_get()->board_type) {
-#if defined(OCTEON_VENDOR_LANNER)
-       case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
-               npi_mem_access_subid.s.shortl = 1;
-               break;
-#endif
-       default:
-               break;
-       }
-       cvmx_write_csr(CVMX_NPI_MEM_ACCESS_SUBID3, npi_mem_access_subid.u64);
+               sc->sc_domain = 0;
+               sc->sc_bus = 0;
 
-       /*
-        * Configure BAR2.  Linux says this has to come first.
-        */
-       NPI_WRITE(CVMX_NPI_PCI_CFG08, 0x00000000);
-       NPI_READ(CVMX_NPI_PCI_CFG08);
-       NPI_WRITE(CVMX_NPI_PCI_CFG09, 0x00000080);
-       NPI_READ(CVMX_NPI_PCI_CFG09);
+               sc->sc_io_base = CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI, 
CVMX_OCT_SUBDID_PCI_IO));
+               sc->sc_io.rm_descr = "Cavium Octeon PCI I/O Ports";
 
-       /*
-        * Disable BAR1 IndexX.
-        */
-       for (i = 0; i < 32; i++) {
-               NPI_WRITE(CVMX_NPI_PCI_BAR1_INDEXX(i), 0);
-               NPI_READ(CVMX_NPI_PCI_BAR1_INDEXX(i));
+               sc->sc_mem1_base = 
CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI, CVMX_OCT_SUBDID_PCI_MEM1));
+               sc->sc_mem1.rm_descr = "Cavium Octeon PCI Memory";
        }
 
-       /*
-        * Configure BAR0 and BAR1.
-        */
-       NPI_WRITE(CVMX_NPI_PCI_CFG04, 0x00000000);
-       NPI_READ(CVMX_NPI_PCI_CFG04);
-       NPI_WRITE(CVMX_NPI_PCI_CFG05, 0x00000000);
-       NPI_READ(CVMX_NPI_PCI_CFG05);
-
-       NPI_WRITE(CVMX_NPI_PCI_CFG06, 0x80000000);
-       NPI_READ(CVMX_NPI_PCI_CFG06);
-       NPI_WRITE(CVMX_NPI_PCI_CFG07, 0x00000000);
-       NPI_READ(CVMX_NPI_PCI_CFG07);
-
-       /*
-        * Clear PCI interrupts.
-        */
-       cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, 0xffffffffffffffffull);
-
-       sc = device_get_softc(dev);
-       sc->sc_dev = dev;
-       sc->sc_domain = 0;
-       sc->sc_bus = 0;
-
        sc->sc_io.rm_type = RMAN_ARRAY;
-       sc->sc_io.rm_descr = "Cavium Octeon PCI I/O Ports";
        error = rman_init(&sc->sc_io);
        if (error != 0)
                return (error);
@@ -337,7 +181,6 @@ octopci_attach(device_t dev)
                return (error);
 
        sc->sc_mem1.rm_type = RMAN_ARRAY;
-       sc->sc_mem1.rm_descr = "Cavium Octeon PCI Memory";
        error = rman_init(&sc->sc_mem1);
        if (error != 0)
                return (error);
@@ -356,11 +199,11 @@ octopci_attach(device_t dev)
        /*
         * Configure devices.
         */
-       octopci_write_config(dev, 0, 0, 0, PCIR_SUBBUS_1, 0xff, 1);
-       subbus = octopci_init_bus(dev, 0);
-       octopci_write_config(dev, 0, 0, 0, PCIR_SUBBUS_1, subbus, 1);
+       octopci_write_config(dev, sc->sc_bus, 0, 0, PCIR_SUBBUS_1, 0xff, 1);
+       subbus = octopci_init_bus(dev, sc->sc_bus);
+       octopci_write_config(dev, sc->sc_bus, 0, 0, PCIR_SUBBUS_1, subbus, 1);
 
-       device_add_child(dev, "pci", 0);
+       device_add_child(dev, "pci", device_get_unit(dev));
 
        return (bus_generic_attach(dev));
 }
@@ -421,10 +264,10 @@ octopci_alloc_resource(device_t bus, dev
 
        switch (type) {
        case SYS_RES_MEMORY:
-               rman_set_bushandle(res, 
CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI, CVMX_OCT_SUBDID_PCI_MEM1)) + 
rman_get_start(res));
+               rman_set_bushandle(res, sc->sc_mem1_base + rman_get_start(res));
                break;
        case SYS_RES_IOPORT:
-               rman_set_bushandle(res, 
CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI, CVMX_OCT_SUBDID_PCI_IO)) + 
rman_get_start(res));
+               rman_set_bushandle(res, sc->sc_io_base + rman_get_start(res));
 #if __mips_n64
                rman_set_virtual(res, (void *)rman_get_bushandle(res));
 #else
@@ -496,6 +339,22 @@ octopci_read_config(device_t dev, u_int 
 
        sc = device_get_softc(dev);
 
+       if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+               if (bus == 0 && slot == 0 && func == 0)
+                       return ((uint32_t)-1);
+
+               switch (bytes) {
+               case 4:
+                       return (cvmx_pcie_config_read32(sc->sc_domain, bus, 
slot, func, reg));
+               case 2:
+                       return (cvmx_pcie_config_read16(sc->sc_domain, bus, 
slot, func, reg));
+               case 1:
+                       return (cvmx_pcie_config_read8(sc->sc_domain, bus, 
slot, func, reg));
+               default:
+                       return ((uint32_t)-1);
+               }
+       }
+
        addr = octopci_cs_addr(bus, slot, func, reg);
 
        switch (bytes) {
@@ -522,6 +381,22 @@ octopci_write_config(device_t dev, u_int
 
        sc = device_get_softc(dev);
 
+       if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+               switch (bytes) {
+               case 4:
+                       cvmx_pcie_config_write32(sc->sc_domain, bus, slot, 
func, reg, data);
+                       return;
+               case 2:
+                       cvmx_pcie_config_write16(sc->sc_domain, bus, slot, 
func, reg, data);
+                       return;
+               case 1:
+                       cvmx_pcie_config_write8(sc->sc_domain, bus, slot, func, 
reg, data);
+                       return;
+               default:
+                       return;
+               }
+       }
+
        addr = octopci_cs_addr(bus, slot, func, reg);
 
        switch (bytes) {
@@ -548,6 +423,9 @@ octopci_route_interrupt(device_t dev, de
 
        sc = device_get_softc(dev);
 
+       if (octeon_has_feature(OCTEON_FEATURE_PCIE))
+               return (CVMX_IRQ_PCI_INT0 + pin - 1);
+
         bus = pci_get_bus(child);
         slot = pci_get_slot(child);
         func = pci_get_function(child);
@@ -586,12 +464,13 @@ octopci_route_interrupt(device_t dev, de
        return (CVMX_IRQ_PCI_INT0 + (irq & 3));
 }
 
-static void
+static unsigned
 octopci_init_bar(device_t dev, unsigned b, unsigned s, unsigned f, unsigned 
barnum, uint8_t *commandp)
 {
        struct octopci_softc *sc;
-       uint32_t bar;
+       uint64_t bar;
        unsigned size;
+       int barsize;
 
        sc = device_get_softc(dev);
 
@@ -599,12 +478,10 @@ octopci_init_bar(device_t dev, unsigned 
        bar = octopci_read_config(dev, b, s, f, PCIR_BAR(barnum), 4);
 
        if (bar == 0) {
-               /* Bar not implemented.  */
-               return;
+               /* Bar not implemented; got to next bar.  */
+               return (barnum + 1);
        }
 
-       /* XXX Some of this is wrong for 64-bit busses.  */
-
        if (PCI_BAR_IO(bar)) {
                size = ~(bar & PCIM_BAR_IO_BASE) + 1;
 
@@ -612,7 +489,7 @@ octopci_init_bar(device_t dev, unsigned 
                if (sc->sc_io_next + size > CVMX_OCT_PCI_IO_SIZE) {
                        device_printf(dev, "%02x.%02x:%02x: no ports for 
BAR%u.\n",
                            b, s, f, barnum);
-                       return;
+                       return (barnum + 1);
                }
                octopci_write_config(dev, b, s, f, PCIR_BAR(barnum),
                    CVMX_OCT_PCI_IO_BASE + sc->sc_io_next, 4);
@@ -622,14 +499,37 @@ octopci_init_bar(device_t dev, unsigned 
                 * Enable I/O ports.
                 */
                *commandp |= PCIM_CMD_PORTEN;
+
+               return (barnum + 1);
        } else {
+               if (PCIR_BAR(barnum) == PCIR_BIOS) {
+                       /*
+                        * ROM BAR is always 32-bit.
+                        */
+                       barsize = 1;
+               } else {
+                       switch (bar & PCIM_BAR_MEM_TYPE) {
+                       case PCIM_BAR_MEM_64:
+                               /*
+                                * XXX
+                                * High 32 bits are all zeroes for now.
+                                */
+                               octopci_write_config(dev, b, s, f, 
PCIR_BAR(barnum + 1), 0, 4);
+                               barsize = 2;
+                               break;
+                       default:
+                               barsize = 1;
+                               break;
+                       }
+               }
+
                size = ~(bar & (uint32_t)PCIM_BAR_MEM_BASE) + 1;
 
                sc->sc_mem1_next = (sc->sc_mem1_next + size - 1) & ~(size - 1);
                if (sc->sc_mem1_next + size > CVMX_OCT_PCI_MEM1_SIZE) {
                        device_printf(dev, "%02x.%02x:%02x: no memory for 
BAR%u.\n",
                            b, s, f, barnum);
-                       return;
+                       return (barnum + barsize);
                }
                octopci_write_config(dev, b, s, f, PCIR_BAR(barnum),
                    CVMX_OCT_PCI_MEM1_BASE + sc->sc_mem1_next, 4);
@@ -639,6 +539,8 @@ octopci_init_bar(device_t dev, unsigned 
                 * Enable memory access.
                 */
                *commandp |= PCIM_CMD_MEMEN;
+
+               return (barnum + barsize);
        }
 }
 
@@ -680,8 +582,9 @@ octopci_init_device(device_t dev, unsign
                return (secbus);
        }
 
-       for (barnum = 0; barnum < bars; barnum++)
-               octopci_init_bar(dev, b, s, f, barnum, &command);
+       barnum = 0;
+       while (barnum < bars)
+               barnum = octopci_init_bar(dev, b, s, f, barnum, &command);
 
        /* Enable bus mastering.  */
        command |= PCIM_CMD_BUSMASTEREN;
@@ -848,6 +751,209 @@ octopci_cs_addr(unsigned bus, unsigned s
        return (pci_addr.u64);
 }
 
+static void
+octopci_init_pci(device_t dev)
+{
+       cvmx_npi_mem_access_subid_t npi_mem_access_subid;
+       cvmx_npi_pci_int_arb_cfg_t npi_pci_int_arb_cfg;
+       cvmx_npi_ctl_status_t npi_ctl_status;
+       cvmx_pci_ctl_status_2_t pci_ctl_status_2;
+       cvmx_pci_cfg56_t pci_cfg56;
+       cvmx_pci_cfg22_t pci_cfg22;
+       cvmx_pci_cfg16_t pci_cfg16;
+       cvmx_pci_cfg19_t pci_cfg19;
+       cvmx_pci_cfg01_t pci_cfg01;
+       unsigned i;
+
+       /*
+        * Reset the PCI bus.
+        */
+       cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x1);
+       cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+
+       DELAY(2000);
+
+       npi_ctl_status.u64 = 0;
+       npi_ctl_status.s.max_word = 1;
+       npi_ctl_status.s.timer = 1;
+       cvmx_write_csr(CVMX_NPI_CTL_STATUS, npi_ctl_status.u64);
+
+       /*
+        * Set host mode.
+        */
+       switch (cvmx_sysinfo_get()->board_type) {
+#if defined(OCTEON_VENDOR_LANNER)
+       case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
+       case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
+               /* 32-bit PCI-X */
+               cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x0);
+               break;
+#endif
+       default:
+               /* 64-bit PCI-X */
+               cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x4);
+               break;
+       }
+       cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+
+       DELAY(2000);
+
+       /*
+        * Enable BARs and configure big BAR mode.
+        */
+       pci_ctl_status_2.u32 = 0;
+       pci_ctl_status_2.s.bb1_hole = 5; /* 256MB hole in BAR1 */
+       pci_ctl_status_2.s.bb1_siz = 1; /* BAR1 is 2GB */
+       pci_ctl_status_2.s.bb_ca = 1; /* Bypass cache for big BAR */
+       pci_ctl_status_2.s.bb_es = 1; /* Do big BAR byte-swapping */
+       pci_ctl_status_2.s.bb1 = 1; /* BAR1 is big */
+       pci_ctl_status_2.s.bb0 = 1; /* BAR0 is big */
+       pci_ctl_status_2.s.bar2pres = 1; /* BAR2 present */
+       pci_ctl_status_2.s.pmo_amod = 1; /* Round-robin priority */
+       pci_ctl_status_2.s.tsr_hwm = 1;
+       pci_ctl_status_2.s.bar2_enb = 1; /* Enable BAR2 */
+       pci_ctl_status_2.s.bar2_esx = 1; /* Do BAR2 byte-swapping */
+       pci_ctl_status_2.s.bar2_cax = 1; /* Bypass cache for BAR2 */
+
+       NPI_WRITE(CVMX_NPI_PCI_CTL_STATUS_2, pci_ctl_status_2.u32);
+
+       DELAY(2000);
+
+       pci_ctl_status_2.u32 = NPI_READ(CVMX_NPI_PCI_CTL_STATUS_2);
+
+       device_printf(dev, "%u-bit PCI%s bus.\n",
+           pci_ctl_status_2.s.ap_64ad ? 64 : 32,
+           pci_ctl_status_2.s.ap_pcix ? "-X" : "");
+
+       /*
+        * Set up transaction splitting, etc., parameters.
+        */
+       pci_cfg19.u32 = 0;
+       pci_cfg19.s.mrbcm = 1;
+       if (pci_ctl_status_2.s.ap_pcix) {
+               pci_cfg19.s.mdrrmc = 0;
+               pci_cfg19.s.tdomc = 4;
+       } else {
+               pci_cfg19.s.mdrrmc = 2;
+               pci_cfg19.s.tdomc = 1;
+       }
+       NPI_WRITE(CVMX_NPI_PCI_CFG19, pci_cfg19.u32);
+       NPI_READ(CVMX_NPI_PCI_CFG19);
+
+       /*
+        * Set up PCI error handling and memory access.
+        */
+       pci_cfg01.u32 = 0;
+       pci_cfg01.s.fbbe = 1;
+       pci_cfg01.s.see = 1;
+       pci_cfg01.s.pee = 1;
+       pci_cfg01.s.me = 1;
+       pci_cfg01.s.msae = 1;
+       if (pci_ctl_status_2.s.ap_pcix) {
+               pci_cfg01.s.fbb = 0;
+       } else {
+               pci_cfg01.s.fbb = 1;
+       }
+       NPI_WRITE(CVMX_NPI_PCI_CFG01, pci_cfg01.u32);
+       NPI_READ(CVMX_NPI_PCI_CFG01);
+
+       /*
+        * Enable the Octeon bus arbiter.
+        */
+       npi_pci_int_arb_cfg.u64 = 0;
+       npi_pci_int_arb_cfg.s.en = 1;
+       cvmx_write_csr(CVMX_NPI_PCI_INT_ARB_CFG, npi_pci_int_arb_cfg.u64);
+
+       /*
+        * Disable master latency timer.
+        */
+       pci_cfg16.u32 = 0;
+       pci_cfg16.s.mltd = 1;
+       NPI_WRITE(CVMX_NPI_PCI_CFG16, pci_cfg16.u32);
+       NPI_READ(CVMX_NPI_PCI_CFG16);
+
+       /*
+        * Configure master arbiter.
+        */
+       pci_cfg22.u32 = 0;
+       pci_cfg22.s.flush = 1;
+       pci_cfg22.s.mrv = 255;
+       NPI_WRITE(CVMX_NPI_PCI_CFG22, pci_cfg22.u32);
+       NPI_READ(CVMX_NPI_PCI_CFG22);
+
+       /*
+        * Set up PCI-X capabilities.
+        */
+       if (pci_ctl_status_2.s.ap_pcix) {
+               pci_cfg56.u32 = 0;
+               pci_cfg56.s.most = 3;
+               pci_cfg56.s.roe = 1; /* Enable relaxed ordering */
+               pci_cfg56.s.dpere = 1;
+               pci_cfg56.s.ncp = 0xe8;
+               pci_cfg56.s.pxcid = 7;
+               NPI_WRITE(CVMX_NPI_PCI_CFG56, pci_cfg56.u32);
+               NPI_READ(CVMX_NPI_PCI_CFG56);
+       }
+
+       NPI_WRITE(CVMX_NPI_PCI_READ_CMD_6, 0x22);
+       NPI_READ(CVMX_NPI_PCI_READ_CMD_6);
+       NPI_WRITE(CVMX_NPI_PCI_READ_CMD_C, 0x33);
+       NPI_READ(CVMX_NPI_PCI_READ_CMD_C);
+       NPI_WRITE(CVMX_NPI_PCI_READ_CMD_E, 0x33);
+       NPI_READ(CVMX_NPI_PCI_READ_CMD_E);
+
+       /*
+        * Configure MEM1 sub-DID access.
+        */
+       npi_mem_access_subid.u64 = 0;
+       npi_mem_access_subid.s.esr = 1; /* Byte-swap on read */
+       npi_mem_access_subid.s.esw = 1; /* Byte-swap on write */
+       switch (cvmx_sysinfo_get()->board_type) {
+#if defined(OCTEON_VENDOR_LANNER)
+       case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
+               npi_mem_access_subid.s.shortl = 1;
+               break;
+#endif
+       default:
+               break;
+       }
+       cvmx_write_csr(CVMX_NPI_MEM_ACCESS_SUBID3, npi_mem_access_subid.u64);
+
+       /*
+        * Configure BAR2.  Linux says this has to come first.
+        */
+       NPI_WRITE(CVMX_NPI_PCI_CFG08, 0x00000000);
+       NPI_READ(CVMX_NPI_PCI_CFG08);
+       NPI_WRITE(CVMX_NPI_PCI_CFG09, 0x00000080);
+       NPI_READ(CVMX_NPI_PCI_CFG09);
+
+       /*
+        * Disable BAR1 IndexX.
+        */
+       for (i = 0; i < 32; i++) {
+               NPI_WRITE(CVMX_NPI_PCI_BAR1_INDEXX(i), 0);
+               NPI_READ(CVMX_NPI_PCI_BAR1_INDEXX(i));
+       }
+
+       /*
+        * Configure BAR0 and BAR1.
+        */
+       NPI_WRITE(CVMX_NPI_PCI_CFG04, 0x00000000);
+       NPI_READ(CVMX_NPI_PCI_CFG04);
+       NPI_WRITE(CVMX_NPI_PCI_CFG05, 0x00000000);
+       NPI_READ(CVMX_NPI_PCI_CFG05);
+
+       NPI_WRITE(CVMX_NPI_PCI_CFG06, 0x80000000);
+       NPI_READ(CVMX_NPI_PCI_CFG06);
+       NPI_WRITE(CVMX_NPI_PCI_CFG07, 0x00000000);
+       NPI_READ(CVMX_NPI_PCI_CFG07);
+
+       /*
+        * Clear PCI interrupts.
+        */
+       cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, 0xffffffffffffffffull);
+}
+
 static device_method_t octopci_methods[] = {
        /* Device interface */
        DEVMETHOD(device_identify,      octopci_identify),
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to