diff options
author | imp <imp@FreeBSD.org> | 2013-05-10 03:04:45 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2013-05-10 03:04:45 +0000 |
commit | 6803113acbb3347f4c4b0678996f8465413d9bcd (patch) | |
tree | 835edb4d8e9ab889e0df78ef38febbcdf8b62614 | |
parent | c5e619b651d1ca95e1c461c940ab382e1b3a019e (diff) | |
download | FreeBSD-src-6803113acbb3347f4c4b0678996f8465413d9bcd.zip FreeBSD-src-6803113acbb3347f4c4b0678996f8465413d9bcd.tar.gz |
Add support from GE Intelligent Platform Cavium Octeon boards. Add
options OCTEON_VENDOR_GEFES to enable support for these boards, to
match changes that GE publishes to the Octeon Simple Executive. Since
board types overlap with other boards, it is unlikely that we will
properly boot on other Octeon boards with OCTEON_VENDOR_GEFES enabled.
Tested extensively on the WANIC 6354, but I retained support for all
the other models. Some features need changes in the base kernel, and
those are in progress.
-rw-r--r-- | sys/contrib/octeon-sdk/cvmx-app-init.h | 38 | ||||
-rw-r--r-- | sys/contrib/octeon-sdk/cvmx-helper-board.c | 128 | ||||
-rw-r--r-- | sys/contrib/octeon-sdk/cvmx-helper-sgmii.c | 66 | ||||
-rw-r--r-- | sys/contrib/octeon-sdk/cvmx-mgmt-port.c | 4 | ||||
-rw-r--r-- | sys/contrib/octeon-sdk/cvmx-pcie.c | 233 |
5 files changed, 457 insertions, 12 deletions
diff --git a/sys/contrib/octeon-sdk/cvmx-app-init.h b/sys/contrib/octeon-sdk/cvmx-app-init.h index 605f43e..beab38e 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, @@ -305,6 +315,16 @@ enum cvmx_board_types_enum { #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 */ @@ -435,6 +461,16 @@ static inline const char *cvmx_board_type_to_string(enum cvmx_board_types_enum t #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) /* Module range */ diff --git a/sys/contrib/octeon-sdk/cvmx-helper-board.c b/sys/contrib/octeon-sdk/cvmx-helper-board.c index d97813e..49e52d4 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) @@ -603,6 +607,30 @@ int cvmx_helper_board_get_mii_address(int ipd_port) /* 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 } /* Some unknown board. Somebody forgot to update this function... */ @@ -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) { @@ -1077,6 +1107,15 @@ cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) } 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 @@ -1319,6 +1396,33 @@ int __cvmx_helper_board_interface_probe(int interface, int supported_ports) 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 if (CVMX_HELPER_INTERFACE_MODE_SPI == cvmx_helper_interface_get_mode(interface) && getenv("disable_spi")) @@ -1481,15 +1585,29 @@ 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; case CVMX_BOARD_TYPE_NIC10E: diff --git a/sys/contrib/octeon-sdk/cvmx-helper-sgmii.c b/sys/contrib/octeon-sdk/cvmx-helper-sgmii.c index 8699548..6cb0973 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 d6f6c5d..759a8ce 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 088efcb..ff8f514 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 @@ retry: 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 */ |