static int __cvmx_pcie_rc_initialize_gen2()

in pci/pcie-octeon.c [1147:1433]


static int __cvmx_pcie_rc_initialize_gen2(int pcie_port)
{
	int i;
	union cvmx_ciu_soft_prst ciu_soft_prst;
	union cvmx_mio_rst_ctlx mio_rst_ctl;
	union cvmx_pemx_bar_ctl pemx_bar_ctl;
	union cvmx_pemx_ctl_status pemx_ctl_status;
	union cvmx_pemx_bist_status pemx_bist_status;
	union cvmx_pemx_bist_status2 pemx_bist_status2;
	union cvmx_pciercx_cfg032 pciercx_cfg032;
	union cvmx_pciercx_cfg515 pciercx_cfg515;
	union cvmx_sli_ctl_portx sli_ctl_portx;
	union cvmx_sli_mem_access_ctl sli_mem_access_ctl;
	union cvmx_sli_mem_access_subidx mem_access_subid;
	union cvmx_sriox_status_reg sriox_status_reg;
	union cvmx_pemx_bar1_indexx bar1_index;

	if (octeon_has_feature(OCTEON_FEATURE_SRIO)) {
		/* Make sure this interface isn't SRIO */
		if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
			/*
			 * The CN66XX requires reading the
			 * MIO_QLMX_CFG register to figure out the
			 * port type.
			 */
			union cvmx_mio_qlmx_cfg qlmx_cfg;
			qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(pcie_port));

			if (qlmx_cfg.s.qlm_spd == 15) {
				pr_notice("PCIe: Port %d is disabled, skipping.\n", pcie_port);
				return -1;
			}

			switch (qlmx_cfg.s.qlm_spd) {
			case 0x1: /* SRIO 1x4 short */
			case 0x3: /* SRIO 1x4 long */
			case 0x4: /* SRIO 2x2 short */
			case 0x6: /* SRIO 2x2 long */
				pr_notice("PCIe: Port %d is SRIO, skipping.\n", pcie_port);
				return -1;
			case 0x9: /* SGMII */
				pr_notice("PCIe: Port %d is SGMII, skipping.\n", pcie_port);
				return -1;
			case 0xb: /* XAUI */
				pr_notice("PCIe: Port %d is XAUI, skipping.\n", pcie_port);
				return -1;
			case 0x0: /* PCIE gen2 */
			case 0x8: /* PCIE gen2 (alias) */
			case 0x2: /* PCIE gen1 */
			case 0xa: /* PCIE gen1 (alias) */
				break;
			default:
				pr_notice("PCIe: Port %d is unknown, skipping.\n", pcie_port);
				return -1;
			}
		} else {
			sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(pcie_port));
			if (sriox_status_reg.s.srio) {
				pr_notice("PCIe: Port %d is SRIO, skipping.\n", pcie_port);
				return -1;
			}
		}
	}

#if 0
    /* This code is so that the PCIe analyzer is able to see 63XX traffic */
	pr_notice("PCIE : init for pcie analyzer.\n");
	cvmx_helper_qlm_jtag_init();
	cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 85);
	cvmx_helper_qlm_jtag_shift(pcie_port, 1, 1);
	cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 300-86);
	cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 85);
	cvmx_helper_qlm_jtag_shift(pcie_port, 1, 1);
	cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 300-86);
	cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 85);
	cvmx_helper_qlm_jtag_shift(pcie_port, 1, 1);
	cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 300-86);
	cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 85);
	cvmx_helper_qlm_jtag_shift(pcie_port, 1, 1);
	cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 300-86);
	cvmx_helper_qlm_jtag_update(pcie_port);
