static void board_configure_qlms()

in board/Marvell/octeon_ebb7304/board.c [448:747]


static void board_configure_qlms(void)
{
	int speed[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
	int mode[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
	int pcie_rc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
	int pcie_gen[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
	int ref_clock_sel[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
	int ref_clock_input[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
	struct gpio_desc desc;
	int rbgx, rqlm;
	char env_var[16];
	int qlm;
	int ret;

	/* RGMII PHY reset GPIO */
	ret = dm_gpio_lookup_name("gpio-controllerA27", &desc);
	if (ret)
		debug("gpio ret=%d\n", ret);
	ret = dm_gpio_request(&desc, "rgmii_phy_reset");
	if (ret)
		debug("gpio_request ret=%d\n", ret);
	ret = dm_gpio_set_dir_flags(&desc, GPIOD_IS_OUT);
	if (ret)
		debug("gpio dir ret=%d\n", ret);

	/* Put RGMII PHY in reset */
	dm_gpio_set_value(&desc, 0);

	octeon_init_qlm(0);

	rbgx = env_get_ulong("bgx_for_rgmii", 10, (unsigned long)-1);
	switch (rbgx) {
	case 0:
		rqlm = 2;
		break;
	case 1:
		rqlm = 3;
		break;
	case 2:
		rqlm = 5;
		break;
	default:
		rqlm = -1;
		break;
	}

	for (qlm = 0; qlm < 7; qlm++) {
		const char *mode_str;
		char spd_env[16];

		mode[qlm] = CVMX_QLM_MODE_DISABLED;
		sprintf(env_var, "qlm%d_mode", qlm);
		mode_str = env_get(env_var);
		if (!mode_str)
			continue;

		if (qlm == 4 && mode[4] != -1 &&
		    mode[4] != CVMX_QLM_MODE_SATA_2X1) {
			printf("Error: DLM 4 can only be configured for SATA\n");
			continue;
		}

		if (strstr(mode_str, ",no_phy"))
			no_phy[qlm] = 1;

		if (!strncmp(mode_str, "sgmii", 5)) {
			bool rgmii = false;

			speed[qlm] = 1250;
			if (rqlm == qlm && qlm < 5) {
				mode[qlm] = CVMX_QLM_MODE_RGMII_SGMII;
				rgmii = true;
			} else if (qlm == 6 || qlm == 5) {
				if (rqlm == qlm && qlm == 5) {
					mode[qlm] = CVMX_QLM_MODE_RGMII_SGMII_1X1;
					rgmii = true;
				} else if (rqlm == 5 && qlm == 6 &&
					   mode[5] != CVMX_QLM_MODE_RGMII_SGMII_1X1) {
					mode[qlm] = CVMX_QLM_MODE_RGMII_SGMII_2X1;
					rgmii = true;
				} else {
					mode[qlm] = CVMX_QLM_MODE_SGMII_2X1;
				}
			} else {
				mode[qlm] = CVMX_QLM_MODE_SGMII;
			}
			ref_clock_sel[qlm] = 2;

			if (qlm == 5 || qlm == 6)
				ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1

			if (no_phy[qlm]) {
				int i;
				int start = 0, stop = 2;

				rbgx = 0;
				switch (qlm) {
				case 3:
					rbgx = 1;
				case 2:
					for (i = 0; i < 4; i++) {
						printf("Ignoring PHY for interface: %d, port: %d\n",
						       rbgx, i);
						cvmx_helper_set_port_force_link_up(rbgx, i, true);
					}
					break;
				case 6:
					start = 2;
					stop = 4;
				case 5:
					for (i = start; i < stop; i++) {
						printf("Ignoring PHY for interface: %d, port: %d\n",
						       2, i);
						cvmx_helper_set_port_force_link_up(2, i, true);
					}
					break;
				default:
					printf("SGMII not supported for QLM/DLM %d\n",
					       qlm);
					break;
				}
			}
			printf("QLM %d: SGMII%s\n",
			       qlm, rgmii ? ", RGMII" : "");
		} else if (!strncmp(mode_str, "xaui", 4)) {
			speed[qlm] = 3125;
			mode[qlm] = CVMX_QLM_MODE_XAUI;
			ref_clock_sel[qlm] = 2;
			if (qlm == 5 || qlm == 6)
				ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
			printf("QLM %d: XAUI\n", qlm);
		} else if (!strncmp(mode_str, "dxaui", 5)) {
			speed[qlm] = 6250;
			mode[qlm] = CVMX_QLM_MODE_XAUI;
			ref_clock_sel[qlm] = 2;
			if (qlm == 5 || qlm == 6)
				ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
			printf("QLM %d: DXAUI\n", qlm);
		} else if (!strncmp(mode_str, "rxaui", 5)) {
			bool rgmii = false;

			speed[qlm] = 6250;
			if (qlm == 5 || qlm == 6) {
				if (rqlm == qlm && qlm == 5) {
					mode[qlm] = CVMX_QLM_MODE_RGMII_RXAUI;
					rgmii = true;
				} else {
					mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;
				}
			} else {
				mode[qlm] = CVMX_QLM_MODE_RXAUI;
			}
			ref_clock_sel[qlm] = 2;
			if (qlm == 5 || qlm == 6)
				ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
			printf("QLM %d: RXAUI%s\n",
			       qlm, rgmii ? ", rgmii" : "");
		} else if (!strncmp(mode_str, "xlaui", 5)) {
			speed[qlm] = 103125;
			mode[qlm] = CVMX_QLM_MODE_XLAUI;
			ref_clock_sel[qlm] = 2;
			if (qlm == 5 || qlm == 6)
				ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
			sprintf(spd_env, "qlm%d_speed", qlm);
			if (env_get(spd_env)) {
				int spd = env_get_ulong(spd_env, 0, 8);

				if (spd)
					speed[qlm] = spd;
				else
					speed[qlm] = 103125;
			}
			printf("QLM %d: XLAUI\n", qlm);
		} else if (!strncmp(mode_str, "xfi", 3)) {
			bool rgmii = false;

			speed[qlm] = 103125;
			if (rqlm == qlm) {
				mode[qlm] = CVMX_QLM_MODE_RGMII_XFI;
				rgmii = true;
			} else if (qlm == 5 || qlm == 6) {
				mode[qlm] = CVMX_QLM_MODE_XFI_1X2;
			} else {
				mode[qlm] = CVMX_QLM_MODE_XFI;
			}
			ref_clock_sel[qlm] = 2;
			if (qlm == 5 || qlm == 6)
				ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
			printf("QLM %d: XFI%s\n", qlm, rgmii ? ", RGMII" : "");
		} else if (!strncmp(mode_str, "10G_KR", 6)) {
			speed[qlm] = 103125;
			if (rqlm == qlm && qlm == 5)
				mode[qlm] = CVMX_QLM_MODE_RGMII_10G_KR;
			else if (qlm == 5 || qlm == 6)
				mode[qlm] = CVMX_QLM_MODE_10G_KR_1X2;
			else
				mode[qlm] = CVMX_QLM_MODE_10G_KR;
			ref_clock_sel[qlm] = 2;
			if (qlm == 5 || qlm == 6)
				ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
			printf("QLM %d: 10G_KR\n", qlm);
		} else if (!strncmp(mode_str, "40G_KR4", 7)) {
			speed[qlm] = 103125;
			mode[qlm] = CVMX_QLM_MODE_40G_KR4;
			ref_clock_sel[qlm] = 2;
			if (qlm == 5 || qlm == 6)
				ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
			printf("QLM %d: 40G_KR4\n", qlm);
		} else if (!strcmp(mode_str, "pcie")) {
			char *pmode;
			int lanes = 0;

			sprintf(env_var, "pcie%d_mode", qlm);
			pmode = env_get(env_var);
			if (pmode && !strcmp(pmode, "ep"))
				pcie_rc[qlm] = 0;
			else
				pcie_rc[qlm] = 1;
			sprintf(env_var, "pcie%d_gen", qlm);
			pcie_gen[qlm] = env_get_ulong(env_var, 0, 3);
			sprintf(env_var, "pcie%d_lanes", qlm);
			lanes = env_get_ulong(env_var, 0, 8);
			if (lanes == 8) {
				mode[qlm] = CVMX_QLM_MODE_PCIE_1X8;
			} else if (qlm == 5 || qlm == 6) {
				if (lanes != 2) {
					printf("QLM%d: Invalid lanes selected, defaulting to 2 lanes\n",
					       qlm);
				}
				mode[qlm] = CVMX_QLM_MODE_PCIE_1X2;
				ref_clock_input[qlm] = 1; // use QLMC_REF_CLK0
			} else {
				mode[qlm] = CVMX_QLM_MODE_PCIE;
			}
			ref_clock_sel[qlm] = 0;
			printf("QLM %d: PCIe gen%d %s, x%d lanes\n",
			       qlm, pcie_gen[qlm] + 1,
			       pcie_rc[qlm] ? "root complex" : "endpoint",
			       lanes);
		} else if (!strcmp(mode_str, "sata")) {
			mode[qlm] = CVMX_QLM_MODE_SATA_2X1;
			ref_clock_sel[qlm] = 0;
			ref_clock_input[qlm] = 1;
			sprintf(spd_env, "qlm%d_speed", qlm);
			if (env_get(spd_env)) {
				int spd = env_get_ulong(spd_env, 0, 8);

				if (spd == 1500 || spd == 3000 || spd == 3000)
					speed[qlm] = spd;
				else
					speed[qlm] = 6000;
			} else {
				speed[qlm] = 6000;
			}
		} else {
			printf("QLM %d: disabled\n", qlm);
		}
	}

	for (qlm = 0; qlm < 7; qlm++) {
		int rc;

		if (mode[qlm] == -1)
			continue;

		debug("Configuring qlm%d with speed(%d), mode(%d), RC(%d), Gen(%d), REF_CLK(%d), CLK_SOURCE(%d)\n",
		      qlm, speed[qlm], mode[qlm], pcie_rc[qlm],
		      pcie_gen[qlm] + 1,
		      ref_clock_sel[qlm], ref_clock_input[qlm]);
		rc = octeon_configure_qlm(qlm, speed[qlm], mode[qlm],
					  pcie_rc[qlm], pcie_gen[qlm],
					  ref_clock_sel[qlm],
					  ref_clock_input[qlm]);

		if (speed[qlm] == 6250) {
			if (mode[qlm] == CVMX_QLM_MODE_RXAUI) {
				octeon_qlm_tune_v3(0, qlm, speed[qlm], 0x12,
						   0xa0, -1, -1);
			} else {
				octeon_qlm_tune_v3(0, qlm, speed[qlm], 0xa,
						   0xa0, -1, -1);
			}
		} else if (speed[qlm] == 103125) {
			octeon_qlm_tune_v3(0, qlm, speed[qlm], 0xd, 0xd0,
					   -1, -1);
		}

		if (qlm == 4 && rc != 0)
			/*
			 * There is a bug with SATA with 73xx.  Until it's
			 * fixed we need to strip it from the device tree.
			 */
			octeon_fdt_patch_rename((void *)gd->fdt_blob, "4,none",
						NULL, true, NULL, NULL);
	}

	dm_gpio_set_value(&desc, 0); /* Put RGMII PHY in reset */
	mdelay(10);
	dm_gpio_set_value(&desc, 1); /* Take RGMII PHY out of reset */
}