/** * Modify the device tree to remove all unused interface types. */ int board_fixup_fdt(void) { const char *fdt_key; cvmx_mio_qlmx_cfg_t mio_qlmx; char *eptr; mio_qlmx.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2)); if (mio_qlmx.s.qlm_spd == 15) { fdt_key = "0,none"; /* Disabled */ } else if (mio_qlmx.s.qlm_cfg == 3) { fdt_key = "0,xaui"; } else if (mio_qlmx.s.qlm_cfg == 2) { fdt_key = "0,sgmii"; } else { fdt_key = "0,none"; /* Disabled */ } octeon_fdt_patch(working_fdt, fdt_key, NULL); mio_qlmx.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0)); if (mio_qlmx.s.qlm_spd == 15) { fdt_key = "1,none"; /* Disabled */ } else if (mio_qlmx.s.qlm_cfg == 3) { fdt_key = "1,xaui"; } else if (mio_qlmx.s.qlm_cfg == 2) { fdt_key = "1,sgmii"; } else { fdt_key = "1,none"; } octeon_fdt_patch(working_fdt, fdt_key, NULL); /* * If 'enable_spi_eeprom' is set in the environment, clear bit * 2 of register 0x15 in the CPLD to enable the SPI EEPROM, * then hijack octeon_fdt_patch to enable/disable the eeprom * in the device tree. */ eptr = getenv("enable_spi_eeprom"); fdt_key = "9,none"; if (eptr) { uchar rv; int ret; ret = i2c_read(0x6c, 0x15, 1, &rv, 1); if (ret == 0) { if (rv == 0) fdt_key = "9,eeprom"; i2c_reg_write(0x6c, 0x15, rv); } } octeon_fdt_patch(working_fdt, fdt_key, NULL); 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 = 0; int qlm; if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X)) num_qlms = 5; else if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X)) num_qlms = 3; else return; /* 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); } } }
int early_board_init(void) { { /* configure clk_out pin */ cvmx_mio_fus_pll_t fus_pll; fus_pll.u64 = cvmx_read_csr(CVMX_MIO_FUS_PLL); fus_pll.cn63xx.c_cout_rst = 1; cvmx_write_csr(CVMX_MIO_FUS_PLL, fus_pll.u64); /* Sel:: 0:rclk, 1:pllout 2:psout 3:gnd */ fus_pll.cn63xx.c_cout_sel = 0; cvmx_write_csr(CVMX_MIO_FUS_PLL, fus_pll.u64); fus_pll.cn63xx.c_cout_rst = 0; cvmx_write_csr(CVMX_MIO_FUS_PLL, fus_pll.u64); } /* Configure the QLM modes.... */ { cvmx_mio_qlmx_cfg_t qlm_cfg; qlm_cfg.u64= 0; qlm_cfg.s.qlm_spd = 0x3; qlm_cfg.s.qlm_cfg = 0x2; cvmx_write_csr(CVMX_MIO_QLMX_CFG(0), qlm_cfg.u64); } /* NOTE: this is early in the init process, so the serial port is not * yet configured */ /* Populate global data from eeprom */ octeon_board_get_clock_info(EVB7100_DEF_DRAM_FREQ); octeon_board_get_descriptor(CVMX_BOARD_TYPE_EVB7100, 1, 0); /* CNF71XX has a fixed 50 MHz reference clock */ gd->arch.ddr_ref_hertz = 50000000; if (gd->mem_clk < 100 || gd->mem_clk > 2000) gd->mem_clk = EVB7100_DEF_DRAM_FREQ; octeon_board_get_mac_addr(); octeon_led_str_write("Booting."); return 0; }
/* * Read QLM and return status based on CN66XX. * @return Return 1 if QLM is SGMII * 2 if QLM is XAUI * 3 if QLM is PCIe gen2 / gen1 * 4 if QLM is SRIO 1x4 short / long * 5 if QLM is SRIO 2x2 short / long * 6 if QLM is SRIO 4x1 short / long * 7 if QLM is PCIe 1x2 gen2 / gen1 * 8 if QLM is PCIe 2x1 gen2 / gen1 * 9 if QLM is ILK * 10 if QLM is RXAUI * -1 otherwise */ int cvmx_qlm_get_status(int qlm) { cvmx_mio_qlmx_cfg_t qlmx_cfg; if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); /* QLM is disabled when QLM SPD is 15. */ if (qlmx_cfg.s.qlm_spd == 15) return -1; switch (qlmx_cfg.s.qlm_cfg) { case 0: /* PCIE */ return 3; case 1: /* ILK */ return 9; case 2: /* SGMII */ return 1; case 3: /* XAUI */ return 2; case 7: /* RXAUI */ return 10; default: return -1; } } else if (OCTEON_IS_MODEL(OCTEON_CN66XX)) { qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); /* QLM is disabled when QLM SPD is 15. */ if (qlmx_cfg.s.qlm_spd == 15) return -1; switch (qlmx_cfg.s.qlm_cfg) { case 0x9: /* SGMII */ return 1; case 0xb: /* XAUI */ return 2; case 0x0: /* PCIE gen2 */ case 0x8: /* PCIE gen2 (alias) */ case 0x2: /* PCIE gen1 */ case 0xa: /* PCIE gen1 (alias) */ return 3; case 0x1: /* SRIO 1x4 short */ case 0x3: /* SRIO 1x4 long */ return 4; case 0x4: /* SRIO 2x2 short */ case 0x6: /* SRIO 2x2 long */ return 5; case 0x5: /* SRIO 4x1 short */ case 0x7: /* SRIO 4x1 long */ if (!OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0)) return 6; default: return -1; } } else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) { cvmx_sriox_status_reg_t status_reg; /* For now skip qlm2 */ if (qlm == 2) { cvmx_gmxx_inf_mode_t inf_mode; inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0)); if (inf_mode.s.speed == 15) return -1; else if(inf_mode.s.mode == 0) return 1; else return 2; } status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm)); if (status_reg.s.srio) return 4; else return 3; } else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) { qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); /* QLM is disabled when QLM SPD is 15. */ if (qlmx_cfg.s.qlm_spd == 15) return -1; switch(qlm) { case 0: switch (qlmx_cfg.s.qlm_cfg) { case 0: /* PCIe 1x4 gen2 / gen1 */ return 3; case 2: /* SGMII */ return 1; case 3: /* XAUI */ return 2; default: return -1; } break; case 1: switch (qlmx_cfg.s.qlm_cfg) { case 0: /* PCIe 1x2 gen2 / gen1 */ return 7; case 1: /* PCIe 2x1 gen2 / gen1 */ return 8; default: return -1; } break; case 2: switch (qlmx_cfg.s.qlm_cfg) { case 2: /* SGMII */ return 1; case 3: /* XAUI */ return 2; default: return -1; } break; } } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) { qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); /* QLM is disabled when QLM SPD is 15. */ if (qlmx_cfg.s.qlm_spd == 15) return -1; switch(qlm) { case 0: if (qlmx_cfg.s.qlm_cfg == 2) /* SGMII */ return 1; break; case 1: switch (qlmx_cfg.s.qlm_cfg) { case 0: /* PCIe 1x2 gen2 / gen1 */ return 7; case 1: /* PCIe 2x1 gen2 / gen1 */ return 8; default: return -1; } break; } } return -1; }
/** * 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_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX)) { 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 */ } } return 0; }
/** * Initialize and start the ILK interface. * * @param interface The identifier of the packet interface to configure and * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and * ilk1. * * @param lane_mask the lane group for this interface * * @return Zero on success, negative of failure. */ int cvmx_ilk_start_interface (int interface, unsigned char lane_mask) { int res = -1; int other_intf, this_qlm, other_qlm; unsigned char uni_mask; cvmx_mio_qlmx_cfg_t mio_qlmx_cfg, other_mio_qlmx_cfg; cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; cvmx_ilk_ser_cfg_t ilk_ser_cfg; if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) return res; if (interface >= CVMX_NUM_ILK_INTF) return res; if (lane_mask == 0) return res; /* check conflicts between 2 ilk interfaces. 1 lane can be assigned to 1 * interface only */ other_intf = !interface; this_qlm = interface + CVMX_ILK_QLM_BASE; other_qlm = other_intf + CVMX_ILK_QLM_BASE; if (cvmx_ilk_intf_cfg[other_intf].lane_en_mask & lane_mask) { cvmx_dprintf ("ILK%d: %s: lane assignment conflict\n", interface, __FUNCTION__); return res; } /* check the legality of the lane mask. interface 0 can have 8 lanes, * while interface 1 can have 4 lanes at most */ uni_mask = lane_mask >> (interface * 4); if ((uni_mask != 0x1 && uni_mask != 0x3 && uni_mask != 0xf && uni_mask != 0xff) || (interface == 1 && lane_mask > 0xf0)) { #if CVMX_ENABLE_DEBUG_PRINTS cvmx_dprintf ("ILK%d: %s: incorrect lane mask: 0x%x \n", interface, __FUNCTION__, uni_mask); #endif return res; } /* check the availability of qlms. qlm_cfg = 001 means the chip is fused * to give this qlm to ilk */ mio_qlmx_cfg.u64 = cvmx_read_csr (CVMX_MIO_QLMX_CFG(this_qlm)); other_mio_qlmx_cfg.u64 = cvmx_read_csr (CVMX_MIO_QLMX_CFG(other_qlm)); if (mio_qlmx_cfg.s.qlm_cfg != 1 || (uni_mask == 0xff && other_mio_qlmx_cfg.s.qlm_cfg != 1)) { #if CVMX_ENABLE_DEBUG_PRINTS cvmx_dprintf ("ILK%d: %s: qlm unavailable\n", interface, __FUNCTION__); #endif return res; } /* power up the serdes */ ilk_ser_cfg.u64 = cvmx_read_csr (CVMX_ILK_SER_CFG); if (ilk_ser_cfg.s.ser_pwrup == 0) { ilk_ser_cfg.s.ser_rxpol_auto = 1; ilk_ser_cfg.s.ser_rxpol = 0; ilk_ser_cfg.s.ser_txpol = 0; ilk_ser_cfg.s.ser_reset_n = 0xff; ilk_ser_cfg.s.ser_haul = 0; } ilk_ser_cfg.s.ser_pwrup |= ((interface ==0) && (lane_mask > 0xf)) ? 0x3 : (1 << interface); cvmx_write_csr (CVMX_ILK_SER_CFG, ilk_ser_cfg.u64); /* configure the lane enable of the interface */ ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); ilk_txx_cfg0.s.lane_ena = ilk_rxx_cfg0.s.lane_ena = lane_mask; cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); /* write to local cache. for lane speed, if interface 0 has 8 lanes, * assume both qlms have the same speed */ cvmx_ilk_intf_cfg[interface].intf_en = 1; cvmx_ilk_intf_cfg[interface].lane_en_mask = lane_mask; res = 0; return res; }
static enum cvmx_qlm_mode __cvmx_qlm_get_mode_cn6xxx(int qlm) { cvmx_mio_qlmx_cfg_t qlmx_cfg; if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); /* QLM is disabled when QLM SPD is 15. */ if (qlmx_cfg.s.qlm_spd == 15) return CVMX_QLM_MODE_DISABLED; switch (qlmx_cfg.s.qlm_cfg) { case 0: /* PCIE */ return CVMX_QLM_MODE_PCIE; case 1: /* ILK */ return CVMX_QLM_MODE_ILK; case 2: /* SGMII */ return CVMX_QLM_MODE_SGMII; case 3: /* XAUI */ return CVMX_QLM_MODE_XAUI; case 7: /* RXAUI */ return CVMX_QLM_MODE_RXAUI; default: return CVMX_QLM_MODE_DISABLED; } } else if (OCTEON_IS_MODEL(OCTEON_CN66XX)) { qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); /* QLM is disabled when QLM SPD is 15. */ if (qlmx_cfg.s.qlm_spd == 15) return CVMX_QLM_MODE_DISABLED; switch (qlmx_cfg.s.qlm_cfg) { case 0x9: /* SGMII */ return CVMX_QLM_MODE_SGMII; case 0xb: /* XAUI */ return CVMX_QLM_MODE_XAUI; case 0x0: /* PCIE gen2 */ case 0x8: /* PCIE gen2 (alias) */ case 0x2: /* PCIE gen1 */ case 0xa: /* PCIE gen1 (alias) */ return CVMX_QLM_MODE_PCIE; case 0x1: /* SRIO 1x4 short */ case 0x3: /* SRIO 1x4 long */ return CVMX_QLM_MODE_SRIO_1X4; case 0x4: /* SRIO 2x2 short */ case 0x6: /* SRIO 2x2 long */ return CVMX_QLM_MODE_SRIO_2X2; case 0x5: /* SRIO 4x1 short */ case 0x7: /* SRIO 4x1 long */ if (!OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0)) return CVMX_QLM_MODE_SRIO_4X1; /* fallthrough */ default: return CVMX_QLM_MODE_DISABLED; } } else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) { cvmx_sriox_status_reg_t status_reg; /* For now skip qlm2 */ if (qlm == 2) { cvmx_gmxx_inf_mode_t inf_mode; inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0)); if (inf_mode.s.speed == 15) return CVMX_QLM_MODE_DISABLED; else if (inf_mode.s.mode == 0) return CVMX_QLM_MODE_SGMII; else return CVMX_QLM_MODE_XAUI; } status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm)); if (status_reg.s.srio) return CVMX_QLM_MODE_SRIO_1X4; else return CVMX_QLM_MODE_PCIE; } else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) { qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); /* QLM is disabled when QLM SPD is 15. */ if (qlmx_cfg.s.qlm_spd == 15) return CVMX_QLM_MODE_DISABLED; switch (qlm) { case 0: switch (qlmx_cfg.s.qlm_cfg) { case 0: /* PCIe 1x4 gen2 / gen1 */ return CVMX_QLM_MODE_PCIE; case 2: /* SGMII */ return CVMX_QLM_MODE_SGMII; case 3: /* XAUI */ return CVMX_QLM_MODE_XAUI; default: return CVMX_QLM_MODE_DISABLED; } break; case 1: switch (qlmx_cfg.s.qlm_cfg) { case 0: /* PCIe 1x2 gen2 / gen1 */ return CVMX_QLM_MODE_PCIE_1X2; case 1: /* PCIe 2x1 gen2 / gen1 */ return CVMX_QLM_MODE_PCIE_2X1; default: return CVMX_QLM_MODE_DISABLED; } break; case 2: switch (qlmx_cfg.s.qlm_cfg) { case 2: /* SGMII */ return CVMX_QLM_MODE_SGMII; case 3: /* XAUI */ return CVMX_QLM_MODE_XAUI; default: return CVMX_QLM_MODE_DISABLED; } break; } } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) { qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); /* QLM is disabled when QLM SPD is 15. */ if (qlmx_cfg.s.qlm_spd == 15) return CVMX_QLM_MODE_DISABLED; switch (qlm) { case 0: if (qlmx_cfg.s.qlm_cfg == 2) /* SGMII */ return CVMX_QLM_MODE_SGMII; break; case 1: switch (qlmx_cfg.s.qlm_cfg) { case 0: /* PCIe 1x2 gen2 / gen1 */ return CVMX_QLM_MODE_PCIE_1X2; case 1: /* PCIe 2x1 gen2 / gen1 */ return CVMX_QLM_MODE_PCIE_2X1; default: return CVMX_QLM_MODE_DISABLED; } break; } } return CVMX_QLM_MODE_DISABLED; }
/** * 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; }
/** * 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); } } } }