powerpc/b4860qds: add workaround for XFI
authorShaohui Xie <Shaohui.Xie@freescale.com>
Thu, 13 Nov 2014 03:27:49 +0000 (11:27 +0800)
committerYork Sun <yorksun@freescale.com>
Fri, 5 Dec 2014 16:06:13 +0000 (08:06 -0800)
XFI does not work stable on current board, it's due to heat sink issue,
to make it work stable the board needs additional heat sink, enable two
XFI lanes only. Right now we do not have such an erratum for the issue,
so use a define CONFIG_SYS_FSL_B4860QDS_XFI_ERR to identify it.
The workaround will only be used in XFI protocols and only if the
hwconfig indicates that XFI is prefered.

A new VSC3308 config function is used instead of re-use the original
function, to avoid making the function complex and ugly.

Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com>
Reviewed-by: York Sun <yorksun@freescale.com>
arch/powerpc/cpu/mpc85xx/cmd_errata.c
board/freescale/b4860qds/b4860qds.c
board/freescale/common/vsc3316_3308.c
board/freescale/common/vsc3316_3308.h
include/configs/B4860QDS.h

index ec75383dea69008890132e5258cdc5abdde69e41..2d5ddf012b6b3a27c370e0bc3c65ad94c87e77d0 100644 (file)
@@ -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;
 }
 
index c99c26680e323df4a9e797b2060666fb587019e6..6a8fca61a0d451b6c407c87a3397bde2f1557eaa 100644 (file)
@@ -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);
index 97a25e838ed414080c7140baba7e6e4ebcf63b0d..dd9c37ebe8faf938b3a8244cb1fe7a1ac3b0ecc6 100644 (file)
 #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)
 {
index 2a491877792fdeef574a66929da6f692f9cccb7c..d722ea39d68e0eddae75770fa75652fff7e1f0e3 100644 (file)
 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);
index b47b9decaacafa64bf470423cdfa359aa2c417cc..9e8e319cf703a6b476f6c99021d49adbe2ba1529 100644 (file)
@@ -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
  */