serdes_prtcl_map[NONE] = 1;
}
+__weak int get_serdes_volt(void)
+{
+ return -1;
+}
+
+__weak int set_serdes_volt(int svdd)
+{
+ return -1;
+}
+
+int setup_serdes_volt(u32 svdd)
+{
+ struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+ struct ccsr_serdes *serdes1_base;
+#ifdef CONFIG_SYS_FSL_SRDS_2
+ struct ccsr_serdes *serdes2_base;
+#endif
+ u32 cfg_rcw4 = gur_in32(&gur->rcwsr[4]);
+ u32 cfg_rcw5 = gur_in32(&gur->rcwsr[5]);
+ u32 cfg_tmp, reg = 0;
+ int svdd_cur, svdd_tar;
+ int ret;
+ int i;
+
+ /* Only support switch SVDD to 900mV/1000mV */
+ if (svdd != 900 && svdd != 1000)
+ return -EINVAL;
+
+ svdd_tar = svdd;
+ svdd_cur = get_serdes_volt();
+ if (svdd_cur < 0)
+ return -EINVAL;
+
+ debug("%s: current SVDD: %dmV; target SVDD: %dmV\n",
+ __func__, svdd_cur, svdd_tar);
+ if (svdd_cur == svdd_tar)
+ return 0;
+
+ serdes1_base = (void *)CONFIG_SYS_FSL_SERDES_ADDR;
+#ifdef CONFIG_SYS_FSL_SRDS_2
+ serdes2_base = (void *)serdes1_base + 0x10000;
+#endif
+
+ /* Put the all enabled lanes in reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+ cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
+ cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
+
+ for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
+ reg = in_be32(&serdes1_base->lane[i].gcr0);
+ reg &= 0xFF9FFFFF;
+ out_be32(&serdes1_base->lane[i].gcr0, reg);
+ }
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+ cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
+ cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
+
+ for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
+ reg = in_be32(&serdes2_base->lane[i].gcr0);
+ reg &= 0xFF9FFFFF;
+ out_be32(&serdes2_base->lane[i].gcr0, reg);
+ }
+#endif
+
+ /* Put the all enabled PLL in reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+ cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
+ for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
+ reg = in_be32(&serdes1_base->bank[i].rstctl);
+ reg &= 0xFFFFFFBF;
+ reg |= 0x10000000;
+ out_be32(&serdes1_base->bank[i].rstctl, reg);
+ udelay(1);
+
+ reg = in_be32(&serdes1_base->bank[i].rstctl);
+ reg &= 0xFFFFFF1F;
+ out_be32(&serdes1_base->bank[i].rstctl, reg);
+ }
+ udelay(1);
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+ cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
+ for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
+ reg = in_be32(&serdes2_base->bank[i].rstctl);
+ reg &= 0xFFFFFFBF;
+ reg |= 0x10000000;
+ out_be32(&serdes2_base->bank[i].rstctl, reg);
+ udelay(1);
+
+ reg = in_be32(&serdes2_base->bank[i].rstctl);
+ reg &= 0xFFFFFF1F;
+ out_be32(&serdes2_base->bank[i].rstctl, reg);
+ }
+ udelay(1);
+#endif
+
+ /* Put the Rx/Tx calibration into reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+ reg = in_be32(&serdes1_base->srdstcalcr);
+ reg &= 0xF7FFFFFF;
+ out_be32(&serdes1_base->srdstcalcr, reg);
+ reg = in_be32(&serdes1_base->srdsrcalcr);
+ reg &= 0xF7FFFFFF;
+ out_be32(&serdes1_base->srdsrcalcr, reg);
+
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+ reg = in_be32(&serdes2_base->srdstcalcr);
+ reg &= 0xF7FFFFFF;
+ out_be32(&serdes2_base->srdstcalcr, reg);
+ reg = in_be32(&serdes2_base->srdsrcalcr);
+ reg &= 0xF7FFFFFF;
+ out_be32(&serdes2_base->srdsrcalcr, reg);
+#endif
+
+ /*
+ * If SVDD set failed, will not return directly, so that the
+ * serdes lanes can complete reseting.
+ */
+ ret = set_serdes_volt(svdd_tar);
+ if (ret)
+ printf("%s: Failed to set SVDD\n", __func__);
+
+ /* Wait for SVDD to stabilize */
+ udelay(100);
+
+ /* For each PLL that’s not disabled via RCW */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+ cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
+ for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
+ reg = in_be32(&serdes1_base->bank[i].rstctl);
+ reg |= 0x00000020;
+ out_be32(&serdes1_base->bank[i].rstctl, reg);
+ udelay(1);
+
+ reg = in_be32(&serdes1_base->bank[i].rstctl);
+ reg |= 0x00000080;
+ out_be32(&serdes1_base->bank[i].rstctl, reg);
+
+ /* Take the Rx/Tx calibration out of reset */
+ if (!(cfg_tmp == 0x3 && i == 1)) {
+ udelay(1);
+ reg = in_be32(&serdes1_base->srdstcalcr);
+ reg |= 0x08000000;
+ out_be32(&serdes1_base->srdstcalcr, reg);
+ reg = in_be32(&serdes1_base->srdsrcalcr);
+ reg |= 0x08000000;
+ out_be32(&serdes1_base->srdsrcalcr, reg);
+ }
+ }
+ udelay(1);
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+ cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
+ for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
+ reg = in_be32(&serdes2_base->bank[i].rstctl);
+ reg |= 0x00000020;
+ out_be32(&serdes2_base->bank[i].rstctl, reg);
+ udelay(1);
+
+ reg = in_be32(&serdes2_base->bank[i].rstctl);
+ reg |= 0x00000080;
+ out_be32(&serdes2_base->bank[i].rstctl, reg);
+
+ /* Take the Rx/Tx calibration out of reset */
+ if (!(cfg_tmp == 0x3 && i == 1)) {
+ udelay(1);
+ reg = in_be32(&serdes2_base->srdstcalcr);
+ reg |= 0x08000000;
+ out_be32(&serdes2_base->srdstcalcr, reg);
+ reg = in_be32(&serdes2_base->srdsrcalcr);
+ reg |= 0x08000000;
+ out_be32(&serdes2_base->srdsrcalcr, reg);
+ }
+ }
+ udelay(1);
+
+#endif
+
+ /* Wait for at lesat 625us to ensure the PLLs being reset are locked */
+ udelay(800);
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+ cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
+ for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
+ /* if the PLL is not locked, set RST_ERR */
+ reg = in_be32(&serdes1_base->bank[i].pllcr0);
+ if (!((reg >> 23) & 0x1)) {
+ reg = in_be32(&serdes1_base->bank[i].rstctl);
+ reg |= 0x20000000;
+ out_be32(&serdes1_base->bank[i].rstctl, reg);
+ } else {
+ udelay(1);
+ reg = in_be32(&serdes1_base->bank[i].rstctl);
+ reg &= 0xFFFFFFEF;
+ reg |= 0x00000040;
+ out_be32(&serdes1_base->bank[i].rstctl, reg);
+ udelay(1);
+ }
+ }
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+ cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
+ for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
+ reg = in_be32(&serdes2_base->bank[i].pllcr0);
+ if (!((reg >> 23) & 0x1)) {
+ reg = in_be32(&serdes2_base->bank[i].rstctl);
+ reg |= 0x20000000;
+ out_be32(&serdes2_base->bank[i].rstctl, reg);
+ } else {
+ udelay(1);
+ reg = in_be32(&serdes2_base->bank[i].rstctl);
+ reg &= 0xFFFFFFEF;
+ reg |= 0x00000040;
+ out_be32(&serdes2_base->bank[i].rstctl, reg);
+ udelay(1);
+ }
+ }
+#endif
+
+ /* Take the all enabled lanes out of reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+ cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
+ cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
+
+ for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
+ reg = in_be32(&serdes1_base->lane[i].gcr0);
+ reg |= 0x00600000;
+ out_be32(&serdes1_base->lane[i].gcr0, reg);
+ }
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+ cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
+ cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
+
+ for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
+ reg = in_be32(&serdes2_base->lane[i].gcr0);
+ reg |= 0x00600000;
+ out_be32(&serdes2_base->lane[i].gcr0, reg);
+ }
+#endif
+ /* For each PLL being reset, and achieved PLL lock set RST_DONE */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+ cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
+ for (i = 0; i < 2; i++) {
+ reg = in_be32(&serdes1_base->bank[i].pllcr0);
+ if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
+ reg = in_be32(&serdes1_base->bank[i].rstctl);
+ reg |= 0x40000000;
+ out_be32(&serdes1_base->bank[i].rstctl, reg);
+ }
+ }
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+ cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
+ for (i = 0; i < 2; i++) {
+ reg = in_be32(&serdes2_base->bank[i].pllcr0);
+ if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
+ reg = in_be32(&serdes2_base->bank[i].rstctl);
+ reg |= 0x40000000;
+ out_be32(&serdes2_base->bank[i].rstctl, reg);
+ }
+ }
+#endif
+
+ return ret;
+}
+
void fsl_serdes_init(void)
{
#ifdef CONFIG_SYS_FSL_SRDS_1
#endif
}
+/* Get VDD in the unit mV from voltage ID */
+int get_core_volt_from_fuse(void)
+{
+ struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+ int vdd;
+ u32 fusesr;
+ u8 vid;
+
+ fusesr = in_be32(&gur->dcfg_fusesr);
+ debug("%s: fusesr = 0x%x\n", __func__, fusesr);
+ vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_ALTVID_SHIFT) &
+ FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK;
+ if ((vid == 0) || (vid == FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK)) {
+ vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_VID_SHIFT) &
+ FSL_CHASSIS2_DCFG_FUSESR_VID_MASK;
+ }
+ debug("%s: VID = 0x%x\n", __func__, vid);
+ switch (vid) {
+ case 0x00: /* VID isn't supported */
+ vdd = -EINVAL;
+ debug("%s: The VID feature is not supported\n", __func__);
+ break;
+ case 0x08: /* 0.9V silicon */
+ vdd = 900;
+ break;
+ case 0x10: /* 1.0V silicon */
+ vdd = 1000;
+ break;
+ default: /* Other core voltage */
+ vdd = -EINVAL;
+ printf("%s: The VID(%x) isn't supported\n", __func__, vid);
+ break;
+ }
+ debug("%s: The required minimum volt of CORE is %dmV\n", __func__, vdd);
+
+ return vdd;
+}
+
+__weak int board_switch_core_volt(u32 vdd)
+{
+ return 0;
+}
+
+static int setup_core_volt(u32 vdd)
+{
+ return board_setup_core_volt(vdd);
+}
+
+#ifdef CONFIG_SYS_FSL_DDR
+static void ddr_enable_0v9_volt(bool en)
+{
+ struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
+ u32 tmp;
+
+ tmp = ddr_in32(&ddr->ddr_cdr1);
+
+ if (en)
+ tmp |= DDR_CDR1_V0PT9_EN;
+ else
+ tmp &= ~DDR_CDR1_V0PT9_EN;
+
+ ddr_out32(&ddr->ddr_cdr1, tmp);
+}
+#endif
+
+int setup_chip_volt(void)
+{
+ int vdd;
+
+ vdd = get_core_volt_from_fuse();
+ /* Nothing to do for silicons doesn't support VID */
+ if (vdd < 0)
+ return vdd;
+
+ if (setup_core_volt(vdd))
+ printf("%s: Switch core VDD to %dmV failed\n", __func__, vdd);
+#ifdef CONFIG_SYS_HAS_SERDES
+ if (setup_serdes_volt(vdd))
+ printf("%s: Switch SVDD to %dmV failed\n", __func__, vdd);
+#endif
+
+#ifdef CONFIG_SYS_FSL_DDR
+ if (vdd == 900)
+ ddr_enable_0v9_volt(true);
+#endif
+
+ return 0;
+}
+
void fsl_lsch2_early_init_f(void)
{
struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR;