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 */
}