/** * Set a field in a QLM JTAG chain * * @param qlm QLM to set * @param lane Lane in QLM to set, or -1 for all lanes * @param name String name of field * @param value Value of the field */ void cvmx_qlm_jtag_set(int qlm, int lane, const char *name, uint64_t value) { int i, l; uint32_t shift_values[CVMX_QLM_JTAG_UINT32]; int num_lanes = cvmx_qlm_get_lanes(qlm); const __cvmx_qlm_jtag_field_t *field = __cvmx_qlm_lookup_field(name); int qlm_jtag_length = cvmx_qlm_jtag_get_length(); int total_length = qlm_jtag_length * num_lanes; int bits = 0; if (!field) return; /* Get the current state */ cvmx_helper_qlm_jtag_capture(qlm); for (i = 0; i < CVMX_QLM_JTAG_UINT32; i++) shift_values[i] = cvmx_helper_qlm_jtag_shift(qlm, 32, 0); /* Put new data in our local array */ for (l = 0; l < num_lanes; l++) { uint64_t new_value = value; int bits; int adj_lanes; if ((l != lane) && (lane != -1)) continue; if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) adj_lanes = l * qlm_jtag_length; else adj_lanes = (num_lanes - 1 - l) * qlm_jtag_length; for (bits = field->start_bit + adj_lanes; bits <= field->stop_bit + adj_lanes; bits++) { if (new_value & 1) shift_values[bits / 32] |= 1 << (bits & 31); else shift_values[bits / 32] &= ~(1 << (bits & 31)); new_value >>= 1; } } /* Shift out data and xor with reference */ while (bits < total_length) { uint32_t shift = shift_values[bits / 32] ^ __cvmx_qlm_jtag_xor_ref[qlm][bits / 32]; int width = total_length - bits; if (width > 32) width = 32; cvmx_helper_qlm_jtag_shift(qlm, width, shift); bits += 32; } /* Update the new data */ cvmx_helper_qlm_jtag_update(qlm); /* Always give the QLM 1ms to settle after every update. This may not always be needed, but some of the options make significant electrical changes */ cvmx_wait_usec(1000); }
/** * @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); }
/** * Initialize a PCIe port for use in host(RC) mode. It doesn't enumerate the bus. * * @param pcie_port PCIe port to initialize * * @return Zero on success */ int cvmx_pcie_rc_initialize(int pcie_port) { int i; cvmx_ciu_soft_prst_t ciu_soft_prst; cvmx_pescx_bist_status_t pescx_bist_status; cvmx_pescx_bist_status2_t pescx_bist_status2; cvmx_npei_ctl_status_t npei_ctl_status; cvmx_npei_mem_access_ctl_t npei_mem_access_ctl; cvmx_npei_mem_access_subidx_t mem_access_subid; cvmx_npei_dbg_data_t npei_dbg_data; cvmx_pescx_ctl_status2_t pescx_ctl_status2; cvmx_pciercx_cfg032_t pciercx_cfg032; retry: /* Make sure we aren't trying to setup a target mode interface in host mode */ npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); if ((pcie_port==0) && !npei_ctl_status.s.host_mode) { cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called on port0, but port0 is not in host mode\n"); return -1; } /* Make sure a CN52XX isn't trying to bring up port 1 when it is disabled */ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); if ((pcie_port==1) && npei_dbg_data.cn52xx.qlm0_link_width) { cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called on port1, but port1 is disabled\n"); return -1; } } /* PCIe switch arbitration mode. '0' == fixed priority NPEI, PCIe0, then PCIe1. '1' == round robin. */ npei_ctl_status.s.arb = 1; /* Allow up to 0x20 config retries */ npei_ctl_status.s.cfg_rtry = 0x20; /* CN52XX pass1.x has an errata where P0_NTAGS and P1_NTAGS don't reset */ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { npei_ctl_status.s.p0_ntags = 0x20; npei_ctl_status.s.p1_ntags = 0x20; } cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS, npei_ctl_status.u64); /* Bring the PCIe out of reset */ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) { /* The EBH5200 board swapped the PCIe reset lines on the board. As a workaround for this bug, we bring both PCIe ports out of reset at the same time instead of on separate calls. So for port 0, we bring both out of reset and do nothing on port 1 */ if (pcie_port == 0) { ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); /* After a chip reset the PCIe will also be in reset. If it isn't, most likely someone is trying to init it again without a proper PCIe reset */ if (ciu_soft_prst.s.soft_prst == 0) { /* Reset the ports */ ciu_soft_prst.s.soft_prst = 1; cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); ciu_soft_prst.s.soft_prst = 1; cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); /* Wait until pcie resets the ports. */ cvmx_wait_usec(2000); } ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); ciu_soft_prst.s.soft_prst = 0; cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); ciu_soft_prst.s.soft_prst = 0; cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); } } else { /* The normal case: The PCIe ports are completely separate and can be brought out of reset independently */ if (pcie_port) ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); else ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); /* After a chip reset the PCIe will also be in reset. If it isn't, most likely someone is trying to init it again without a proper PCIe reset */ if (ciu_soft_prst.s.soft_prst == 0) { /* Reset the port */ ciu_soft_prst.s.soft_prst = 1; if (pcie_port) cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); else cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); /* Wait until pcie resets the ports. */ cvmx_wait_usec(2000); } if (pcie_port) { ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); ciu_soft_prst.s.soft_prst = 0; cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); } else { ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); ciu_soft_prst.s.soft_prst = 0; cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); } } /* Wait for PCIe reset to complete. Due to errata PCIE-700, we don't poll PESCX_CTL_STATUS2[PCIERST], but simply wait a fixed number of cycles */ cvmx_wait(400000); /* PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of CN56XX and CN52XX, so we only probe it on newer chips */ if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { /* Clear PCLK_RUN so we can check if the clock is running */ pescx_ctl_status2.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); pescx_ctl_status2.s.pclk_run = 1; cvmx_write_csr(CVMX_PESCX_CTL_STATUS2(pcie_port), pescx_ctl_status2.u64); /* Now that we cleared PCLK_RUN, wait for it to be set again telling us the clock is running */ if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CTL_STATUS2(pcie_port), cvmx_pescx_ctl_status2_t, pclk_run, ==, 1, 10000)) { cvmx_dprintf("PCIe: Port %d isn't clocked, skipping.\n", pcie_port); return -1; } }
/** * Initialize a USB port for use. This must be called before any * other access to the Octeon USB port is made. The port starts * off in the disabled state. * * @param usb Pointer to an empty cvmx_usbd_state_t structure * that will be populated by the initialize call. * This structure is then passed to all other USB * functions. * @param usb_port_number * Which Octeon USB port to initialize. * @param flags Flags to control hardware initialization. See * cvmx_usbd_initialize_flags_t for the flag * definitions. Some flags are mandatory. * * @return Zero or a negative on error. */ int cvmx_usbd_initialize(cvmx_usbd_state_t *usb, int usb_port_number, cvmx_usbd_initialize_flags_t flags) { cvmx_usbnx_clk_ctl_t usbn_clk_ctl; cvmx_usbnx_usbp_ctl_status_t usbn_usbp_ctl_status; if (cvmx_unlikely(flags & CVMX_USBD_INITIALIZE_FLAGS_DEBUG)) cvmx_dprintf("%s: Called\n", __FUNCTION__); memset(usb, 0, sizeof(*usb)); usb->init_flags = flags; usb->index = usb_port_number; /* Try to determine clock type automatically */ if ((usb->init_flags & (CVMX_USBD_INITIALIZE_FLAGS_CLOCK_XO_XI | CVMX_USBD_INITIALIZE_FLAGS_CLOCK_XO_GND)) == 0) { if (__cvmx_helper_board_usb_get_clock_type() == USB_CLOCK_TYPE_CRYSTAL_12) usb->init_flags |= CVMX_USBD_INITIALIZE_FLAGS_CLOCK_XO_XI; /* Only 12 MHZ crystals are supported */ else usb->init_flags |= CVMX_USBD_INITIALIZE_FLAGS_CLOCK_XO_GND; } if (usb->init_flags & CVMX_USBD_INITIALIZE_FLAGS_CLOCK_XO_GND) { /* Check for auto ref clock frequency */ if (!(usb->init_flags & CVMX_USBD_INITIALIZE_FLAGS_CLOCK_MHZ_MASK)) switch (__cvmx_helper_board_usb_get_clock_type()) { case USB_CLOCK_TYPE_REF_12: usb->init_flags |= CVMX_USBD_INITIALIZE_FLAGS_CLOCK_12MHZ; break; case USB_CLOCK_TYPE_REF_24: usb->init_flags |= CVMX_USBD_INITIALIZE_FLAGS_CLOCK_24MHZ; break; case USB_CLOCK_TYPE_REF_48: default: usb->init_flags |= CVMX_USBD_INITIALIZE_FLAGS_CLOCK_48MHZ; break; } } /* Power On Reset and PHY Initialization */ /* 1. Wait for DCOK to assert (nothing to do) */ /* 2a. Write USBN0/1_CLK_CTL[POR] = 1 and USBN0/1_CLK_CTL[HRST,PRST,HCLK_RST] = 0 */ usbn_clk_ctl.u64 = cvmx_read_csr(CVMX_USBNX_CLK_CTL(usb->index)); usbn_clk_ctl.s.por = 1; usbn_clk_ctl.s.hrst = 0; usbn_clk_ctl.s.prst = 0; usbn_clk_ctl.s.hclk_rst = 0; usbn_clk_ctl.s.enable = 0; /* 2b. Select the USB reference clock/crystal parameters by writing appropriate values to USBN0/1_CLK_CTL[P_C_SEL, P_RTYPE, P_COM_ON] */ if (usb->init_flags & CVMX_USBD_INITIALIZE_FLAGS_CLOCK_XO_GND) { /* The USB port uses 12/24/48MHz 2.5V board clock source at USB_XO. USB_XI should be tied to GND. Most Octeon evaluation boards require this setting */ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { usbn_clk_ctl.cn31xx.p_rclk = 1; /* From CN31XX,CN30XX manual */ usbn_clk_ctl.cn31xx.p_xenbn = 0; } else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) usbn_clk_ctl.cn56xx.p_rtype = 2; /* From CN56XX,CN50XX manual */ else usbn_clk_ctl.cn52xx.p_rtype = 1; /* From CN52XX manual */ switch (usb->init_flags & CVMX_USBD_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) { case CVMX_USBD_INITIALIZE_FLAGS_CLOCK_12MHZ: usbn_clk_ctl.s.p_c_sel = 0; break; case CVMX_USBD_INITIALIZE_FLAGS_CLOCK_24MHZ: usbn_clk_ctl.s.p_c_sel = 1; break; case CVMX_USBD_INITIALIZE_FLAGS_CLOCK_48MHZ: usbn_clk_ctl.s.p_c_sel = 2; break; } } else { /* The USB port uses a 12MHz crystal as clock source at USB_XO and USB_XI */ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { usbn_clk_ctl.cn31xx.p_rclk = 1; /* From CN31XX,CN30XX manual */ usbn_clk_ctl.cn31xx.p_xenbn = 1; } else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) usbn_clk_ctl.cn56xx.p_rtype = 0; /* From CN56XX,CN50XX manual */ else usbn_clk_ctl.cn52xx.p_rtype = 0; /* From CN52XX manual */ usbn_clk_ctl.s.p_c_sel = 0; } /* 2c. Select the HCLK via writing USBN0/1_CLK_CTL[DIVIDE, DIVIDE2] and setting USBN0/1_CLK_CTL[ENABLE] = 1. Divide the core clock down such that USB is as close as possible to 125Mhz */ { int divisor = (cvmx_clock_get_rate(CVMX_CLOCK_CORE)+125000000-1)/125000000; if (divisor < 4) /* Lower than 4 doesn't seem to work properly */ divisor = 4; usbn_clk_ctl.s.divide = divisor; usbn_clk_ctl.s.divide2 = 0; } cvmx_write_csr(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); /* 2d. Write USBN0/1_CLK_CTL[HCLK_RST] = 1 */ usbn_clk_ctl.s.hclk_rst = 1; cvmx_write_csr(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); /* 2e. Wait 64 core-clock cycles for HCLK to stabilize */ cvmx_wait(64); /* 3. Program the power-on reset field in the USBN clock-control register: USBN_CLK_CTL[POR] = 0 */ usbn_clk_ctl.s.por = 0; cvmx_write_csr(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); /* 4. Wait 1 ms for PHY clock to start */ cvmx_wait_usec(1000); /* 5. Program the Reset input from automatic test equipment field in the USBP control and status register: USBN_USBP_CTL_STATUS[ATE_RESET] = 1 */ usbn_usbp_ctl_status.u64 = cvmx_read_csr(CVMX_USBNX_USBP_CTL_STATUS(usb->index)); usbn_usbp_ctl_status.s.ate_reset = 1; cvmx_write_csr(CVMX_USBNX_USBP_CTL_STATUS(usb->index), usbn_usbp_ctl_status.u64); /* 6. Wait 10 cycles */ cvmx_wait(10); /* 7. Clear ATE_RESET field in the USBN clock-control register: USBN_USBP_CTL_STATUS[ATE_RESET] = 0 */ usbn_usbp_ctl_status.s.ate_reset = 0; cvmx_write_csr(CVMX_USBNX_USBP_CTL_STATUS(usb->index), usbn_usbp_ctl_status.u64); /* 8. Program the PHY reset field in the USBN clock-control register: USBN_CLK_CTL[PRST] = 1 */ usbn_clk_ctl.s.prst = 1; cvmx_write_csr(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); /* 9. Program the USBP control and status register to select host or device mode. USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for device */ usbn_usbp_ctl_status.s.hst_mode = 1; usbn_usbp_ctl_status.s.dm_pulld = 0; usbn_usbp_ctl_status.s.dp_pulld = 0; cvmx_write_csr(CVMX_USBNX_USBP_CTL_STATUS(usb->index), usbn_usbp_ctl_status.u64); /* 10. Wait 1 µs */ cvmx_wait_usec(1); /* 11. Program the hreset_n field in the USBN clock-control register: USBN_CLK_CTL[HRST] = 1 */ usbn_clk_ctl.s.hrst = 1; cvmx_write_csr(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); /* 12. Proceed to USB core initialization */ usbn_clk_ctl.s.enable = 1; cvmx_write_csr(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); cvmx_wait_usec(1); /* Program the following fields in the global AHB configuration register (USBC_GAHBCFG) DMA mode, USBC_GAHBCFG[DMAEn]: 1 = DMA mode, 0 = slave mode Burst length, USBC_GAHBCFG[HBSTLEN] = 0 Nonperiodic TxFIFO empty level (slave mode only), USBC_GAHBCFG[NPTXFEMPLVL] Periodic TxFIFO empty level (slave mode only), USBC_GAHBCFG[PTXFEMPLVL] Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1 */ { cvmx_usbcx_gahbcfg_t usbcx_gahbcfg; usbcx_gahbcfg.u32 = 0; usbcx_gahbcfg.s.dmaen = 1; usbcx_gahbcfg.s.hbstlen = 0; usbcx_gahbcfg.s.nptxfemplvl = 1; usbcx_gahbcfg.s.ptxfemplvl = 1; usbcx_gahbcfg.s.glblintrmsk = 1; __cvmx_usbd_write_csr32(usb, CVMX_USBCX_GAHBCFG(usb->index), usbcx_gahbcfg.u32); } /* Program the following fields in USBC_GUSBCFG register. HS/FS timeout calibration, USBC_GUSBCFG[TOUTCAL] = 0 ULPI DDR select, USBC_GUSBCFG[DDRSEL] = 0 USB turnaround time, USBC_GUSBCFG[USBTRDTIM] = 0x5 PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0 */ { cvmx_usbcx_gusbcfg_t usbcx_gusbcfg; usbcx_gusbcfg.u32 = __cvmx_usbd_read_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index)); usbcx_gusbcfg.s.toutcal = 0; usbcx_gusbcfg.s.ddrsel = 0; usbcx_gusbcfg.s.usbtrdtim = 0x5; usbcx_gusbcfg.s.phylpwrclksel = 0; __cvmx_usbd_write_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index), usbcx_gusbcfg.u32); } /* Program the following fields in the USBC0/1_DCFG register: Device speed, USBC0/1_DCFG[DEVSPD] = 0 (high speed) Non-zero-length status OUT handshake, USBC0/1_DCFG[NZSTSOUTHSHK]=0 Periodic frame interval (if periodic endpoints are supported), USBC0/1_DCFG[PERFRINT] = 1 */ { cvmx_usbcx_dcfg_t usbcx_dcfg; usbcx_dcfg.u32 = __cvmx_usbd_read_csr32(usb, CVMX_USBCX_DCFG(usb->index)); usbcx_dcfg.s.devspd = 0; usbcx_dcfg.s.nzstsouthshk = 0; usbcx_dcfg.s.perfrint = 1; __cvmx_usbd_write_csr32(usb, CVMX_USBCX_DCFG(usb->index), usbcx_dcfg.u32); } /* Program the USBC0/1_GINTMSK register */ { cvmx_usbcx_gintmsk_t usbcx_gintmsk; usbcx_gintmsk.u32 = __cvmx_usbd_read_csr32(usb, CVMX_USBCX_GINTMSK(usb->index)); usbcx_gintmsk.s.oepintmsk = 1; usbcx_gintmsk.s.inepintmsk = 1; usbcx_gintmsk.s.enumdonemsk = 1; usbcx_gintmsk.s.usbrstmsk = 1; usbcx_gintmsk.s.usbsuspmsk = 1; __cvmx_usbd_write_csr32(usb, CVMX_USBCX_GINTMSK(usb->index), usbcx_gintmsk.u32); } cvmx_usbd_disable(usb); return 0; }
void oct_directfw_set() { uint32_t port; oct_directfw = srv_dp_sync->dp_directfw_able; oct_directfw_sleeptime = srv_dp_sync->dp_directfw_sleep_time; if(oct_directfw) { for(port = OCT_PHY_PORT_FIRST; port < OCT_PHY_PORT_MAX; port++) { cvmx_pip_port_tag_cfg_t tag_config; /*config group*/ tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(port)); tag_config.s.grp = FROM_INPUT_PORT_GROUP; if( running_core_num == 4) { /*config tuple of hash value*/ tag_config.cn70xx.ip4_src_flag = 0; tag_config.cn70xx.ip4_dst_flag = 0; tag_config.cn70xx.ip4_sprt_flag = 0; tag_config.cn70xx.ip4_dprt_flag = 0; tag_config.cn70xx.ip4_pctl_flag = 0; tag_config.cn70xx.grptag = 0; tag_config.cn70xx.grptagmask = 0; tag_config.cn70xx.grptagbase = 0; } cvmx_write_csr(CVMX_PIP_PRT_TAGX(port), tag_config.u64); cvmx_wait_usec(1000); } } else { for(port = OCT_PHY_PORT_FIRST; port < OCT_PHY_PORT_MAX; port++) { cvmx_pip_port_tag_cfg_t tag_config; /*config group*/ tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(port)); tag_config.s.grp = FROM_INPUT_PORT_GROUP; if( running_core_num == 4) { /*config tuple of hash value*/ tag_config.cn70xx.ip4_src_flag = 1; tag_config.cn70xx.ip4_dst_flag = 1; tag_config.cn70xx.ip4_sprt_flag = 1; tag_config.cn70xx.ip4_dprt_flag = 1; tag_config.cn70xx.ip4_pctl_flag = 1; tag_config.cn70xx.grptag = 1; tag_config.cn70xx.grptagmask = 0xc; tag_config.cn70xx.grptagbase = 1; } cvmx_write_csr(CVMX_PIP_PRT_TAGX(port), tag_config.u64); cvmx_wait_usec(1000); } } }
//#define CVMX_ILK_STATS_ENA 1 int cvmx_ilk_enable (int interface) { int res = -1; int retry_count = 0; cvmx_helper_link_info_t result; cvmx_ilk_txx_cfg1_t ilk_txx_cfg1; cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1; #ifdef CVMX_ILK_STATS_ENA cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; #endif if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) return res; if (interface >= CVMX_NUM_ILK_INTF) return res; result.u64 = 0; #ifdef CVMX_ILK_STATS_ENA cvmx_dprintf ("\n"); cvmx_dprintf ("<<<< ILK%d: Before enabling ilk\n", interface); cvmx_ilk_reg_dump_rx (interface); cvmx_ilk_reg_dump_tx (interface); #endif /* RX packet will be enabled only if link is up */ /* TX side */ ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface)); ilk_txx_cfg1.s.pkt_ena = 1; ilk_txx_cfg1.s.rx_link_fc_ign = 1; /* cannot use link fc workaround */ cvmx_write_csr (CVMX_ILK_TXX_CFG1(interface), ilk_txx_cfg1.u64); cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface)); #ifdef CVMX_ILK_STATS_ENA /* RX side stats */ ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); ilk_rxx_cfg0.s.lnk_stats_ena = 1; cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); /* TX side stats */ ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); ilk_txx_cfg0.s.lnk_stats_ena = 1; cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); #endif retry: retry_count++; if (retry_count > 10) goto out; /* Make sure the link is up, so that packets can be sent. */ result = __cvmx_helper_ilk_link_get(cvmx_helper_get_ipd_port(interface + CVMX_ILK_GBL_BASE, 0)); /* Small delay before another retry. */ cvmx_wait_usec(100); ilk_rxx_cfg1.u64 = cvmx_read_csr(CVMX_ILK_RXX_CFG1(interface)); if (ilk_rxx_cfg1.s.pkt_ena == 0) goto retry; out: #ifdef CVMX_ILK_STATS_ENA cvmx_dprintf (">>>> ILK%d: After ILK is enabled\n", interface); cvmx_ilk_reg_dump_rx (interface); cvmx_ilk_reg_dump_tx (interface); #endif if (result.s.link_up) return 0; return -1; }
/** * Measure the reference clock of a QLM * * @param qlm QLM to measure * * @return Clock rate in Hz * */ int cvmx_qlm_measure_clock(int qlm) { cvmx_mio_ptp_clock_cfg_t ptp_clock; uint64_t count; uint64_t start_cycle, stop_cycle; #ifdef CVMX_BUILD_FOR_UBOOT int ref_clock[16] = {0}; #else static int ref_clock[16] = {0}; #endif if (ref_clock[qlm]) return ref_clock[qlm]; if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) return -1; /* Force the reference to 156.25Mhz when running in simulation. This supports the most speeds */ #ifdef CVMX_BUILD_FOR_UBOOT if (gd->arch.board_desc.board_type == CVMX_BOARD_TYPE_SIM) return 156250000; #elif !defined(CVMX_BUILD_FOR_LINUX_HOST) if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) return 156250000; #endif /* Disable the PTP event counter while we configure it */ ptp_clock.u64 = cvmx_read_csr(CVMX_MIO_PTP_CLOCK_CFG); /* For CN63XXp1 errata */ ptp_clock.s.evcnt_en = 0; cvmx_write_csr(CVMX_MIO_PTP_CLOCK_CFG, ptp_clock.u64); /* Count on rising edge, Choose which QLM to count */ ptp_clock.u64 = cvmx_read_csr(CVMX_MIO_PTP_CLOCK_CFG); /* For CN63XXp1 errata */ ptp_clock.s.evcnt_edge = 0; ptp_clock.s.evcnt_in = 0x10 + qlm; cvmx_write_csr(CVMX_MIO_PTP_CLOCK_CFG, ptp_clock.u64); /* Clear MIO_PTP_EVT_CNT */ cvmx_read_csr(CVMX_MIO_PTP_EVT_CNT); /* For CN63XXp1 errata */ count = cvmx_read_csr(CVMX_MIO_PTP_EVT_CNT); cvmx_write_csr(CVMX_MIO_PTP_EVT_CNT, -count); /* Set MIO_PTP_EVT_CNT to 1 billion */ cvmx_write_csr(CVMX_MIO_PTP_EVT_CNT, 1000000000); /* Enable the PTP event counter */ ptp_clock.u64 = cvmx_read_csr(CVMX_MIO_PTP_CLOCK_CFG); /* For CN63XXp1 errata */ ptp_clock.s.evcnt_en = 1; cvmx_write_csr(CVMX_MIO_PTP_CLOCK_CFG, ptp_clock.u64); start_cycle = cvmx_clock_get_count(CVMX_CLOCK_CORE); /* Wait for 50ms */ cvmx_wait_usec(50000); /* Read the counter */ cvmx_read_csr(CVMX_MIO_PTP_EVT_CNT); /* For CN63XXp1 errata */ count = cvmx_read_csr(CVMX_MIO_PTP_EVT_CNT); stop_cycle = cvmx_clock_get_count(CVMX_CLOCK_CORE); /* Disable the PTP event counter */ ptp_clock.u64 = cvmx_read_csr(CVMX_MIO_PTP_CLOCK_CFG); /* For CN63XXp1 errata */ ptp_clock.s.evcnt_en = 0; cvmx_write_csr(CVMX_MIO_PTP_CLOCK_CFG, ptp_clock.u64); /* Clock counted down, so reverse it */ count = 1000000000 - count; /* Return the rate */ ref_clock[qlm] = count * cvmx_clock_get_rate(CVMX_CLOCK_CORE) / (stop_cycle - start_cycle); return ref_clock[qlm]; }