--- /dev/null
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch-fsl-lsch3/immap_lsch3.h>
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
+#endif
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+       int ret = 0;
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+       ret |= serdes1_prtcl_map[device];
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+       ret |= serdes2_prtcl_map[device];
+#endif
+
+       return !!ret;
+}
+
+int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
+{
+       struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+       u32 cfg = in_le32(&gur->rcwsr[28]);
+       int i;
+
+       switch (sd) {
+#ifdef CONFIG_SYS_FSL_SRDS_1
+       case FSL_SRDS_1:
+               cfg &= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK;
+               cfg >>= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
+               break;
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+       case FSL_SRDS_2:
+               cfg &= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK;
+               cfg >>= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT;
+               break;
+#endif
+       default:
+               printf("invalid SerDes%d\n", sd);
+               break;
+       }
+       /* Is serdes enabled at all? */
+       if (cfg == 0)
+               return -ENODEV;
+
+       for (i = 0; i < SRDS_MAX_LANES; i++) {
+               if (serdes_get_prtcl(sd, cfg, i) == device)
+                       return i;
+       }
+
+       return -ENODEV;
+}
+
+void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
+               u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
+{
+       struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+       u32 cfg;
+       int lane;
+
+       memset(serdes_prtcl_map, 0, sizeof(serdes_prtcl_map));
+
+       cfg = in_le32(&gur->rcwsr[28]) & sd_prctl_mask;
+       cfg >>= sd_prctl_shift;
+       printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
+
+       if (!is_serdes_prtcl_valid(sd, cfg))
+               printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
+
+       for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
+               enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
+               if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
+                       debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
+               else
+                       serdes_prtcl_map[lane_prtcl] = 1;
+       }
+}
+
+void fsl_serdes_init(void)
+{
+#ifdef CONFIG_SYS_FSL_SRDS_1
+       serdes_init(FSL_SRDS_1,
+                   CONFIG_SYS_FSL_LSCH3_SERDES_ADDR,
+                   FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK,
+                   FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT,
+                   serdes1_prtcl_map);
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+       serdes_init(FSL_SRDS_2,
+                   CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + FSL_SRDS_2 * 0x10000,
+                   FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK,
+                   FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT,
+                   serdes2_prtcl_map);
+#endif
+}
 
--- /dev/null
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch-fsl-lsch3/immap_lsch3.h>
+
+struct serdes_config {
+       u8 protocol;
+       u8 lanes[SRDS_MAX_LANES];
+};
+
+static struct serdes_config serdes1_cfg_tbl[] = {
+       /* SerDes 1 */
+       {0x03, {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2 } },
+       {0x05, {PCIE2, PCIE2, PCIE2, PCIE2, SGMII4, SGMII3, SGMII2, SGMII1 } },
+       {0x07, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
+               SGMII1 } },
+       {0x09, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
+               SGMII1 } },
+       {0x0A, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
+               SGMII1 } },
+       {0x0C, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
+               SGMII1 } },
+       {0x0E, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
+               SGMII1 } },
+       {0x26, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, XFI2, XFI1 } },
+       {0x28, {SGMII8, SGMII7, SGMII6, SGMII5, XFI4, XFI3, XFI2, XFI1 } },
+       {0x2A, {XFI8, XFI7, XFI6, XFI5, XFI4, XFI3, XFI2, XFI1 } },
+       {0x2B, {SGMII8, SGMII7, SGMII6, SGMII5, XAUI1, XAUI1, XAUI1, XAUI1  } },
+       {0x32, {XAUI2, XAUI2, XAUI2, XAUI2, XAUI1, XAUI1, XAUI1, XAUI1  } },
+       {0x33, {PCIE2, PCIE2, PCIE2, PCIE2, QSGMII_D, QSGMII_C, QSGMII_B,
+               QSGMII_A} },
+       {0x35, {QSGMII_D, QSGMII_C, QSGMII_B, PCIE2, XFI4, XFI3, XFI2, XFI1 } },
+               {}
+};
+static struct serdes_config serdes2_cfg_tbl[] = {
+       /* SerDes 2 */
+       {0x07, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
+               SGMII16 } },
+       {0x09, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
+               SGMII16 } },
+       {0x0A, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
+               SGMII16 } },
+       {0x0C, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
+               SGMII16 } },
+       {0x0E, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
+               SGMII16 } },
+       {0x3D, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } },
+       {0x3E, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } },
+       {0x3F, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } },
+       {0x40, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } },
+       {0x41, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } },
+       {0x42, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } },
+       {0x43, {PCIE3, PCIE3, PCIE3, PCIE3, NONE, NONE, SATA1, SATA2 } },
+       {0x44, {PCIE3, PCIE3, PCIE3, PCIE3, NONE, NONE, SATA1, SATA2 } },
+       {0x45, {PCIE3, SGMII10, SGMII11, SGMII12, PCIE4, SGMII14, SGMII15,
+               SGMII16 } },
+       {0x47, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, PCIE4,
+               PCIE4 } },
+       {0x49, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, SATA1,
+               SATA2 } },
+       {0x4A, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, SATA1,
+               SATA2 } },
+       {}
+};
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+       serdes1_cfg_tbl,
+       serdes2_cfg_tbl,
+};
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+       struct serdes_config *ptr;
+
+       if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+               return 0;
+
+       ptr = serdes_cfg_tbl[serdes];
+       while (ptr->protocol) {
+               if (ptr->protocol == cfg)
+                       return ptr->lanes[lane];
+               ptr++;
+       }
+
+       return 0;
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+       int i;
+       struct serdes_config *ptr;
+
+       if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+               return 0;
+
+       ptr = serdes_cfg_tbl[serdes];
+       while (ptr->protocol) {
+               if (ptr->protocol == prtcl)
+                       break;
+               ptr++;
+       }
+
+       if (!ptr->protocol)
+               return 0;
+
+       for (i = 0; i < SRDS_MAX_LANES; i++) {
+               if (ptr->lanes[i] != NONE)
+                       return 1;
+       }
+
+       return 0;
+}