static int __cvmx_pcie_rc_initialize_gen1()

in pci/pcie-octeon.c [691:1078]


static int __cvmx_pcie_rc_initialize_gen1(int pcie_port)
{
	int i;
	int base;
	u64 addr_swizzle;
	union cvmx_ciu_soft_prst ciu_soft_prst;
	union cvmx_pescx_bist_status pescx_bist_status;
	union cvmx_pescx_bist_status2 pescx_bist_status2;
	union cvmx_npei_ctl_status npei_ctl_status;
	union cvmx_npei_mem_access_ctl npei_mem_access_ctl;
	union cvmx_npei_mem_access_subidx mem_access_subid;
	union cvmx_npei_dbg_data npei_dbg_data;
	union cvmx_pescx_ctl_status2 pescx_ctl_status2;
	union cvmx_pciercx_cfg032 pciercx_cfg032;
	union cvmx_npei_bar1_indexx bar1_index;

retry:
	/*
	 * Make sure we aren't trying to setup a target mode interface
	 * in host mode.
	 */
	npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS);
	if ((pcie_port == 0) && !npei_ctl_status.s.host_mode) {
		cvmx_dprintf("PCIe: Port %d in endpoint mode\n", pcie_port);
		return -1;
	}

	/*
	 * Make sure a CN52XX isn't trying to bring up port 1 when it
	 * is disabled.
	 */
	if (OCTEON_IS_MODEL(OCTEON_CN52XX)) {
		npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
		if ((pcie_port == 1) && npei_dbg_data.cn52xx.qlm0_link_width) {
			cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called on port1, but port1 is disabled\n");
			return -1;
		}
	}

	/*
	 * PCIe switch arbitration mode. '0' == fixed priority NPEI,
	 * PCIe0, then PCIe1. '1' == round robin.
	 */
	npei_ctl_status.s.arb = 1;
	/* Allow up to 0x20 config retries */
	npei_ctl_status.s.cfg_rtry = 0x20;
	/*
	 * CN52XX pass1.x has an errata where P0_NTAGS and P1_NTAGS
	 * don't reset.
	 */
	if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
		npei_ctl_status.s.p0_ntags = 0x20;
		npei_ctl_status.s.p1_ntags = 0x20;
	}
	cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS, npei_ctl_status.u64);

	/* Bring the PCIe out of reset */
	if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) {
		/*
		 * The EBH5200 board swapped the PCIe reset lines on
		 * the board. As a workaround for this bug, we bring
		 * both PCIe ports out of reset at the same time
		 * instead of on separate calls. So for port 0, we
		 * bring both out of reset and do nothing on port 1
		 */
		if (pcie_port == 0) {
			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
			/*
			 * After a chip reset the PCIe will also be in
			 * reset. If it isn't, most likely someone is
			 * trying to init it again without a proper
			 * PCIe reset.
			 */
			if (ciu_soft_prst.s.soft_prst == 0) {
				/* Reset the ports */
				ciu_soft_prst.s.soft_prst = 1;
				cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64);
				ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
				ciu_soft_prst.s.soft_prst = 1;
				cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64);
				/* Wait until pcie resets the ports. */
				udelay(2000);
			}
			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
			ciu_soft_prst.s.soft_prst = 0;
			cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64);
			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
			ciu_soft_prst.s.soft_prst = 0;
			cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64);
		}
	} else {
		/*
		 * The normal case: The PCIe ports are completely
		 * separate and can be brought out of reset
		 * independently.
		 */
		if (pcie_port)
			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
		else
			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
		/*
		 * After a chip reset the PCIe will also be in
		 * reset. If it isn't, most likely someone is trying
		 * to init it again without a proper PCIe reset.
		 */
		if (ciu_soft_prst.s.soft_prst == 0) {
			/* Reset the port */
			ciu_soft_prst.s.soft_prst = 1;
			if (pcie_port)
				cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64);
			else
				cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64);
			/* Wait until pcie resets the ports. */
			udelay(2000);
		}
		if (pcie_port) {
			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
			ciu_soft_prst.s.soft_prst = 0;
			cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64);
		} else {
			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
			ciu_soft_prst.s.soft_prst = 0;
			cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64);
		}
	}

	/*
	 * Wait for PCIe reset to complete. Due to errata PCIE-700, we
	 * don't poll PESCX_CTL_STATUS2[PCIERST], but simply wait a
	 * fixed number of cycles.
	 */
	__delay(400000);

	/*
	 * PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of
	 * CN56XX and CN52XX, so we only probe it on newer chips
	 */
	if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
		/* Clear PCLK_RUN so we can check if the clock is running */
		pescx_ctl_status2.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port));
		pescx_ctl_status2.s.pclk_run = 1;
		cvmx_write_csr(CVMX_PESCX_CTL_STATUS2(pcie_port), pescx_ctl_status2.u64);
		/* Now that we cleared PCLK_RUN, wait for it to be set
		 * again telling us the clock is running
		 */
		if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CTL_STATUS2(pcie_port),
					  union cvmx_pescx_ctl_status2, pclk_run, ==, 1, 10000)) {
			cvmx_dprintf("PCIe: Port %d isn't clocked, skipping.\n", pcie_port);
			return -1;
		}
	}

	/*
	 * Check and make sure PCIe came out of reset. If it doesn't
	 * the board probably hasn't wired the clocks up and the
	 * interface should be skipped.
	 */
	pescx_ctl_status2.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port));
	if (pescx_ctl_status2.s.pcierst) {
		cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n", pcie_port);
		return -1;
	}

	/*
	 * Check BIST2 status. If any bits are set skip this
	 * interface. This is an attempt to catch PCIE-813 on pass 1
	 * parts.
	 */
	pescx_bist_status2.u64 = cvmx_read_csr(CVMX_PESCX_BIST_STATUS2(pcie_port));
	if (pescx_bist_status2.u64) {
		cvmx_dprintf("PCIe: Port %d BIST2 failed. Most likely this port isn't hooked up, skipping.\n",
			     pcie_port);
		return -1;
	}

	/* Check BIST status */
	pescx_bist_status.u64 = cvmx_read_csr(CVMX_PESCX_BIST_STATUS(pcie_port));
	if (pescx_bist_status.u64)
		cvmx_dprintf("PCIe: BIST FAILED for port %d (0x%016llx)\n",
			     pcie_port, CAST64(pescx_bist_status.u64));

	/* Initialize the config space CSRs */
	__cvmx_pcie_rc_initialize_config_space(pcie_port);

	/* Bring the link up */
	if (__cvmx_pcie_rc_initialize_link_gen1(pcie_port)) {
		cvmx_dprintf("PCIe: Failed to initialize port %d, probably the slot is empty\n",
			     pcie_port);
		return -1;
	}

	/* Store merge control (NPEI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */
	npei_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL);
	npei_mem_access_ctl.s.max_word = 0;	/* Allow 16 words to combine */
	npei_mem_access_ctl.s.timer = 127;	/* Wait up to 127 cycles for more data */
	cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL, npei_mem_access_ctl.u64);

	/* Setup Mem access SubDIDs */
	mem_access_subid.u64 = 0;
	mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */
	mem_access_subid.s.nmerge = 1;	/* Due to an errata on pass 1 chips, no merging is allowed. */
	mem_access_subid.s.esr = 1;	/* Endian-swap for Reads. */
	mem_access_subid.s.esw = 1;	/* Endian-swap for Writes. */
	mem_access_subid.s.nsr = 0;	/* Enable Snooping for Reads. Octeon doesn't care, but devices might want this more conservative setting */
	mem_access_subid.s.nsw = 0;	/* Enable Snoop for Writes. */
	mem_access_subid.s.ror = 0;	/* Disable Relaxed Ordering for Reads. */
	mem_access_subid.s.row = 0;	/* Disable Relaxed Ordering for Writes. */
	mem_access_subid.s.ba = 0;	/* PCIe Adddress Bits <63:34>. */

	/*
	 * Setup mem access 12-15 for port 0, 16-19 for port 1,
	 * supplying 36 bits of address space.
	 */
	for (i = 12 + pcie_port * 4; i < 16 + pcie_port * 4; i++) {
		cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(i), mem_access_subid.u64);
		mem_access_subid.s.ba += 1; /* Set each SUBID to extend the addressable range */
	}

	/*
	 * Disable the peer to peer forwarding register. This must be
	 * setup by the OS after it enumerates the bus and assigns
	 * addresses to the PCIe busses.
	 */
	for (i = 0; i < 4; i++) {
		cvmx_write_csr(CVMX_PESCX_P2P_BARX_START(i, pcie_port), -1);
		cvmx_write_csr(CVMX_PESCX_P2P_BARX_END(i, pcie_port), -1);
	}

	/* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */
	cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0);

	/* BAR1 follows BAR2 with a gap so it has the same address as for gen2. */
	cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), CVMX_PCIE_BAR1_RC_BASE);

	bar1_index.u32 = 0;
	bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22);
	bar1_index.s.ca = 1;	   /* Not Cached */
	bar1_index.s.end_swp = 1;  /* Endian Swap mode */
	bar1_index.s.addr_v = 1;   /* Valid entry */

	base = pcie_port ? 16 : 0;

	/* Big endian swizzle for 32-bit PEXP_NCB register. */
