enum cvmx_qlm_mode __cvmx_qlm_get_mode_cn73xx()

in arch/mips/mach-octeon/cvmx-qlm.c [1437:1690]


enum cvmx_qlm_mode __cvmx_qlm_get_mode_cn73xx(int qlm)
{
	cvmx_gserx_cfg_t gserx_cfg;
	int qlm_mode[7] = { -1, -1, -1, -1, -1, -1, -1 };

	if (qlm_mode[qlm] != -1)
		return qlm_mode[qlm];

	if (qlm > 6) {
		debug("Invalid QLM(%d) passed\n", qlm);
		return -1;
	}

	gserx_cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));
	if (gserx_cfg.s.pcie) {
		cvmx_pemx_cfg_t pemx_cfg;

		switch (qlm) {
		case 0: /* Either PEM0 x4 or PEM0 x8 */
		case 1: /* Either PEM0 x8 or PEM1 x4 */
		{
			pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));
			if (pemx_cfg.cn78xx.lanes8) {
				/* PEM0 x8 */
				qlm_mode[qlm] = CVMX_QLM_MODE_PCIE_1X8;
			} else {
				/* PEM0/PEM1 x4 */
				qlm_mode[qlm] = CVMX_QLM_MODE_PCIE;
			}
			break;
		}
		case 2: /* Either PEM2 x4 or PEM2 x8 */
		{
			pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));
			if (pemx_cfg.cn78xx.lanes8) {
				/* PEM2 x8 */
				qlm_mode[qlm] = CVMX_QLM_MODE_PCIE_1X8;
			} else {
				/* PEM2 x4 */
				qlm_mode[qlm] = CVMX_QLM_MODE_PCIE;
			}
			break;
		}
		case 5:
		case 6:						/* PEM3 x2 */
			qlm_mode[qlm] = CVMX_QLM_MODE_PCIE_1X2; /* PEM3 x2 */
			break;
		case 3: /* Either PEM2 x8 or PEM3 x4 */
		{
			pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));
			if (pemx_cfg.cn78xx.lanes8) {
				/* PEM2 x8 */
				qlm_mode[qlm] = CVMX_QLM_MODE_PCIE_1X8;
			} else {
				/* PEM3 x4 */
				qlm_mode[qlm] = CVMX_QLM_MODE_PCIE;
			}
			break;
		}
		default:
			qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
			break;
		}
	} else if (gserx_cfg.s.bgx) {
		cvmx_bgxx_cmrx_config_t cmr_config;
		cvmx_bgxx_cmr_rx_lmacs_t bgx_cmr_rx_lmacs;
		cvmx_bgxx_spux_br_pmd_control_t pmd_control;
		int bgx = 0;
		int start = 0, end = 4, index;
		int lane_mask = 0, train_mask = 0;
		int mux = 0; // 0:BGX2 (DLM5/DLM6), 1:BGX2(DLM5), 2:BGX2(DLM6)

		if (qlm < 4) {
			bgx = qlm - 2;
		} else if (qlm == 5 || qlm == 6) {
			bgx = 2;
			mux = cvmx_qlm_mux_interface(bgx);
			if (mux == 0) {
				start = 0;
				end = 4;
			} else if (mux == 1) {
				start = 0;
				end = 2;
			} else if (mux == 2) {
				start = 2;
				end = 4;
			} else {
				qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
				return qlm_mode[qlm];
			}
		}

		for (index = start; index < end; index++) {
			cmr_config.u64 = csr_rd(CVMX_BGXX_CMRX_CONFIG(index, bgx));
			pmd_control.u64 = csr_rd(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx));
			lane_mask |= (cmr_config.s.lmac_type << (index * 4));
			train_mask |= (pmd_control.s.train_en << (index * 4));
		}

		/* Need to include DLM5 lmacs when only DLM6 DLM is used */
		if (mux == 2)
			bgx_cmr_rx_lmacs.u64 = csr_rd(CVMX_BGXX_CMR_RX_LMACS(2));
		switch (lane_mask) {
		case 0:
			if (mux == 1) {
				qlm_mode[qlm] = CVMX_QLM_MODE_SGMII_2X1;
			} else if (mux == 2) {
				qlm_mode[qlm] = CVMX_QLM_MODE_SGMII_2X1;
				bgx_cmr_rx_lmacs.s.lmacs = 4;
			}
			qlm_mode[qlm] = CVMX_QLM_MODE_SGMII;
			break;
		case 0x1:
			qlm_mode[qlm] = CVMX_QLM_MODE_XAUI;
			break;
		case 0x2:
			if (mux == 1) {
				// NONE+RXAUI
				qlm_mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;
			} else if (mux == 0) {
				// RXAUI+SGMII
				qlm_mode[qlm] = CVMX_QLM_MODE_MIXED;
			} else {
				qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
			}
			break;
		case 0x202:
			if (mux == 2) {
				// RXAUI+RXAUI
				qlm_mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;
				bgx_cmr_rx_lmacs.s.lmacs = 4;
			} else if (mux == 1) {
				// RXAUI+RXAUI
				qlm_mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;
			} else if (mux == 0) {
				qlm_mode[qlm] = CVMX_QLM_MODE_RXAUI;
			} else {
				qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
			}
			break;
		case 0x22:
			qlm_mode[qlm] = CVMX_QLM_MODE_RXAUI;
			break;
		case 0x3333:
			/*
			 * Use training to determine if we're in 10GBASE-KR
			 * or XFI
			 */
			if (train_mask)
				qlm_mode[qlm] = CVMX_QLM_MODE_10G_KR;
			else
				qlm_mode[qlm] = CVMX_QLM_MODE_XFI;
			break;
		case 0x4:
			/*
			 * Use training to determine if we're in 40GBASE-KR
			 * or XLAUI
			 */
			if (train_mask)
				qlm_mode[qlm] = CVMX_QLM_MODE_40G_KR4;
			else
				qlm_mode[qlm] = CVMX_QLM_MODE_XLAUI;
			break;
		case 0x0005:
			qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_SGMII;
			break;
		case 0x3335:
			if (train_mask)
				qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_10G_KR;
			else
				qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_XFI;
			break;
		case 0x45:
			if (train_mask)
				qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_40G_KR4;
			else
				qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_XLAUI;
			break;
		case 0x225:
			qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_RXAUI;
			break;
		case 0x15:
			qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_XAUI;
			break;

		case 0x200:
			if (mux == 2) {
				qlm_mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;
				bgx_cmr_rx_lmacs.s.lmacs = 4;
			} else
		case 0x205:
		case 0x233:
		case 0x3302:
		case 0x3305:
			if (mux == 0)
				qlm_mode[qlm] = CVMX_QLM_MODE_MIXED;
			else
				qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
			break;
		case 0x3300:
			if (mux == 0) {
				qlm_mode[qlm] = CVMX_QLM_MODE_MIXED;
			} else if (mux == 2) {
				if (train_mask)
					qlm_mode[qlm] = CVMX_QLM_MODE_10G_KR_1X2;
				else
					qlm_mode[qlm] = CVMX_QLM_MODE_XFI_1X2;
				bgx_cmr_rx_lmacs.s.lmacs = 4;
			} else {
				qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
			}
			break;
		case 0x33:
			if (mux == 1 || mux == 2) {
				if (train_mask)
					qlm_mode[qlm] = CVMX_QLM_MODE_10G_KR_1X2;
				else
					qlm_mode[qlm] = CVMX_QLM_MODE_XFI_1X2;
				if (mux == 2)
					bgx_cmr_rx_lmacs.s.lmacs = 4;
			} else {
				qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
			}
			break;
		case 0x0035:
			if (mux == 0)
				qlm_mode[qlm] = CVMX_QLM_MODE_MIXED;
			else if (train_mask)
				qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_10G_KR_1X1;
			else
				qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_XFI_1X1;
			break;
		case 0x235:
			if (mux == 0)
				qlm_mode[qlm] = CVMX_QLM_MODE_MIXED;
			else
				qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
			break;
		default:
			qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
			break;
		}
		if (mux == 2) {
			csr_wr(CVMX_BGXX_CMR_RX_LMACS(2), bgx_cmr_rx_lmacs.u64);
			csr_wr(CVMX_BGXX_CMR_TX_LMACS(2), bgx_cmr_rx_lmacs.u64);
		}
	} else if (gserx_cfg.s.sata) {
		qlm_mode[qlm] = CVMX_QLM_MODE_SATA_2X1;
	} else {
		qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
	}

	return qlm_mode[qlm];
}