#endif

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

	/* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be programmed */
	if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0)) {
		if (pcie_port) {
			union cvmx_ciu_qlm ciu_qlm;
			ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1);
			ciu_qlm.s.txbypass = 1;
			ciu_qlm.s.txdeemph = 5;
			ciu_qlm.s.txmargin = 0x17;
			cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64);
		} else {
			union cvmx_ciu_qlm ciu_qlm;
			ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0);
			ciu_qlm.s.txbypass = 1;
			ciu_qlm.s.txdeemph = 5;
			ciu_qlm.s.txmargin = 0x17;
			cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64);
		}
	}
	/* Bring the PCIe out of reset */
	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 */
	udelay(1000);

	/*
	 * 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.
	 */
	if (CVMX_WAIT_FOR_FIELD64(CVMX_MIO_RST_CTLX(pcie_port), union cvmx_mio_rst_ctlx, rst_done, ==, 1, 10000)) {
		pr_notice("PCIe: Port %d stuck in reset, skipping.\n", pcie_port);
		return -1;
	}

	/* Check BIST status */
	pemx_bist_status.u64 = cvmx_read_csr(CVMX_PEMX_BIST_STATUS(pcie_port));
	if (pemx_bist_status.u64)
		pr_notice("PCIe: BIST FAILED for port %d (0x%016llx)\n", pcie_port, CAST64(pemx_bist_status.u64));
	pemx_bist_status2.u64 = cvmx_read_csr(CVMX_PEMX_BIST_STATUS2(pcie_port));
	/* Errata PCIE-14766 may cause the lower 6 bits to be randomly set on CN63XXp1 */
	if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
		pemx_bist_status2.u64 &= ~0x3full;
	if (pemx_bist_status2.u64)
		pr_notice("PCIe: BIST2 FAILED for port %d (0x%016llx)\n", pcie_port, CAST64(pemx_bist_status2.u64));

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

	/* Enable gen2 speed selection */
	pciercx_cfg515.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG515(pcie_port));
	pciercx_cfg515.s.dsc = 1;
	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG515(pcie_port), pciercx_cfg515.u32);

	/* Bring the link up */
	if (__cvmx_pcie_rc_initialize_link_gen2(pcie_port)) {
		/*
		 * Some gen1 devices don't handle the gen 2 training
		 * correctly. Disable gen2 and try again with only
		 * gen1
		 */
		union cvmx_pciercx_cfg031 pciercx_cfg031;
		pciercx_cfg031.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG031(pcie_port));
		pciercx_cfg031.s.mls = 1;
		cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG031(pcie_port), pciercx_cfg031.u32);
		if (__cvmx_pcie_rc_initialize_link_gen2(pcie_port)) {
			pr_notice("PCIe: Link timeout on port %d, probably the slot is empty\n", pcie_port);
			return -1;
		}
	}

	/* Store merge control (SLI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */
	sli_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL);
	sli_mem_access_ctl.s.max_word = 0;	/* Allow 16 words to combine */
	sli_mem_access_ctl.s.timer = 127;	/* Wait up to 127 cycles for more data */
	cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL, sli_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 = 0;	/* Allow merging as it works on CN6XXX. */
	mem_access_subid.s.esr = 1;	/* Endian-swap for Reads. */
	mem_access_subid.s.esw = 1;	/* Endian-swap for Writes. */
	mem_access_subid.s.wtype = 0;	/* "No snoop" and "Relaxed ordering" are not set */
	mem_access_subid.s.rtype = 0;	/* "No snoop" and "Relaxed ordering" are not set */
	/* PCIe Adddress Bits <63:34>. */
	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
		mem_access_subid.cn68xx.ba = 0;
	else
		mem_access_subid.s.ba = 0;

	/*
	 * 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_SLI_MEM_ACCESS_SUBIDX(i), mem_access_subid.u64);
		/* Set each SUBID to extend the addressable range */
		__cvmx_increment_ba(&mem_access_subid);
	}

	/*
	 * 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_PEMX_P2P_BARX_START(i, pcie_port), -1);
		cvmx_write_csr(CVMX_PEMX_P2P_BARX_END(i, pcie_port), -1);
	}

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

	/*
	 * Set Octeon's BAR2 to decode 0-2^41. 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_PEMX_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])
	 */
	pemx_bar_ctl.u64 = cvmx_read_csr(CVMX_PEMX_BAR_CTL(pcie_port));
	pemx_bar_ctl.s.bar1_siz = 3;  /* 256MB BAR1*/
	pemx_bar_ctl.s.bar2_enb = 1;
	pemx_bar_ctl.s.bar2_esx = 1;
	pemx_bar_ctl.s.bar2_cax = 0;
	cvmx_write_csr(CVMX_PEMX_BAR_CTL(pcie_port), pemx_bar_ctl.u64);
	sli_ctl_portx.u64 = cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(pcie_port));
	sli_ctl_portx.s.ptlp_ro = 1;
	sli_ctl_portx.s.ctlp_ro = 1;
	sli_ctl_portx.s.wait_com = 0;
	sli_ctl_portx.s.waitl_com = 0;
	cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(pcie_port), sli_ctl_portx.u64);

	/* BAR1 follows BAR2 */
	cvmx_write_csr(CVMX_PEMX_P2N_BAR1_START(pcie_port), CVMX_PCIE_BAR1_RC_BASE);

	bar1_index.u64 = 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 */

	for (i = 0; i < 16; i++) {
		cvmx_write_csr(CVMX_PEMX_BAR1_INDEXX(i, pcie_port), bar1_index.u64);
		/* 256MB / 16 >> 22 == 4 */
		bar1_index.s.addr_idx += (((1ull << 28) / 16ull) >> 22);
	}

	/*
	 * Allow config retries for 250ms. Count is based off the 5Ghz
	 * SERDES clock.
	 */
	pemx_ctl_status.u64 = cvmx_read_csr(CVMX_PEMX_CTL_STATUS(pcie_port));
	pemx_ctl_status.s.cfg_rtry = 250 * 5000000 / 0x10000;
	cvmx_write_csr(CVMX_PEMX_CTL_STATUS(pcie_port), pemx_ctl_status.u64);

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

	return 0;
}