X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=board%2Ffreescale%2Fb4860qds%2Fb4860qds.c;h=b2d53781438d35a296990068e90085bf27ef8ce2;hb=557a3319089499aa0e55d65a6b43b7137f362003;hp=f6b012dbbc6370c718dbac9cf2d8dae2fef1d98a;hpb=935b402eaec0f78ffdafd614aa8176a777d8b6d9;p=u-boot diff --git a/board/freescale/b4860qds/b4860qds.c b/board/freescale/b4860qds/b4860qds.c index f6b012dbbc..b2d5378143 100644 --- a/board/freescale/b4860qds/b4860qds.c +++ b/board/freescale/b4860qds/b4860qds.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -22,13 +23,13 @@ #include "../common/qixis.h" #include "../common/vsc3316_3308.h" #include "../common/idt8t49n222a_serdes_clk.h" +#include "../common/zm7300.h" #include "b4860qds.h" #include "b4860qds_qixis.h" #include "b4860qds_crossbar_con.h" #define CLK_MUX_SEL_MASK 0x4 #define ETH_PHY_CLK_OUT 0x4 -#define PLL_NUM 2 DECLARE_GLOBAL_DATA_PTR; @@ -94,6 +95,238 @@ int select_i2c_ch_pca(u8 ch) return 0; } +/* + * read_voltage from sensor on I2C bus + * We use average of 4 readings, waiting for 532us befor another reading + */ +#define WAIT_FOR_ADC 532 /* wait for 532 microseconds for ADC */ +#define NUM_READINGS 4 /* prefer to be power of 2 for efficiency */ + +static inline int read_voltage(void) +{ + int i, ret, voltage_read = 0; + u16 vol_mon; + + for (i = 0; i < NUM_READINGS; i++) { + ret = i2c_read(I2C_VOL_MONITOR_ADDR, + I2C_VOL_MONITOR_BUS_V_OFFSET, 1, (void *)&vol_mon, 2); + if (ret) { + printf("VID: failed to read core voltage\n"); + return ret; + } + if (vol_mon & I2C_VOL_MONITOR_BUS_V_OVF) { + printf("VID: Core voltage sensor error\n"); + return -1; + } + debug("VID: bus voltage reads 0x%04x\n", vol_mon); + /* LSB = 4mv */ + voltage_read += (vol_mon >> I2C_VOL_MONITOR_BUS_V_SHIFT) * 4; + udelay(WAIT_FOR_ADC); + } + /* calculate the average */ + voltage_read /= NUM_READINGS; + + return voltage_read; +} + +static int adjust_vdd(ulong vdd_override) +{ + int re_enable = disable_interrupts(); + ccsr_gur_t __iomem *gur = + (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + u32 fusesr; + u8 vid; + int vdd_target, vdd_last; + int existing_voltage, temp_voltage, voltage; /* all in 1/10 mV */ + int ret; + unsigned int orig_i2c_speed; + unsigned long vdd_string_override; + char *vdd_string; + static const uint16_t vdd[32] = { + 0, /* unused */ + 9875, /* 0.9875V */ + 9750, + 9625, + 9500, + 9375, + 9250, + 9125, + 9000, + 8875, + 8750, + 8625, + 8500, + 8375, + 8250, + 8125, + 10000, /* 1.0000V */ + 10125, + 10250, + 10375, + 10500, + 10625, + 10750, + 10875, + 11000, + 0, /* reserved */ + }; + struct vdd_drive { + u8 vid; + unsigned voltage; + }; + + ret = select_i2c_ch_pca(I2C_MUX_CH_VOL_MONITOR); + if (ret) { + printf("VID: I2c failed to switch channel\n"); + ret = -1; + goto exit; + } + + /* get the voltage ID from fuse status register */ + fusesr = in_be32(&gur->dcfg_fusesr); + vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_VID_SHIFT) & + FSL_CORENET_DCFG_FUSESR_VID_MASK; + if (vid == FSL_CORENET_DCFG_FUSESR_VID_MASK) { + vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) & + FSL_CORENET_DCFG_FUSESR_ALTVID_MASK; + } + vdd_target = vdd[vid]; + debug("VID:Reading from from fuse,vid=%x vdd is %dmV\n", + vid, vdd_target/10); + + /* check override variable for overriding VDD */ + vdd_string = getenv("b4qds_vdd_mv"); + if (vdd_override == 0 && vdd_string && + !strict_strtoul(vdd_string, 10, &vdd_string_override)) + vdd_override = vdd_string_override; + if (vdd_override >= 819 && vdd_override <= 1212) { + vdd_target = vdd_override * 10; /* convert to 1/10 mV */ + debug("VDD override is %lu\n", vdd_override); + } else if (vdd_override != 0) { + printf("Invalid value.\n"); + } + + if (vdd_target == 0) { + printf("VID: VID not used\n"); + ret = 0; + goto exit; + } + + /* + * Read voltage monitor to check real voltage. + * Voltage monitor LSB is 4mv. + */ + vdd_last = read_voltage(); + if (vdd_last < 0) { + printf("VID: abort VID adjustment\n"); + ret = -1; + goto exit; + } + + debug("VID: Core voltage is at %d mV\n", vdd_last); + ret = select_i2c_ch_pca(I2C_MUX_CH_DPM); + if (ret) { + printf("VID: I2c failed to switch channel to DPM\n"); + ret = -1; + goto exit; + } + + /* Round up to the value of step of Voltage regulator */ + voltage = roundup(vdd_target, ZM_STEP); + debug("VID: rounded up voltage = %d\n", voltage); + + /* lower the speed to 100kHz to access ZM7300 device */ + debug("VID: Setting bus speed to 100KHz if not already set\n"); + orig_i2c_speed = i2c_get_bus_speed(); + if (orig_i2c_speed != 100000) + i2c_set_bus_speed(100000); + + /* Read the existing level on board, if equal to requsted one, + no need to re-set */ + existing_voltage = zm_read_voltage(); + + /* allowing the voltage difference of one step 0.0125V acceptable */ + if ((existing_voltage >= voltage) && + (existing_voltage < (voltage + ZM_STEP))) { + debug("VID: voltage already set as requested,returning\n"); + ret = existing_voltage; + goto out; + } + debug("VID: Changing voltage for board from %dmV to %dmV\n", + existing_voltage/10, voltage/10); + + if (zm_disable_wp() < 0) { + ret = -1; + goto out; + } + /* Change Voltage: the change is done through all the steps in the + way, to avoid reset to the board due to power good signal fail + in big voltage change gap jump. + */ + if (existing_voltage > voltage) { + temp_voltage = existing_voltage - ZM_STEP; + while (temp_voltage >= voltage) { + ret = zm_write_voltage(temp_voltage); + if (ret == temp_voltage) { + temp_voltage -= ZM_STEP; + } else { + /* ZM7300 device failed to set + * the voltage */ + printf + ("VID:Stepping down vol failed:%dmV\n", + temp_voltage/10); + ret = -1; + goto out; + } + } + } else { + temp_voltage = existing_voltage + ZM_STEP; + while (temp_voltage < (voltage + ZM_STEP)) { + ret = zm_write_voltage(temp_voltage); + if (ret == temp_voltage) { + temp_voltage += ZM_STEP; + } else { + /* ZM7300 device failed to set + * the voltage */ + printf + ("VID:Stepping up vol failed:%dmV\n", + temp_voltage/10); + ret = -1; + goto out; + } + } + } + + if (zm_enable_wp() < 0) + ret = -1; + + /* restore the speed to 400kHz */ +out: debug("VID: Restore the I2C bus speed to %dKHz\n", + orig_i2c_speed/1000); + i2c_set_bus_speed(orig_i2c_speed); + if (ret < 0) + goto exit; + + ret = select_i2c_ch_pca(I2C_MUX_CH_VOL_MONITOR); + if (ret) { + printf("VID: I2c failed to switch channel\n"); + ret = -1; + goto exit; + } + vdd_last = read_voltage(); + select_i2c_ch_pca(I2C_CH_DEFAULT); + + if (vdd_last > 0) + printf("VID: Core voltage %d mV\n", vdd_last); + else + ret = -1; + +exit: + if (re_enable) + enable_interrupts(); + return ret; +} + int configure_vsc3316_3308(void) { ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); @@ -120,6 +353,7 @@ int configure_vsc3316_3308(void) debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl); switch (serdes1_prtcl) { + case 0x29: case 0x2a: case 0x2C: case 0x2D: @@ -151,7 +385,55 @@ int configure_vsc3316_3308(void) } break; + case 0x02: + case 0x04: + case 0x05: + case 0x06: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x30: + case 0x32: + case 0x33: + case 0x34: + case 0x39: + case 0x3A: + case 0x3C: + case 0x3D: + case 0x5C: + case 0x5D: + /* + * Configuration: + * SERDES: 1 + * Lanes: A,B: AURORA + * Lanes: C,d: SGMII + * Lanes: E,F,G,H: CPRI + */ + debug("Configuring crossbar for Aurora, SGMII 3 and 4," + " and CPRI. srds_prctl:%x\n", serdes1_prtcl); + num_vsc16_con = NUM_CON_VSC3316; + /* Configure VSC3316 crossbar switch */ + ret = select_i2c_ch_pca(I2C_CH_VSC3316); + if (!ret) { + ret = vsc3316_config(VSC3316_TX_ADDRESS, + vsc16_tx_sfp_sgmii_aurora, + num_vsc16_con); + if (ret) + return ret; + ret = vsc3316_config(VSC3316_RX_ADDRESS, + vsc16_rx_sfp_sgmii_aurora, + num_vsc16_con); + if (ret) + return ret; + } else { + return ret; + } + break; + #ifdef CONFIG_PPC_B4420 + case 0x17: case 0x18: /* * Configuration: @@ -239,14 +521,191 @@ int configure_vsc3316_3308(void) return 0; } +static int calibrate_pll(serdes_corenet_t *srds_regs, int pll_num) +{ + u32 rst_err; + + /* Steps For SerDes PLLs reset and reconfiguration + * or PLL power-up procedure + */ + debug("CALIBRATE PLL:%d\n", pll_num); + clrbits_be32(&srds_regs->bank[pll_num].rstctl, + SRDS_RSTCTL_SDRST_B); + udelay(10); + clrbits_be32(&srds_regs->bank[pll_num].rstctl, + (SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B)); + udelay(10); + setbits_be32(&srds_regs->bank[pll_num].rstctl, + SRDS_RSTCTL_RST); + setbits_be32(&srds_regs->bank[pll_num].rstctl, + (SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B + | SRDS_RSTCTL_SDRST_B)); + + udelay(20); + + /* Check whether PLL has been locked or not */ + rst_err = in_be32(&srds_regs->bank[pll_num].rstctl) & + SRDS_RSTCTL_RSTERR; + rst_err >>= SRDS_RSTCTL_RSTERR_SHIFT; + debug("RST_ERR value for PLL %d is: 0x%x:\n", pll_num, rst_err); + if (rst_err) + return rst_err; + + return rst_err; +} + +static int check_pll_locks(serdes_corenet_t *srds_regs, int pll_num) +{ + int ret = 0; + u32 fcap, dcbias, bcap, pllcr1, pllcr0; + + if (calibrate_pll(srds_regs, pll_num)) { + /* STEP 1 */ + /* Read fcap, dcbias and bcap value */ + clrbits_be32(&srds_regs->bank[pll_num].pllcr0, + SRDS_PLLCR0_DCBIAS_OUT_EN); + fcap = in_be32(&srds_regs->bank[pll_num].pllsr2) & + SRDS_PLLSR2_FCAP; + fcap >>= SRDS_PLLSR2_FCAP_SHIFT; + bcap = in_be32(&srds_regs->bank[pll_num].pllsr2) & + SRDS_PLLSR2_BCAP_EN; + bcap >>= SRDS_PLLSR2_BCAP_EN_SHIFT; + setbits_be32(&srds_regs->bank[pll_num].pllcr0, + SRDS_PLLCR0_DCBIAS_OUT_EN); + dcbias = in_be32(&srds_regs->bank[pll_num].pllsr2) & + SRDS_PLLSR2_DCBIAS; + dcbias >>= SRDS_PLLSR2_DCBIAS_SHIFT; + debug("values of bcap:%x, fcap:%x and dcbias:%x\n", + bcap, fcap, dcbias); + if (fcap == 0 && bcap == 1) { + /* Step 3 */ + clrbits_be32(&srds_regs->bank[pll_num].rstctl, + (SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B + | SRDS_RSTCTL_SDRST_B)); + clrbits_be32(&srds_regs->bank[pll_num].pllcr1, + SRDS_PLLCR1_BCAP_EN); + setbits_be32(&srds_regs->bank[pll_num].pllcr1, + SRDS_PLLCR1_BCAP_OVD); + if (calibrate_pll(srds_regs, pll_num)) { + /*save the fcap, dcbias and bcap values*/ + clrbits_be32(&srds_regs->bank[pll_num].pllcr0, + SRDS_PLLCR0_DCBIAS_OUT_EN); + fcap = in_be32(&srds_regs->bank[pll_num].pllsr2) + & SRDS_PLLSR2_FCAP; + fcap >>= SRDS_PLLSR2_FCAP_SHIFT; + bcap = in_be32(&srds_regs->bank[pll_num].pllsr2) + & SRDS_PLLSR2_BCAP_EN; + bcap >>= SRDS_PLLSR2_BCAP_EN_SHIFT; + setbits_be32(&srds_regs->bank[pll_num].pllcr0, + SRDS_PLLCR0_DCBIAS_OUT_EN); + dcbias = in_be32 + (&srds_regs->bank[pll_num].pllsr2) & + SRDS_PLLSR2_DCBIAS; + dcbias >>= SRDS_PLLSR2_DCBIAS_SHIFT; + + /* Step 4*/ + clrbits_be32(&srds_regs->bank[pll_num].rstctl, + (SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B + | SRDS_RSTCTL_SDRST_B)); + setbits_be32(&srds_regs->bank[pll_num].pllcr1, + SRDS_PLLCR1_BYP_CAL); + clrbits_be32(&srds_regs->bank[pll_num].pllcr1, + SRDS_PLLCR1_BCAP_EN); + setbits_be32(&srds_regs->bank[pll_num].pllcr1, + SRDS_PLLCR1_BCAP_OVD); + /* change the fcap and dcbias to the saved + * values from Step 3 */ + clrbits_be32(&srds_regs->bank[pll_num].pllcr1, + SRDS_PLLCR1_PLL_FCAP); + pllcr1 = (in_be32 + (&srds_regs->bank[pll_num].pllcr1)| + (fcap << SRDS_PLLCR1_PLL_FCAP_SHIFT)); + out_be32(&srds_regs->bank[pll_num].pllcr1, + pllcr1); + clrbits_be32(&srds_regs->bank[pll_num].pllcr0, + SRDS_PLLCR0_DCBIAS_OVRD); + pllcr0 = (in_be32 + (&srds_regs->bank[pll_num].pllcr0)| + (dcbias << SRDS_PLLCR0_DCBIAS_OVRD_SHIFT)); + out_be32(&srds_regs->bank[pll_num].pllcr0, + pllcr0); + ret = calibrate_pll(srds_regs, pll_num); + if (ret) + return ret; + } else { + goto out; + } + } else { /* Step 5 */ + clrbits_be32(&srds_regs->bank[pll_num].rstctl, + (SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B + | SRDS_RSTCTL_SDRST_B)); + udelay(10); + /* Change the fcap, dcbias, and bcap to the + * values from Step 1 */ + setbits_be32(&srds_regs->bank[pll_num].pllcr1, + SRDS_PLLCR1_BYP_CAL); + clrbits_be32(&srds_regs->bank[pll_num].pllcr1, + SRDS_PLLCR1_PLL_FCAP); + pllcr1 = (in_be32(&srds_regs->bank[pll_num].pllcr1)| + (fcap << SRDS_PLLCR1_PLL_FCAP_SHIFT)); + out_be32(&srds_regs->bank[pll_num].pllcr1, + pllcr1); + clrbits_be32(&srds_regs->bank[pll_num].pllcr0, + SRDS_PLLCR0_DCBIAS_OVRD); + pllcr0 = (in_be32(&srds_regs->bank[pll_num].pllcr0)| + (dcbias << SRDS_PLLCR0_DCBIAS_OVRD_SHIFT)); + out_be32(&srds_regs->bank[pll_num].pllcr0, + pllcr0); + clrbits_be32(&srds_regs->bank[pll_num].pllcr1, + SRDS_PLLCR1_BCAP_EN); + setbits_be32(&srds_regs->bank[pll_num].pllcr1, + SRDS_PLLCR1_BCAP_OVD); + ret = calibrate_pll(srds_regs, pll_num); + if (ret) + return ret; + } + } +out: + return 0; +} + +static int check_serdes_pll_locks(void) +{ + serdes_corenet_t *srds1_regs = + (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR; + serdes_corenet_t *srds2_regs = + (void *)CONFIG_SYS_FSL_CORENET_SERDES2_ADDR; + int i, ret1, ret2; + + debug("\nSerDes1 Lock check\n"); + for (i = 0; i < CONFIG_SYS_FSL_SRDS_NUM_PLLS; i++) { + ret1 = check_pll_locks(srds1_regs, i); + if (ret1) { + printf("SerDes1, PLL:%d didnt lock\n", i); + return ret1; + } + } + debug("\nSerDes2 Lock check\n"); + for (i = 0; i < CONFIG_SYS_FSL_SRDS_NUM_PLLS; i++) { + ret2 = check_pll_locks(srds2_regs, i); + if (ret2) { + printf("SerDes2, PLL:%d didnt lock\n", i); + return ret2; + } + } + + return 0; +} + int config_serdes1_refclks(void) { ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); serdes_corenet_t *srds_regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR; u32 serdes1_prtcl, lane; - unsigned int flag_sgmii_prtcl = 0; - int ret, i; + unsigned int flag_sgmii_aurora_prtcl = 0; + int i; + int ret = 0; serdes1_prtcl = in_be32(&gur->rcwsr[4]) & FSL_CORENET2_RCWSR4_SRDS1_PRTCL; @@ -257,10 +716,12 @@ int config_serdes1_refclks(void) serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT; debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl); - /* Clear SRDS_RSTCTL_RST bit for both PLLs before changing refclks + /* To prevent generation of reset request from SerDes + * while changing the refclks, By setting SRDS_RST_MSK bit, + * SerDes reset event cannot cause a reset request */ - for (i = 0; i < PLL_NUM; i++) - clrbits_be32(&srds_regs->bank[i].rstctl, SRDS_RSTCTL_RST); + setbits_be32(&gur->rstrqmr1, FSL_CORENET_RSTRQMR1_SRDS_RST_MSK); + /* Reconfigure IDT idt8t49n222a device for CPRI to work * For this SerDes1's Refclk1 and refclk2 need to be set * to 122.88MHz @@ -270,6 +731,25 @@ int config_serdes1_refclks(void) case 0x2C: case 0x2D: case 0x2E: + case 0x02: + case 0x04: + case 0x05: + case 0x06: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x30: + case 0x32: + case 0x33: + case 0x34: + case 0x39: + case 0x3A: + case 0x3C: + case 0x3D: + case 0x5C: + case 0x5D: debug("Configuring idt8t49n222a for CPRI SerDes clks:" " for srds_prctl:%x\n", serdes1_prtcl); ret = select_i2c_ch_pca(I2C_CH_IDT); @@ -279,16 +759,16 @@ int config_serdes1_refclks(void) SERDES_REFCLK_122_88, 0); if (ret) { printf("IDT8T49N222A configuration failed.\n"); - return ret; + goto out; } else - printf("IDT8T49N222A configured.\n"); + debug("IDT8T49N222A configured.\n"); } else { - return ret; + goto out; } select_i2c_ch_pca(I2C_CH_DEFAULT); /* Change SerDes1's Refclk1 to 125MHz for on board - * SGMIIs to work + * SGMIIs or Aurora to work */ for (lane = 0; lane < SRDS_MAX_LANES; lane++) { enum srds_prtcl lane_prtcl = serdes_get_prtcl @@ -300,20 +780,21 @@ int config_serdes1_refclks(void) case SGMII_FM1_DTSEC4: case SGMII_FM1_DTSEC5: case SGMII_FM1_DTSEC6: - flag_sgmii_prtcl++; + case AURORA: + flag_sgmii_aurora_prtcl++; break; default: break; } } - if (flag_sgmii_prtcl) + if (flag_sgmii_aurora_prtcl) QIXIS_WRITE(brdcfg[4], QIXIS_SRDS1CLK_125); /* Steps For SerDes PLLs reset and reconfiguration after * changing SerDes's refclks */ - for (i = 0; i < PLL_NUM; i++) { + for (i = 0; i < CONFIG_SYS_FSL_SRDS_NUM_PLLS; i++) { debug("For PLL%d reset and reconfiguration after" " changing refclks\n", i+1); clrbits_be32(&srds_regs->bank[i].rstctl, @@ -333,16 +814,101 @@ int config_serdes1_refclks(void) printf("WARNING:IDT8T49N222A configuration not" " supported for:%x SerDes1 Protocol.\n", serdes1_prtcl); - return -1; } - return 0; +out: + /* Clearing SRDS_RST_MSK bit as now + * SerDes reset event can cause a reset request + */ + clrbits_be32(&gur->rstrqmr1, FSL_CORENET_RSTRQMR1_SRDS_RST_MSK); + return ret; +} + +int config_serdes2_refclks(void) +{ + ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + serdes_corenet_t *srds2_regs = + (void *)CONFIG_SYS_FSL_CORENET_SERDES2_ADDR; + u32 serdes2_prtcl; + int ret = 0; + int i; + + serdes2_prtcl = in_be32(&gur->rcwsr[4]) & + FSL_CORENET2_RCWSR4_SRDS2_PRTCL; + if (!serdes2_prtcl) { + debug("SERDES2 is not enabled\n"); + return -ENODEV; + } + serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT; + debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl); + + /* To prevent generation of reset request from SerDes + * while changing the refclks, By setting SRDS_RST_MSK bit, + * SerDes reset event cannot cause a reset request + */ + setbits_be32(&gur->rstrqmr1, FSL_CORENET_RSTRQMR1_SRDS_RST_MSK); + + /* Reconfigure IDT idt8t49n222a device for PCIe SATA to work + * For this SerDes2's Refclk1 need to be set to 100MHz + */ + switch (serdes2_prtcl) { + case 0x9E: + case 0x9A: + case 0xb2: + debug("Configuring IDT for PCIe SATA for srds_prctl:%x\n", + serdes2_prtcl); + ret = select_i2c_ch_pca(I2C_CH_IDT); + if (!ret) { + ret = set_serdes_refclk(IDT_SERDES2_ADDRESS, 2, + SERDES_REFCLK_100, + SERDES_REFCLK_156_25, 0); + if (ret) { + printf("IDT8T49N222A configuration failed.\n"); + goto out; + } else + debug("IDT8T49N222A configured.\n"); + } else { + goto out; + } + select_i2c_ch_pca(I2C_CH_DEFAULT); + + /* Steps For SerDes PLLs reset and reconfiguration after + * changing SerDes's refclks + */ + for (i = 0; i < CONFIG_SYS_FSL_SRDS_NUM_PLLS; i++) { + clrbits_be32(&srds2_regs->bank[i].rstctl, + SRDS_RSTCTL_SDRST_B); + udelay(10); + clrbits_be32(&srds2_regs->bank[i].rstctl, + (SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B)); + udelay(10); + setbits_be32(&srds2_regs->bank[i].rstctl, + SRDS_RSTCTL_RST); + setbits_be32(&srds2_regs->bank[i].rstctl, + (SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B + | SRDS_RSTCTL_SDRST_B)); + + udelay(10); + } + break; + default: + printf("IDT configuration not supported for:%x S2 Protocol.\n", + serdes2_prtcl); + } + +out: + /* Clearing SRDS_RST_MSK bit as now + * SerDes reset event can cause a reset request + */ + clrbits_be32(&gur->rstrqmr1, FSL_CORENET_RSTRQMR1_SRDS_RST_MSK); + return ret; } int board_early_init_r(void) { const unsigned int flashbase = CONFIG_SYS_FLASH_BASE; const u8 flash_esel = find_tlb_idx((void *)flashbase, 1); + int ret; /* * Remap Boot flash + PROMJET region to caching-inhibited @@ -364,6 +930,13 @@ int board_early_init_r(void) #ifdef CONFIG_SYS_DPAA_QBMAN setup_portals(); #endif + /* + * Adjust core voltage according to voltage ID + * This function changes I2C mux to channel 2. + */ + if (adjust_vdd(0) < 0) + printf("Warning: Adjusting core voltage failed\n"); + /* SerDes1 refclks need to be set again, as default clks * are not suitable for CPRI and onboard SGMIIs to work * simultaneously. @@ -375,6 +948,35 @@ int board_early_init_r(void) else printf("SerDes1 Refclks have been set.\n"); + /* SerDes2 refclks need to be set again, as default clks + * are not suitable for PCIe SATA to work + * This function will set SerDes2's Refclk1 and refclk2 + * for SerDes2 protocols having PCIe in them + * for PCIe SATA to work + */ + ret = config_serdes2_refclks(); + if (!ret) + printf("SerDes2 Refclks have been set.\n"); + else if (ret == -ENODEV) + printf("SerDes disable, Refclks couldn't change.\n"); + else + printf("SerDes2 Refclk reconfiguring failed.\n"); + +#if defined(CONFIG_SYS_FSL_ERRATUM_A006384) || \ + defined(CONFIG_SYS_FSL_ERRATUM_A006475) + /* Rechecking the SerDes locks after all SerDes configurations + * are done, As SerDes PLLs may not lock reliably at 5 G VCO + * and at cold temperatures. + * Following sequence ensure the proper locking of SerDes PLLs. + */ + if (SVR_MAJ(get_svr()) == 1) { + if (check_serdes_pll_locks()) + printf("SerDes plls still not locked properly.\n"); + else + printf("SerDes plls have been locked well.\n"); + } +#endif + /* Configure VSC3316 and VSC3308 crossbar switches */ if (configure_vsc3316_3308()) printf("VSC:failed to configure VSC3316/3308.\n");