summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjmallett <jmallett@FreeBSD.org>2011-01-11 02:37:58 +0000
committerjmallett <jmallett@FreeBSD.org>2011-01-11 02:37:58 +0000
commitd204f90ffeee44ead70c0909b723dc89499d29c4 (patch)
treeb8e956d1eded58f2aa519c54d14567a42b15f919
parent3e5f77d5aa1822ec5f6d0c353c36a4c256d4aa7e (diff)
downloadFreeBSD-src-d204f90ffeee44ead70c0909b723dc89499d29c4.zip
FreeBSD-src-d204f90ffeee44ead70c0909b723dc89499d29c4.tar.gz
Initialize PCIe buses and add preliminary support for 64-bit BARs.
-rw-r--r--sys/mips/cavium/octopci.c536
1 files changed, 321 insertions, 215 deletions
diff --git a/sys/mips/cavium/octopci.c b/sys/mips/cavium/octopci.c
index d065ae3..8477321 100644
--- a/sys/mips/cavium/octopci.c
+++ b/sys/mips/cavium/octopci.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org>
+ * Copyright (c) 2010-2011 Juli Mallett <jmallett@FreeBSD.org>
* 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_t, u_int, u_int, u_int, u_int,
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, device_t child, int type, int *rid,
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 bus, u_int slot, u_int func, u_int reg,
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 bus, u_int slot, u_int func,
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, device_t child, int pin)
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, device_t child, int pin)
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 b, unsigned s, unsigned f, unsigned barn
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 b, unsigned s, unsigned f, unsigned barn
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 b, unsigned s, unsigned f, unsigned barn
* 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 b, unsigned s, unsigned f, unsigned barn
* Enable memory access.
*/
*commandp |= PCIM_CMD_MEMEN;
+
+ return (barnum + barsize);
}
}
@@ -680,8 +582,9 @@ octopci_init_device(device_t dev, unsigned b, unsigned s, unsigned f, unsigned s
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 slot, unsigned func, unsigned reg)
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),
OpenPOWER on IntegriCloud