#ifdef __MIPSEB__
	addr_swizzle = 4;
#else
	addr_swizzle = 0;
#endif
	for (i = 0; i < 16; i++) {
		cvmx_write64_uint32((CVMX_PEXP_NPEI_BAR1_INDEXX(base) ^ addr_swizzle),
				    bar1_index.u32);
		base++;
		/* 256MB / 16 >> 22 == 4 */
		bar1_index.s.addr_idx += (((1ull << 28) / 16ull) >> 22);
	}

	/*
	 * Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take
	 * precedence where they overlap. It also overlaps with the
	 * device addresses, so make sure the peer to peer forwarding
	 * is set right.
	 */
	cvmx_write_csr(CVMX_PESCX_P2N_BAR2_START(pcie_port), 0);

	/*
	 * Setup BAR2 attributes
	 *
	 * Relaxed Ordering (NPEI_CTL_PORTn[PTLP_RO,CTLP_RO, WAIT_COM])
	 * - PTLP_RO,CTLP_RO should normally be set (except for debug).
	 * - WAIT_COM=0 will likely work for all applications.
	 *
	 * Load completion relaxed ordering (NPEI_CTL_PORTn[WAITL_COM]).
	 */
	if (pcie_port) {
		union cvmx_npei_ctl_port1 npei_ctl_port;
		npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT1);
		npei_ctl_port.s.bar2_enb = 1;
		npei_ctl_port.s.bar2_esx = 1;
		npei_ctl_port.s.bar2_cax = 0;
		npei_ctl_port.s.ptlp_ro = 1;
		npei_ctl_port.s.ctlp_ro = 1;
		npei_ctl_port.s.wait_com = 0;
		npei_ctl_port.s.waitl_com = 0;
		cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT1, npei_ctl_port.u64);
	} else {
		union cvmx_npei_ctl_port0 npei_ctl_port;
		npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT0);
		npei_ctl_port.s.bar2_enb = 1;
		npei_ctl_port.s.bar2_esx = 1;
		npei_ctl_port.s.bar2_cax = 0;
		npei_ctl_port.s.ptlp_ro = 1;
		npei_ctl_port.s.ctlp_ro = 1;
		npei_ctl_port.s.wait_com = 0;
		npei_ctl_port.s.waitl_com = 0;
		cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT0, npei_ctl_port.u64);
	}

	/*
	 * Both pass 1 and pass 2 of CN52XX and CN56XX have an errata
	 * that causes TLP ordering to not be preserved after multiple
	 * PCIe port resets. This code detects this fault and corrects
	 * it by aligning the TLP counters properly. Another link
	 * reset is then performed. See PCIE-13340
	 */
	if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
	    OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X) ||
	    OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) ||
	    OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
		union cvmx_npei_dbg_data dbg_data;
		int old_in_fif_p_count;
		int in_fif_p_count;
		int out_p_count;
		int in_p_offset = (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X) || OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) ? 4 : 1;
		int i;

		/*
		 * Choose a write address of 1MB. It should be
		 * harmless as all bars haven't been setup.
		 */
		uint64_t write_address = (cvmx_pcie_get_mem_base_address(pcie_port) + 0x100000) | (1ull<<63);

		/*
		 * Make sure at least in_p_offset have been executed before we try and
		 * read in_fif_p_count
		 */
		i = in_p_offset;
		while (i--) {
			cvmx_write64_uint32(write_address, 0);
			__delay(10000);
		}

		/*
		 * Read the IN_FIF_P_COUNT from the debug
		 * select. IN_FIF_P_COUNT can be unstable sometimes so
		 * read it twice with a write between the reads.  This
		 * way we can tell the value is good as it will
		 * increment by one due to the write
		 */
		cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, (pcie_port) ? 0xd7fc : 0xcffc);
		cvmx_read_csr(CVMX_PEXP_NPEI_DBG_SELECT);
		do {
			dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
			old_in_fif_p_count = dbg_data.s.data & 0xff;
			cvmx_write64_uint32(write_address, 0);
			__delay(10000);
			dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
			in_fif_p_count = dbg_data.s.data & 0xff;
		} while (in_fif_p_count != ((old_in_fif_p_count+1) & 0xff));

		/* Update in_fif_p_count for it's offset with respect to out_p_count */
		in_fif_p_count = (in_fif_p_count + in_p_offset) & 0xff;

		/* Read the OUT_P_COUNT from the debug select */
		cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, (pcie_port) ? 0xd00f : 0xc80f);
		cvmx_read_csr(CVMX_PEXP_NPEI_DBG_SELECT);
		dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
		out_p_count = (dbg_data.s.data>>1) & 0xff;

		/* Check that the two counters are aligned */
		if (out_p_count != in_fif_p_count) {
			cvmx_dprintf("PCIe: Port %d aligning TLP counters as workaround to maintain ordering\n", pcie_port);
			while (in_fif_p_count != 0) {
				cvmx_write64_uint32(write_address, 0);
				__delay(10000);
				in_fif_p_count = (in_fif_p_count + 1) & 0xff;
			}
			/*
			 * The EBH5200 board swapped the PCIe reset
			 * lines on the board. This means we must
			 * bring both links down and up, which will
			 * cause the PCIe0 to need alignment
			 * again. Lots of messages will be displayed,
			 * but everything should work
			 */
			if ((cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) &&
				(pcie_port == 1))
				cvmx_pcie_rc_initialize(0);
			/* Rety bringing this port up */
			goto retry;
		}
	}

	/* Display the link status */
	pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port));
	cvmx_dprintf("PCIe: Port %d link active, %d lanes\n", pcie_port, pciercx_cfg032.s.nlw);

	return 0;
}