enum command_ret_t do_qlm_clock(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { int qlm; if (argc < 2) return CMD_RET_USAGE; qlm = simple_strtoul(argv[1], NULL, 10); printf("QLM %d clock speed: %d\n", qlm, cvmx_qlm_measure_clock(qlm)); return CMD_RET_SUCCESS; }
/** * @INTERNAL * Decrement the MPLL Multiplier for the DLM as per Errata G-20669 * * @param qlm DLM to configure * @param baud_mhz Speed of the DLM configured at * @param old_multiplier MPLL_MULTIPLIER value to decrement */ void __cvmx_qlm_set_mult(int qlm, int baud_mhz, int old_multiplier) { cvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier; uint64_t meas_refclock, mult; if (!OCTEON_IS_MODEL(OCTEON_CN70XX)) return; if (qlm == -1) return; meas_refclock = cvmx_qlm_measure_clock(qlm); if (meas_refclock == 0) { cvmx_warn("DLM%d: Reference clock not running\n", qlm); return; } mult = (uint64_t)baud_mhz * 1000000 + (meas_refclock/2); mult /= meas_refclock; #ifdef CVMX_BUILD_FOR_UBOOT /* For simulator just write the multiplier directly, to make it faster to boot. */ if (gd->arch.board_desc.board_type == CVMX_BOARD_TYPE_SIM) { cvmx_write_csr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0), mult); return; } #endif /* 6. Decrease MPLL_MULTIPLIER by one continually until it reaches the desired long-term setting, ensuring that each MPLL_MULTIPLIER value is constant for at least 1 msec before changing to the next value. The desired long-term setting is as indicated in HRM tables 21-1, 21-2, and 21-3. This is not required with the HRM sequence. */ do { mpll_multiplier.u64 = cvmx_read_csr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0)); mpll_multiplier.s.mpll_multiplier = --old_multiplier; cvmx_write_csr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0), mpll_multiplier.u64); /* Wait for 1 ms */ cvmx_wait_usec(1000); } while (old_multiplier > (int)mult); }
int checkboard(void) { int clk_to_use = 0; /* Clock used for DLM0 */ int val; val = pca953x_get_val(0, 0x20); /* Print it early so switches are in order */ if (val & 1) { /* DLM0_SEL */ puts("SW4-1 on: RXAUI (10G) port selected\n"); octeon_configure_qlm(0, 6250, CVMX_QLM_MODE_RXAUI, 0, 0, 2, 2); } else { puts("SW4-1 off: QSGMII ports selected\n"); octeon_configure_qlm(0, 2500, CVMX_QLM_MODE_QSGMII_QSGMII, 0, 0, 1, 1); } if (val & 2) { /* DLM1_SEL */ if (val & 4) { puts("SW4-2 on, SW4-3 off: PCIe 1x2 mode selected\n"); octeon_configure_qlm(1, 5000, CVMX_QLM_MODE_PCIE_1X2, 1, 1, 0, 0); } else { int host_mode = cvmx_pcie_is_host_mode(0); printf("SW4-2 on, SW4-3 on: PCIe 1x4 %s mode selected\n", host_mode ? "host" : "target"); /* For PCIe target mode we need to use clock 1 for DLM0 * since in this case clock 0 is coming from the PCIe * host. Also, there's no need to configure the DLM * if we're in PCIe target (endpoint) mode. */ if (host_mode) octeon_configure_qlm(1, 5000, CVMX_QLM_MODE_PCIE, 1, 1, clk_to_use, 0); else clk_to_use = 1; } } else { puts("SW4-2 off: mini-PCIe slots selected\n"); octeon_configure_qlm(1, 5000, CVMX_QLM_MODE_PCIE_2X1, 1, 1, 0, 0); } if (val & 4) { /* DLM2_SEL */ puts("SW4-3 on: SATA ports selected\n"); octeon_configure_qlm(2, 3125, CVMX_QLM_MODE_SATA_2X1, 0, 0, 1, 1); } if (val & 8) puts("SW4-4 on: PCM mode selected, SPI NOR disabled\n"); else puts("SW4-4 off: SPI NOR enabled\n"); printf("SW 1-8 is %s, %s selected as slot 1.\n", val & 0x10 ? "on" : "off", val & 0x10 ? "internal eMMC flash" : "external SD/MMC slot"); debug("qlm 0 reference clock: %llu\n", cvmx_qlm_measure_clock(0)); debug("qlm 1 reference clock: %llu\n", cvmx_qlm_measure_clock(1)); debug("qlm 2 reference clock: %llu\n", cvmx_qlm_measure_clock(2)); return 0; }
/** * Get the speed (Gbaud) of the QLM in Mhz. * * @param qlm QLM to examine * * @return Speed in Mhz */ int cvmx_qlm_get_gbaud_mhz(int qlm) { if (OCTEON_IS_MODEL(OCTEON_CN63XX)) { if (qlm == 2) { cvmx_gmxx_inf_mode_t inf_mode; inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0)); switch (inf_mode.s.speed) { case 0: return 5000; /* 5 Gbaud */ case 1: return 2500; /* 2.5 Gbaud */ case 2: return 2500; /* 2.5 Gbaud */ case 3: return 1250; /* 1.25 Gbaud */ case 4: return 1250; /* 1.25 Gbaud */ case 5: return 6250; /* 6.25 Gbaud */ case 6: return 5000; /* 5 Gbaud */ case 7: return 2500; /* 2.5 Gbaud */ case 8: return 3125; /* 3.125 Gbaud */ case 9: return 2500; /* 2.5 Gbaud */ case 10: return 1250; /* 1.25 Gbaud */ case 11: return 5000; /* 5 Gbaud */ case 12: return 6250; /* 6.25 Gbaud */ case 13: return 3750; /* 3.75 Gbaud */ case 14: return 3125; /* 3.125 Gbaud */ default: return 0; /* Disabled */ } } else { cvmx_sriox_status_reg_t status_reg; status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm)); if (status_reg.s.srio) { cvmx_sriomaintx_port_0_ctl2_t sriomaintx_port_0_ctl2; sriomaintx_port_0_ctl2.u32 = cvmx_read_csr(CVMX_SRIOMAINTX_PORT_0_CTL2(qlm)); switch (sriomaintx_port_0_ctl2.s.sel_baud) { case 1: return 1250; /* 1.25 Gbaud */ case 2: return 2500; /* 2.5 Gbaud */ case 3: return 3125; /* 3.125 Gbaud */ case 4: return 5000; /* 5 Gbaud */ case 5: return 6250; /* 6.250 Gbaud */ default: return 0; /* Disabled */ } } else { cvmx_pciercx_cfg032_t pciercx_cfg032; pciercx_cfg032.u32 = cvmx_read_csr(CVMX_PCIERCX_CFG032(qlm)); switch (pciercx_cfg032.s.ls) { case 1: return 2500; case 2: return 5000; case 4: return 8000; default: { cvmx_mio_rst_boot_t mio_rst_boot; mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT); if ((qlm == 0) && mio_rst_boot.s.qlm0_spd == 0xf) return 0; if ((qlm == 1) && mio_rst_boot.s.qlm1_spd == 0xf) return 0; return 5000; /* Best guess I can make */ } } } } } else if (OCTEON_IS_OCTEON2()) { cvmx_mio_qlmx_cfg_t qlm_cfg; qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); switch (qlm_cfg.s.qlm_spd) { case 0: return 5000; /* 5 Gbaud */ case 1: return 2500; /* 2.5 Gbaud */ case 2: return 2500; /* 2.5 Gbaud */ case 3: return 1250; /* 1.25 Gbaud */ case 4: return 1250; /* 1.25 Gbaud */ case 5: return 6250; /* 6.25 Gbaud */ case 6: return 5000; /* 5 Gbaud */ case 7: return 2500; /* 2.5 Gbaud */ case 8: return 3125; /* 3.125 Gbaud */ case 9: return 2500; /* 2.5 Gbaud */ case 10: return 1250; /* 1.25 Gbaud */ case 11: return 5000; /* 5 Gbaud */ case 12: return 6250; /* 6.25 Gbaud */ case 13: return 3750; /* 3.75 Gbaud */ case 14: return 3125; /* 3.125 Gbaud */ default: return 0; /* Disabled */ } } else if (OCTEON_IS_MODEL(OCTEON_CN70XX)) { cvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier; uint64_t meas_refclock; uint64_t freq; /* Measure the reference clock */ meas_refclock = cvmx_qlm_measure_clock(qlm); /* Multiply to get the final frequency */ mpll_multiplier.u64 = cvmx_read_csr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0)); freq = meas_refclock * mpll_multiplier.s.mpll_multiplier; freq = (freq + 500000) / 1000000; return freq; } return 0; }