diff options
-rw-r--r-- | arch/powerpc/cpu/mpc85xx/cmd_errata.c | 4 | ||||
-rw-r--r-- | board/freescale/b4860qds/b4860qds.c | 13 | ||||
-rw-r--r-- | board/freescale/common/vsc3316_3308.c | 108 | ||||
-rw-r--r-- | board/freescale/common/vsc3316_3308.h | 4 | ||||
-rw-r--r-- | include/configs/B4860QDS.h | 2 |
5 files changed, 131 insertions, 0 deletions
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c index ec75383..2d5ddf0 100644 --- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c +++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c @@ -319,6 +319,10 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (IS_SVR_REV(svr, 1, 0)) puts("Work-around for Erratum A-008044 enabled\n"); #endif +#if defined(CONFIG_SYS_FSL_B4860QDS_XFI_ERR) && defined(CONFIG_B4860QDS) + puts("Work-around for Erratum XFI on B4860QDS enabled\n"); +#endif + return 0; } diff --git a/board/freescale/b4860qds/b4860qds.c b/board/freescale/b4860qds/b4860qds.c index c99c266..6a8fca6 100644 --- a/board/freescale/b4860qds/b4860qds.c +++ b/board/freescale/b4860qds/b4860qds.c @@ -548,6 +548,18 @@ int configure_vsc3316_3308(void) if (hwconfig_subarg_cmp_f("fsl_b4860_serdes2", "sfp_amc", "sfp", buf)) { +#ifdef CONFIG_SYS_FSL_B4860QDS_XFI_ERR + /* change default VSC3308 for XFI erratum */ + ret = vsc3308_config_adjust(VSC3308_TX_ADDRESS, + vsc08_tx_sfp, num_vsc08_con); + if (ret) + return ret; + + ret = vsc3308_config_adjust(VSC3308_RX_ADDRESS, + vsc08_rx_sfp, num_vsc08_con); + if (ret) + return ret; +#else ret = vsc3308_config(VSC3308_TX_ADDRESS, vsc08_tx_sfp, num_vsc08_con); if (ret) @@ -557,6 +569,7 @@ int configure_vsc3316_3308(void) vsc08_rx_sfp, num_vsc08_con); if (ret) return ret; +#endif } else { ret = vsc3308_config(VSC3308_TX_ADDRESS, vsc08_tx_amc, num_vsc08_con); diff --git a/board/freescale/common/vsc3316_3308.c b/board/freescale/common/vsc3316_3308.c index 97a25e8..dd9c37e 100644 --- a/board/freescale/common/vsc3316_3308.c +++ b/board/freescale/common/vsc3316_3308.c @@ -13,7 +13,12 @@ #define INPUT_STATE_REG 0x13 #define GLOBAL_INPUT_ISE1 0x51 #define GLOBAL_INPUT_ISE2 0x52 +#define GLOBAL_INPUT_GAIN 0x53 #define GLOBAL_INPUT_LOS 0x55 +#define GLOBAL_OUTPUT_PE1 0x56 +#define GLOBAL_OUTPUT_PE2 0x57 +#define GLOBAL_OUTPUT_LEVEL 0x58 +#define GLOBAL_OUTPUT_TERMINATION 0x5A #define GLOBAL_CORE_CNTRL 0x5D #define OUTPUT_MODE_PAGE 0x23 #define CORE_CONTROL_PAGE 0x25 @@ -92,6 +97,109 @@ int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2], return 0; } +#ifdef CONFIG_SYS_FSL_B4860QDS_XFI_ERR +int vsc3308_config_adjust(unsigned int vsc_addr, const int8_t con_arr[][2], + unsigned int num_con) +{ + unsigned int i; + u8 rev_id = 0; + int ret; + + debug("VSC:Initializing VSC3308 at I2C address 0x%x for Tx\n", + vsc_addr); + + ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1); + if (ret < 0) { + printf("VSC:0x%x could not read REV_ID from device.\n", + vsc_addr); + return ret; + } + + if (rev_id != 0xab) { + printf("VSC: device at address 0x%x is not VSC3316/3308.\n", + vsc_addr); + return -ENODEV; + } + + ret = vsc_if_enable(vsc_addr); + if (ret) { + printf("VSC:0x%x could not configured for 2-wire I/F.\n", + vsc_addr); + return ret; + } + + /* config connections - page 0x00 */ + i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE); + + /* Configure Global Input ISE */ + i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0); + i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0); + + /* Configure Tx/Rx Global Output PE1 */ + i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE1, 0); + + /* Configure Tx/Rx Global Output PE2 */ + i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE2, 0); + + /* Configure Tx/Rx Global Input GAIN */ + i2c_reg_write(vsc_addr, GLOBAL_INPUT_GAIN, 0x3F); + + /* Setting Global Input LOS threshold value */ + i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0xE0); + + /* Setting Global output termination */ + i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_TERMINATION, 0); + + /* Configure Tx/Rx Global Output level */ + if (vsc_addr == VSC3308_TX_ADDRESS) + i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 4); + else + i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 2); + + /* Making crosspoint connections, by connecting required + * input to output */ + for (i = 0; i < num_con ; i++) + i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]); + + /* input state - page 0x13 */ + i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG); + /* Turning off all the required input of the switch */ + for (i = 0; i < num_con; i++) + i2c_reg_write(vsc_addr, con_arr[i][0], 1); + + /* only turn on specific Tx/Rx requested by the XFI erratum */ + if (vsc_addr == VSC3308_TX_ADDRESS) { + i2c_reg_write(vsc_addr, 2, 0); + i2c_reg_write(vsc_addr, 3, 0); + } else { + i2c_reg_write(vsc_addr, 0, 0); + i2c_reg_write(vsc_addr, 1, 0); + } + + /* config output mode - page 0x23 */ + i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE); + /* Turn off the Output driver correspond to required output*/ + for (i = 0; i < num_con ; i++) + i2c_reg_write(vsc_addr, con_arr[i][1], 1); + + /* only turn on specific Tx/Rx requested by the XFI erratum */ + if (vsc_addr == VSC3308_TX_ADDRESS) { + i2c_reg_write(vsc_addr, 0, 0); + i2c_reg_write(vsc_addr, 1, 0); + } else { + i2c_reg_write(vsc_addr, 3, 0); + i2c_reg_write(vsc_addr, 4, 0); + } + + /* configure global core control register, Turn on Global core power */ + i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0); + + vsc_wp_config(vsc_addr); + + return 0; +} +#endif + int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2], unsigned int num_con) { diff --git a/board/freescale/common/vsc3316_3308.h b/board/freescale/common/vsc3316_3308.h index 2a49187..d722ea3 100644 --- a/board/freescale/common/vsc3316_3308.h +++ b/board/freescale/common/vsc3316_3308.h @@ -14,6 +14,10 @@ int vsc_if_enable(unsigned int vsc_addr); int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2], unsigned int num_con); +#ifdef CONFIG_SYS_FSL_B4860QDS_XFI_ERR +int vsc3308_config_adjust(unsigned int vsc_addr, const int8_t con_arr[][2], + unsigned int num_con); +#endif int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2], unsigned int num_con); void vsc_wp_config(unsigned int vsc_addr); diff --git a/include/configs/B4860QDS.h b/include/configs/B4860QDS.h index b47b9de..9e8e319 100644 --- a/include/configs/B4860QDS.h +++ b/include/configs/B4860QDS.h @@ -731,6 +731,8 @@ unsigned long get_board_ddr_clk(void); #define CONFIG_PHY_GIGE /* Include GbE speed/duplex detection */ #endif +#define CONFIG_SYS_FSL_B4860QDS_XFI_ERR + /* * Environment */ |