Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Jan 2011 02:37:58 +0000 (UTC)
From:      Juli Mallett <jmallett@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r217254 - head/sys/mips/cavium
Message-ID:  <201101110237.p0B2bwUC003454@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <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_
 				     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),



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201101110237.p0B2bwUC003454>