diff --git a/sys/contrib/octeon-sdk/cvmx-app-init.h b/sys/contrib/octeon-sdk/cvmx-app-init.h index 605f43e77f38..beab38e66e1e 100644 --- a/sys/contrib/octeon-sdk/cvmx-app-init.h +++ b/sys/contrib/octeon-sdk/cvmx-app-init.h @@ -120,6 +120,9 @@ struct cvmx_bootinfo { uint32_t dfa_ref_clock_hz; /**< DFA reference clock in hz (if applicable)*/ uint32_t config_flags; /**< flags indicating various configuration options. These flags supercede ** the 'flags' variable and should be used instead if available */ +#if defined(OCTEON_VENDOR_GEFES) + uint32_t dfm_size; /**< DFA Size */ +#endif #endif #if (CVMX_BOOTINFO_MIN_VER >= 3) uint64_t fdt_addr; /**< Address of the OF Flattened Device Tree structure describing the board. */ @@ -216,10 +219,17 @@ enum cvmx_board_types_enum { CVMX_BOARD_TYPE_HIKARI = 10, CVMX_BOARD_TYPE_CN3010_EVB_HS5 = 11, CVMX_BOARD_TYPE_CN3005_EVB_HS5 = 12, +#if defined(OCTEON_VENDOR_GEFES) + CVMX_BOARD_TYPE_TNPA3804 = 13, + CVMX_BOARD_TYPE_AT5810 = 14, + CVMX_BOARD_TYPE_WNPA3850 = 15, + CVMX_BOARD_TYPE_W3860 = 16, +#else CVMX_BOARD_TYPE_KBP = 13, CVMX_BOARD_TYPE_CN3020_EVB_HS5 = 14, /* Deprecated, CVMX_BOARD_TYPE_CN3010_EVB_HS5 supports the CN3020 */ CVMX_BOARD_TYPE_EBT5800 = 15, CVMX_BOARD_TYPE_NICPRO2 = 16, +#endif CVMX_BOARD_TYPE_EBH5600 = 17, CVMX_BOARD_TYPE_EBH5601 = 18, CVMX_BOARD_TYPE_EBH5200 = 19, @@ -304,6 +314,16 @@ enum cvmx_board_types_enum { #endif #if defined(OCTEON_VENDOR_RADISYS) CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE=20002, +#endif +#if defined(OCTEON_VENDOR_GEFES) + CVMX_BOARD_TYPE_CUST_TNPA5804 = 20005, + CVMX_BOARD_TYPE_CUST_W5434 = 20006, + CVMX_BOARD_TYPE_CUST_W5650 = 20007, + CVMX_BOARD_TYPE_CUST_W5800 = 20008, + CVMX_BOARD_TYPE_CUST_W5651X = 20009, + CVMX_BOARD_TYPE_CUST_TNPA5651X = 20010, + CVMX_BOARD_TYPE_CUST_TNPA56X4 = 20011, + CVMX_BOARD_TYPE_CUST_W63XX = 20013, #endif CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000, @@ -352,10 +372,17 @@ static inline const char *cvmx_board_type_to_string(enum cvmx_board_types_enum t ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_HIKARI) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3010_EVB_HS5) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3005_EVB_HS5) +#if defined(OCTEON_VENDOR_GEFES) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_TNPA3804) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_AT5810) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_WNPA3850) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_W3860) +#else ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KBP) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3020_EVB_HS5) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5800) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NICPRO2) +#endif ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5600) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5601) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5200) @@ -420,7 +447,6 @@ static inline const char *cvmx_board_type_to_string(enum cvmx_board_types_enum t #else ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_ZINWELL) #endif - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MAX) /* Customer private range */ @@ -434,6 +460,16 @@ static inline const char *cvmx_board_type_to_string(enum cvmx_board_types_enum t #endif #if defined(OCTEON_VENDOR_RADISYS) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE) +#endif +#if defined(OCTEON_VENDOR_GEFES) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_TNPA5804) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_W5434) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_W5650) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_W5800) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_W5651X) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_TNPA5651X) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_TNPA56X4) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_W63XX) #endif ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX) diff --git a/sys/contrib/octeon-sdk/cvmx-helper-board.c b/sys/contrib/octeon-sdk/cvmx-helper-board.c index d97813ea85d0..49e52d47d1bc 100644 --- a/sys/contrib/octeon-sdk/cvmx-helper-board.c +++ b/sys/contrib/octeon-sdk/cvmx-helper-board.c @@ -385,10 +385,12 @@ int cvmx_helper_board_get_mii_address(int ipd_port) case CVMX_BOARD_TYPE_SIM: /* Simulator doesn't have MII */ return -1; - case CVMX_BOARD_TYPE_EBT3000: +#if !defined(OCTEON_VENDOR_GEFES) case CVMX_BOARD_TYPE_EBT5800: - case CVMX_BOARD_TYPE_THUNDER: case CVMX_BOARD_TYPE_NICPRO2: +#endif + case CVMX_BOARD_TYPE_EBT3000: + case CVMX_BOARD_TYPE_THUNDER: /* Interface 0 is SPI4, interface 1 is RGMII */ if ((ipd_port >= 16) && (ipd_port < 20)) return ipd_port - 16; @@ -410,7 +412,9 @@ int cvmx_helper_board_get_mii_address(int ipd_port) case CVMX_BOARD_TYPE_HIKARI: case CVMX_BOARD_TYPE_CN3010_EVB_HS5: case CVMX_BOARD_TYPE_CN3005_EVB_HS5: +#if !defined(OCTEON_VENDOR_GEFES) case CVMX_BOARD_TYPE_CN3020_EVB_HS5: +#endif /* Port 0 is WAN connected to a PHY, Port 1 is GMII connected to a switch */ if (ipd_port == 0) @@ -602,6 +606,30 @@ int cvmx_helper_board_get_mii_address(int ipd_port) case CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE: /* No MII. */ return -1; +#endif +#if defined(OCTEON_VENDOR_GEFES) + case CVMX_BOARD_TYPE_AT5810: + return -1; + case CVMX_BOARD_TYPE_TNPA3804: + case CVMX_BOARD_TYPE_CUST_TNPA5804: + case CVMX_BOARD_TYPE_CUST_W5800: + case CVMX_BOARD_TYPE_WNPA3850: + case CVMX_BOARD_TYPE_W3860: + return -1;// RGMII boards should use inbad status + case CVMX_BOARD_TYPE_CUST_W5651X: + case CVMX_BOARD_TYPE_CUST_W5650: + case CVMX_BOARD_TYPE_CUST_TNPA56X4: + case CVMX_BOARD_TYPE_CUST_TNPA5651X: + case CVMX_BOARD_TYPE_CUST_W63XX: + return -1; /* No PHYs are connected to Octeon, PHYs inside of SFPs which is accessed over TWSI */ + case CVMX_BOARD_TYPE_CUST_W5434: + /* Board has 4 SGMII ports. 4 connect out + * must return the MII address of the PHY connected to each IPD port + */ + if ((ipd_port >= 16) && (ipd_port < 20)) + return ipd_port - 16 + 0x40; + else + return -1; #endif } @@ -991,7 +1019,9 @@ cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) case CVMX_BOARD_TYPE_EBH3100: case CVMX_BOARD_TYPE_CN3010_EVB_HS5: case CVMX_BOARD_TYPE_CN3005_EVB_HS5: +#if !defined(OCTEON_VENDOR_GEFES) case CVMX_BOARD_TYPE_CN3020_EVB_HS5: +#endif /* Port 1 on these boards is always Gigabit */ if (ipd_port == 1) { @@ -1076,6 +1106,15 @@ cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) return result; } break; +#endif +#if defined(OCTEON_VENDOR_GEFES) + case CVMX_BOARD_TYPE_CUST_TNPA5651X: + /* Since we don't auto-negotiate... 1Gbps full duplex link */ + result.s.link_up = 1; + result.s.full_duplex = 1; + result.s.speed = 1000; + return result; + break; #endif } #endif @@ -1103,6 +1142,44 @@ cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) here. Reading broken in-band status tends to do bad things */ result = __get_inband_link_state(ipd_port); } +#if defined(OCTEON_VENDOR_GEFES) + else if( (OCTEON_IS_MODEL(OCTEON_CN56XX)) || (OCTEON_IS_MODEL(OCTEON_CN63XX)) ) + { + int interface = cvmx_helper_get_interface_num(ipd_port); + int index = cvmx_helper_get_interface_index_num(ipd_port); + cvmx_pcsx_miscx_ctl_reg_t mode_type; + cvmx_pcsx_mrx_status_reg_t mrx_status; + cvmx_pcsx_anx_adv_reg_t anxx_adv; + cvmx_pcsx_sgmx_lp_adv_reg_t sgmii_inband_status; + + anxx_adv.u64 = cvmx_read_csr(CVMX_PCSX_ANX_ADV_REG(index, interface)); + mrx_status.u64 = cvmx_read_csr(CVMX_PCSX_MRX_STATUS_REG(index, interface)); + + mode_type.u64 = cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); + + /* Read Octeon's inband status */ + sgmii_inband_status.u64 = cvmx_read_csr(CVMX_PCSX_SGMX_LP_ADV_REG(index, interface)); + + result.s.link_up = sgmii_inband_status.s.link; + result.s.full_duplex = sgmii_inband_status.s.dup; + switch (sgmii_inband_status.s.speed) + { + case 0: /* 10 Mbps */ + result.s.speed = 10; + break; + case 1: /* 100 Mbps */ + result.s.speed = 100; + break; + case 2: /* 1 Gbps */ + result.s.speed = 1000; + break; + case 3: /* Illegal */ + result.s.speed = 0; + result.s.link_up = 0; + break; + } + } +#endif else { /* We don't have a PHY address and we don't have in-band status. There @@ -1318,6 +1395,33 @@ int __cvmx_helper_board_interface_probe(int interface, int supported_ports) if (interface == 1) return 12; break; +#endif +#if defined(OCTEON_VENDOR_GEFES) + case CVMX_BOARD_TYPE_CUST_TNPA5651X: + if (interface < 2) /* interface can be EITHER 0 or 1 */ + return 1;//always return 1 for XAUI and SGMII mode. + break; + case CVMX_BOARD_TYPE_CUST_TNPA56X4: + if ((interface == 0) && + (cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_SGMII)) + { + cvmx_pcsx_miscx_ctl_reg_t pcsx_miscx_ctl_reg; + + /* For this port we need to set the mode to 1000BaseX */ + pcsx_miscx_ctl_reg.u64 = + cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(0, interface)); + pcsx_miscx_ctl_reg.cn56xx.mode = 1; + cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(0, interface), + pcsx_miscx_ctl_reg.u64); + pcsx_miscx_ctl_reg.u64 = + cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(1, interface)); + pcsx_miscx_ctl_reg.cn56xx.mode = 1; + cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(1, interface), + pcsx_miscx_ctl_reg.u64); + + return 2; + } + break; #endif } #ifdef CVMX_BUILD_FOR_UBOOT @@ -1481,14 +1585,28 @@ cvmx_helper_board_usb_clock_types_t __cvmx_helper_board_usb_get_clock_type(void) case CVMX_BOARD_TYPE_LANAI2_U: case CVMX_BOARD_TYPE_LANAI2_G: #if defined(OCTEON_VENDOR_LANNER) - case CVMX_BOARD_TYPE_CUST_LANNER_MR320: - case CVMX_BOARD_TYPE_CUST_LANNER_MR321X: + case CVMX_BOARD_TYPE_CUST_LANNER_MR320: + case CVMX_BOARD_TYPE_CUST_LANNER_MR321X: #endif #if defined(OCTEON_VENDOR_UBIQUITI) - case CVMX_BOARD_TYPE_CUST_UBIQUITI_E100: + case CVMX_BOARD_TYPE_CUST_UBIQUITI_E100: #endif #if defined(OCTEON_BOARD_CAPK_0100ND) case CVMX_BOARD_TYPE_CN3010_EVB_HS5: +#endif +#if defined(OCTEON_VENDOR_GEFES) /* All GEFES' boards use same xtal type */ + case CVMX_BOARD_TYPE_TNPA3804: + case CVMX_BOARD_TYPE_AT5810: + case CVMX_BOARD_TYPE_WNPA3850: + case CVMX_BOARD_TYPE_W3860: + case CVMX_BOARD_TYPE_CUST_TNPA5804: + case CVMX_BOARD_TYPE_CUST_W5434: + case CVMX_BOARD_TYPE_CUST_W5650: + case CVMX_BOARD_TYPE_CUST_W5800: + case CVMX_BOARD_TYPE_CUST_W5651X: + case CVMX_BOARD_TYPE_CUST_TNPA5651X: + case CVMX_BOARD_TYPE_CUST_TNPA56X4: + case CVMX_BOARD_TYPE_CUST_W63XX: #endif case CVMX_BOARD_TYPE_NIC10E_66: return USB_CLOCK_TYPE_CRYSTAL_12; diff --git a/sys/contrib/octeon-sdk/cvmx-helper-sgmii.c b/sys/contrib/octeon-sdk/cvmx-helper-sgmii.c index 8699548c576c..6cb0973bd959 100644 --- a/sys/contrib/octeon-sdk/cvmx-helper-sgmii.c +++ b/sys/contrib/octeon-sdk/cvmx-helper-sgmii.c @@ -116,7 +116,13 @@ static int __cvmx_helper_sgmii_hardware_init_one_time(int interface, int index) interval. */ pcsx_miscx_ctl_reg.u64 = cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); pcsx_linkx_timer_count_reg.u64 = cvmx_read_csr(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface)); - if (pcsx_miscx_ctl_reg.s.mode) + if (pcsx_miscx_ctl_reg.s.mode +#if defined(OCTEON_VENDOR_GEFES) + /* GEF Fiber SFP testing on W5650 showed this to cause link issues for 1000BASE-X*/ + && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_CUST_W5650) + && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_CUST_W63XX) +#endif + ) { /* 1000BASE-X */ pcsx_linkx_timer_count_reg.s.count = (10000ull * clock_mhz) >> 10; @@ -200,7 +206,15 @@ static int __cvmx_helper_need_g15618(void) static int __cvmx_helper_sgmii_hardware_init_link(int interface, int index) { cvmx_pcsx_mrx_control_reg_t control_reg; + uint64_t link_timeout; +#if defined(OCTEON_VENDOR_GEFES) + if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_TNPA5651X) { + return 0; /* no auto-negotiation */ + } +#endif + + /* Take PCS through a reset sequence. PCS*_MR*_CONTROL_REG[PWR_DN] should be cleared to zero. Write PCS*_MR*_CONTROL_REG[RESET]=1 (while not changing the value of @@ -211,9 +225,16 @@ static int __cvmx_helper_sgmii_hardware_init_link(int interface, int index) /* Errata G-15618 requires disabling PCS soft reset in CN63XX pass upto 2.1. */ if (!__cvmx_helper_need_g15618()) { + link_timeout = 200000; +#if defined(OCTEON_VENDOR_GEFES) + if( (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_TNPA56X4) && (interface == 0) ) + { + link_timeout = 5000000; + } +#endif control_reg.s.reset = 1; cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface), control_reg.u64); - if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSX_MRX_CONTROL_REG(index, interface), cvmx_pcsx_mrx_control_reg_t, reset, ==, 0, 10000)) + if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSX_MRX_CONTROL_REG(index, interface), cvmx_pcsx_mrx_control_reg_t, reset, ==, 0, link_timeout)) { cvmx_dprintf("SGMII%d: Timeout waiting for port %d to finish reset\n", interface, index); return -1; @@ -256,6 +277,11 @@ static int __cvmx_helper_sgmii_hardware_init_link_speed(int interface, int index cvmx_gmxx_prtx_cfg_t gmxx_prtx_cfg; cvmx_pcsx_miscx_ctl_reg_t pcsx_miscx_ctl_reg; +#if defined(OCTEON_VENDOR_GEFES) + if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_TNPA5651X) + return 0; /* no auto-negotiation */ +#endif + /* Disable GMX before we make any changes. Remember the enable state */ gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); is_enabled = gmxx_prtx_cfg.s.en; @@ -586,8 +612,42 @@ cvmx_helper_link_info_t __cvmx_helper_sgmii_link_get(int ipd_port) pcsx_miscx_ctl_reg.u64 = cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); if (pcsx_miscx_ctl_reg.s.mode) { +#if defined(OCTEON_VENDOR_GEFES) /* 1000BASE-X */ - // FIXME + int interface = cvmx_helper_get_interface_num(ipd_port); + int index = cvmx_helper_get_interface_index_num(ipd_port); + cvmx_pcsx_miscx_ctl_reg_t mode_type; + cvmx_pcsx_anx_results_reg_t inband_status; + cvmx_pcsx_mrx_status_reg_t mrx_status; + cvmx_pcsx_anx_adv_reg_t anxx_adv; + + anxx_adv.u64 = cvmx_read_csr(CVMX_PCSX_ANX_ADV_REG(index, interface)); + mrx_status.u64 = cvmx_read_csr(CVMX_PCSX_MRX_STATUS_REG(index, interface)); + mode_type.u64 = cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); + + /* Read Octeon's inband status */ + inband_status.u64 = cvmx_read_csr(CVMX_PCSX_ANX_RESULTS_REG(index, interface)); + + result.s.link_up = inband_status.s.link_ok;/* this is only accurate for 1000-base x */ + + result.s.full_duplex = inband_status.s.dup; + switch (inband_status.s.spd) + { + case 0: /* 10 Mbps */ + result.s.speed = 10; + break; + case 1: /* 100 Mbps */ + result.s.speed = 100; + break; + case 2: /* 1 Gbps */ + result.s.speed = 1000; + break; + case 3: /* Illegal */ + result.s.speed = 0; + result.s.link_up = 0; + break; + } +#endif /* Actually not 100% this is GEFES specific */ } else { diff --git a/sys/contrib/octeon-sdk/cvmx-mgmt-port.c b/sys/contrib/octeon-sdk/cvmx-mgmt-port.c index d6f6c5d70a9b..759a8ce2152d 100644 --- a/sys/contrib/octeon-sdk/cvmx-mgmt-port.c +++ b/sys/contrib/octeon-sdk/cvmx-mgmt-port.c @@ -116,12 +116,16 @@ CVMX_SHARED cvmx_mgmt_port_state_t *cvmx_mgmt_port_state_ptr = NULL; */ static int __cvmx_mgmt_port_num_ports(void) { +#if defined(OCTEON_VENDOR_GEFES) + return 0; /* none of the GEFES boards have mgmt ports */ +#else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN68XX)) return 1; else if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN6XXX)) return 2; else return 0; +#endif } diff --git a/sys/contrib/octeon-sdk/cvmx-pcie.c b/sys/contrib/octeon-sdk/cvmx-pcie.c index 088efcb9e72c..ff8f51419fde 100644 --- a/sys/contrib/octeon-sdk/cvmx-pcie.c +++ b/sys/contrib/octeon-sdk/cvmx-pcie.c @@ -422,12 +422,12 @@ static int __cvmx_pcie_rc_initialize_link_gen1(int pcie_port) start_cycle = cvmx_get_cycle(); do { - if (cvmx_get_cycle() - start_cycle > 2*cvmx_clock_get_rate(CVMX_CLOCK_CORE)) + if (cvmx_get_cycle() - start_cycle > 100*cvmx_clock_get_rate(CVMX_CLOCK_CORE)) { cvmx_dprintf("PCIe: Port %d link timeout\n", pcie_port); return -1; } - cvmx_wait(10000); + cvmx_wait(50000); pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); } while (pciercx_cfg032.s.dlla == 0); @@ -518,6 +518,41 @@ static int __cvmx_pcie_rc_initialize_gen1(int pcie_port) return -1; } +#if defined(CONFIG_GEFES_SUPPORT) /* Commented out for now */ + /* check if we should initialize this port */ + if ((cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_TNPA56X4) || + (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_TNPA5651X)) { + unsigned char fpga_ekeylanes0 = 0; + unsigned char fpga_ekeylanes1 = 0; + + cvmx_get_mmc_ekeying(&fpga_ekeylanes0, &fpga_ekeylanes1); + /* For pcie_port 0 - QLM0 (& optionally QLM1) + x4 PCIe AMC ports 4-7 via QLM0 + x8 PCIe AMC ports 4-7 via QLM0 and AMC ports 8-11 via QLM1 + root complex or end point configuration + must be root complex via "if (npei_ctl_status.s.host_mode) {" + */ + + if ((pcie_port == 0) && (fpga_ekeylanes1 == 0)) { + return -1; + } + + /* For pcie_port 1 - QLM2 in RC only connected to 82571 ethernet */ + /* always enabled, don't check ekeying lanes */ + } + else /* all other GEFES boards(maybe just WANIC?)*/ + { + cvmx_npei_ctl_status_t npei_ctl_status; + + npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); + if ( (pcie_port == 1) && (!npei_ctl_status.s.host_mode) ) + { + cvmx_dprintf("PCIe: Port 1 not used (RC only), skipping.\\n"); + return -1; + } + } +#endif /* CONFIG_GEFES_SUPPORT */ + /* 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 */ @@ -988,6 +1023,27 @@ static int __cvmx_pcie_rc_initialize_gen2(int pcie_port) return -1; } +#ifdef CONFIG_GEFES_SUPPORT /* commented out for now */ + /* check if we should initialize this port */ + if ((cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_TNPA56X4) || + (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_TNPA5651X)) { + unsigned char fpga_ekeylanes0; + unsigned char fpga_ekeylanes1; + + cvmx_get_mmc_ekeying(&fpga_ekeylanes0, &fpga_ekeylanes1); + /* For pcie_port 0 - QLM0 (& optionally QLM1) + x4 PCIe AMC ports 4-7 via QLM0 + x8 PCIe AMC ports 4-7 via QLM0 and AMC ports 8-11 via QLM1 + root complex or end point configuration + must be endpoint via "if (npei_ctl_status.s.host_mode) {" + */ + if (( pcie_port == 0) && (fpga_ekeylanes1 == 0)) { + return -1; + } + /* can't get here for pcie_port 1 as is always only root complex configured */ + } +#endif /* CONFIG_GEFES_SUPPORT */ + /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be programmed */ if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0)) { @@ -1340,7 +1396,46 @@ uint16_t cvmx_pcie_config_read16(int pcie_port, int bus, int dev, int fn, int re */ uint32_t cvmx_pcie_config_read32(int pcie_port, int bus, int dev, int fn, int reg) { - uint64_t address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); + uint64_t address; + +#ifdef CONFIG_GEFES_SUPPORT /* Commented out for now */ + + int result; + + /* if U-boot initializes the PCIe ports, then to Linux + it looks as if the ports are up, when in fact, the + port 0 link could be down because there is no endpoint + configured card present. If that is the case, U-boot + would not have configured the access to the PCIe config + space for that port and Linux would crash when it tries + to access that memory space. This code checks to see + if root complex mode is configured, and if it is, if + the link is up for the port before trying to access + the config space. + */ + + /* root complex ? */ + result = cvmx_pcie_dogetinfo(pcie_port, 2); + if (result == 1) { + //cvmx_dprintf("cvmx_pcie_config_read32: pcie_port %d in root complex mode\n", pcie_port); + } else { + //cvmx_dprintf("cvmx_pcie_config_read32: pcie_port %d in end point mode\n", pcie_port); + } + + if (result == 1) { + /* link up? */ + result = cvmx_pcie_dogetinfo(pcie_port, 0); + + if (result == 1) { + //cvmx_dprintf("cvmx_pcie_config_read32: pcie_port %d link UP\n", pcie_port); + } else { + cvmx_dprintf("cvmx_pcie_config_read32: pcie_port %d link DOWN\n", pcie_port); + return 0xffffffff; + } + } +#endif /* CONFIG_GEFES_SUPPORT */ + + address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); if (address) return cvmx_le32_to_cpu(cvmx_read64_uint32(address)); else @@ -1698,3 +1793,135 @@ void cvmx_pcie_wait_for_pending(int pcie_port) } } } + +#ifdef CONFIG_GEFES_SUPPORT +/* eastestdebug - add ekeying from MMC routine */ +/* support routine for CVMX_BOARD_TYPE_TNPA56X4 ekeying */ +void cvmx_get_mmc_ekeying(unsigned char *fpga_ekeylanes0, unsigned char *fpga_ekeylanes1) +{ + switch (cvmx_sysinfo_get()->board_type) { + case CVMX_BOARD_TYPE_TNPA56X4: + case CVMX_BOARD_TYPE_TNPA5651X: + /*TODO: need to check AMC shelf response for 4-7 and 8-11*/ + /*TODO: get rid of magic numbers for FPGA access*/ + /* IPMI define = BOARD_FPGA_DPRAM_PORT_EN_0 */ + /* base ports 0 & 1, fabric xaui 4-7 */ + *fpga_ekeylanes0 = *(char*)0x8000000016000080; + /* IPMI define = BOARD_FPGA_DPRAM_PORT_EN_1 */ + /* fabric pcie 4-7, fabric pcie 8-11 */ + *fpga_ekeylanes1 = *(char*)0x8000000016000082; + default: + /* TBD for other board types */ + break; + } +} + +/* eastestdebug - add cvmx_pcie_getinfo for PCIe /proc/ data */ +/** + * Get desired info for a PCIe port on our Octeon. + * Note not possible to have multiple devObj from caller. + * + * @param pcie_port PCIe port to get info for + * + * @return uint8_t value for desired info + */ +int cvmx_pcie_dogetinfo(int pcie_port, int infotype) +{ +cvmx_pciercx_cfg032_t pciercx_cfg032; +cvmx_npei_ctl_status_t npei_ctl_status; +unsigned char fpga_ekeylanes0 = 0; +unsigned char fpga_ekeylanes1 = 0; +uint64_t start_cycle; + + switch (cvmx_sysinfo_get()->board_type) { + case CVMX_BOARD_TYPE_TNPA56X4: + case CVMX_BOARD_TYPE_TNPA5651X: + switch (infotype) { + case 0: /* link up (1) /down (0) */ +#if 0 + pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); + if (pciercx_cfg032.s.nlw) { + /* link up */ + return(1); + } + return(0); +#endif + /* Wait for the link to come up */ + //cvmx_dprintf("PCIe: Waiting for port %d link\n", pcie_port); + start_cycle = cvmx_get_cycle(); + pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); + while (pciercx_cfg032.s.dlla == 0) { + /* if (cvmx_get_cycle() - start_cycle > 2*cvmx_sysinfo_get()->cpu_clock_hz) */ + if (cvmx_get_cycle() - start_cycle > 100 * cvmx_sysinfo_get()->cpu_clock_hz) + { + cvmx_dprintf("PCIe: Port %d link timeout\n", pcie_port); + return 0; + } + /* cvmx_wait(10000); */ + cvmx_wait(50000); + pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); + } + + /* Display the link status */ + //cvmx_dprintf("PCIe: Port %d link active, %d lanes\n", pcie_port, pciercx_cfg032.s.nlw); + return(1); + + case 1: /* link valid (1) / disabled (0) */ + /* CVMX_BOARD_TYPE_TNPA56X4 specific */ + if (pcie_port == 1) { + /* port 1 - QLM2 RC x4 always enabled */ + return (1); + } + cvmx_get_mmc_ekeying(&fpga_ekeylanes0, &fpga_ekeylanes1); + if (fpga_ekeylanes1) { + /* ekeying on for something - i.e. valid */ + return(1); + } + return(0); + case 2: /* link type root complex (1) /end point (0) */ + if (pcie_port == 1) { + /* port 1 - QLM2 RC x4 always enabled */ + return (1); + } + /* check if port 0 host (rc) or endpoint */ + npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); + if (npei_ctl_status.s.host_mode) { + return(1); + } + return(0); + case 3: /* desired link size x8 (8) /x4 (4) */ + cvmx_get_mmc_ekeying(&fpga_ekeylanes0, &fpga_ekeylanes1); + if (fpga_ekeylanes1 & 0xf0) { + return (8); /* x8 */ + } else if (fpga_ekeylanes1 & 0x0f) { + return (4); /* x4 */ + } + break; /* disabled */ + case 4: /* actual configured link size x32 (32)/ x16 (16) /x8 (8) /x4 (4) /x2 (2) x1 (1) */ + pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); + switch (pciercx_cfg032.s.nlw) { + case 1: /* 1 lane */ + return(1); + case 2: /* 2 lanes */ + return(2); + case 4: /* 4 lanes */ + return(4); + case 8: /* 8 lanes */ + return(8); + default: + break; + } + /* unknown, return x4 */ + return(4); + default: + /* TBD for other info types */ + return 0; + } + break; + default: + /* TBD for other board types */ + break; + } + return 0; +} +#endif /* CONFIG_GEFES_SUPPORT */