int do_qlm(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { int num_qlm; int qlm; int c_arg; /* Make sure we got the correct number of arguments */ if (((argc - 2) % 3) != 0) { printf("Invalid number of arguments %d\n", argc); usage(argv); return -1; } num_qlm = cvmx_qlm_get_num(); qlm = simple_strtoul(argv[1], NULL, 0); if ((qlm < 0) || (qlm >= num_qlm)) { printf("Invalid qlm number\n"); return -1; } if (argc >= 5) { int lane; uint64_t value; int field_count; int num_fields = (argc - 2) / 3; c_arg = 2; for (field_count = 0; field_count < num_fields; field_count++) { char name[30]; if (!strcmp(argv[c_arg], "all")) lane = -1; else { lane = (int)simple_strtol(argv[c_arg], NULL, 0); if (lane >= cvmx_qlm_get_lanes(qlm)) { printf("Invalid lane passed\n"); return -1; } } strcpy(name, argv[c_arg + 1]); value = convert_number(argv[c_arg + 2]); cvmx_qlm_jtag_set(qlm, lane, name, value); /* Assert serdes_tx_byp to force the new settings to override the QLM default. */ if (strncmp(name, "biasdrv_", 8) == 0 || strncmp(name, "tcoeff_", 7) == 0) cvmx_qlm_jtag_set(qlm, lane, "serdes_tx_byp", 1); c_arg += 3; if (lane == -1) break; } } else cvmx_qlm_display_registers(qlm); return 0; }
/** * Errata G-16094: QLM Gen2 Equalizer Default Setting Change. * CN68XX pass 1.x and CN66XX pass 1.x QLM tweak. This function tweaks the * JTAG setting for a QLMs to run better at 5 and 6.25Ghz. */ void __cvmx_qlm_speed_tweak(void) { cvmx_mio_qlmx_cfg_t qlm_cfg; int num_qlms = cvmx_qlm_get_num(); int qlm; /* Workaround for Errata (G-16467) */ if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_X)) { for (qlm = 0; qlm < num_qlms; qlm++) { int ir50dac; /* This workaround only applies to QLMs running at 6.25Ghz */ if (cvmx_qlm_get_gbaud_mhz(qlm) == 6250) { #ifdef CVMX_QLM_DUMP_STATE cvmx_dprintf("%s:%d: QLM%d: Applying workaround for Errata G-16467\n", __func__, __LINE__, qlm); cvmx_qlm_display_registers(qlm); cvmx_dprintf("\n"); #endif cvmx_qlm_jtag_set(qlm, -1, "cfg_cdr_trunc", 0); /* Hold the QLM in reset */ cvmx_qlm_jtag_set(qlm, -1, "cfg_rst_n_set", 0); cvmx_qlm_jtag_set(qlm, -1, "cfg_rst_n_clr", 1); /* Forcfe TX to be idle */ cvmx_qlm_jtag_set(qlm, -1, "cfg_tx_idle_clr", 0); cvmx_qlm_jtag_set(qlm, -1, "cfg_tx_idle_set", 1); if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_0)) { ir50dac = cvmx_qlm_jtag_get(qlm, 0, "ir50dac"); while (++ir50dac <= 31) cvmx_qlm_jtag_set(qlm, -1, "ir50dac", ir50dac); } cvmx_qlm_jtag_set(qlm, -1, "div4_byp", 0); cvmx_qlm_jtag_set(qlm, -1, "clkf_byp", 16); cvmx_qlm_jtag_set(qlm, -1, "serdes_pll_byp", 1); cvmx_qlm_jtag_set(qlm, -1, "spdsel_byp", 1); #ifdef CVMX_QLM_DUMP_STATE cvmx_dprintf("%s:%d: QLM%d: Done applying workaround for Errata G-16467\n", __func__, __LINE__, qlm); cvmx_qlm_display_registers(qlm); cvmx_dprintf("\n\n"); #endif /* The QLM will be taken out of reset later when ILK/XAUI are initialized. */ } } #ifndef CVMX_BUILD_FOR_LINUX_HOST /* These QLM tuning parameters are specific to EBB6800 eval boards using Cavium QLM cables. These should be removed or tunned based on customer boards. */ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBB6800) { for (qlm = 0; qlm < num_qlms; qlm++) { #ifdef CVMX_QLM_DUMP_STATE cvmx_dprintf("Setting tunning parameters for QLM%d\n", qlm); #endif cvmx_qlm_jtag_set(qlm, -1, "biasdrv_hs_ls_byp", 12); cvmx_qlm_jtag_set(qlm, -1, "biasdrv_hf_byp", 12); cvmx_qlm_jtag_set(qlm, -1, "biasdrv_lf_ls_byp", 12); cvmx_qlm_jtag_set(qlm, -1, "biasdrv_lf_byp", 12); cvmx_qlm_jtag_set(qlm, -1, "tcoeff_hf_byp", 15); cvmx_qlm_jtag_set(qlm, -1, "tcoeff_hf_ls_byp", 15); cvmx_qlm_jtag_set(qlm, -1, "tcoeff_lf_ls_byp", 15); cvmx_qlm_jtag_set(qlm, -1, "tcoeff_lf_byp", 15); cvmx_qlm_jtag_set(qlm, -1, "rx_cap_gen2", 0); cvmx_qlm_jtag_set(qlm, -1, "rx_eq_gen2", 11); cvmx_qlm_jtag_set(qlm, -1, "serdes_tx_byp", 1); } } else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_NIC68_4) { for (qlm = 0; qlm < num_qlms; qlm++) { #ifdef CVMX_QLM_DUMP_STATE cvmx_dprintf("Setting tunning parameters for QLM%d\n", qlm); #endif cvmx_qlm_jtag_set(qlm, -1, "biasdrv_hs_ls_byp", 30); cvmx_qlm_jtag_set(qlm, -1, "biasdrv_hf_byp", 30); cvmx_qlm_jtag_set(qlm, -1, "biasdrv_lf_ls_byp", 30); cvmx_qlm_jtag_set(qlm, -1, "biasdrv_lf_byp", 30); cvmx_qlm_jtag_set(qlm, -1, "tcoeff_hf_byp", 0); cvmx_qlm_jtag_set(qlm, -1, "tcoeff_hf_ls_byp", 0); cvmx_qlm_jtag_set(qlm, -1, "tcoeff_lf_ls_byp", 0); cvmx_qlm_jtag_set(qlm, -1, "tcoeff_lf_byp", 0); cvmx_qlm_jtag_set(qlm, -1, "rx_cap_gen2", 1); cvmx_qlm_jtag_set(qlm, -1, "rx_eq_gen2", 8); cvmx_qlm_jtag_set(qlm, -1, "serdes_tx_byp", 1); } } #endif } /* G-16094 QLM Gen2 Equalizer Default Setting Change */ else if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X) || OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X)) { /* Loop through the QLMs */ for (qlm = 0; qlm < num_qlms; qlm++) { /* Read the QLM speed */ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); /* If the QLM is at 6.25Ghz or 5Ghz then program JTAG */ if ((qlm_cfg.s.qlm_spd == 5) || (qlm_cfg.s.qlm_spd == 12) || (qlm_cfg.s.qlm_spd == 0) || (qlm_cfg.s.qlm_spd == 6) || (qlm_cfg.s.qlm_spd == 11)) { cvmx_qlm_jtag_set(qlm, -1, "rx_cap_gen2", 0x1); cvmx_qlm_jtag_set(qlm, -1, "rx_eq_gen2", 0x8); } } } }