From: Minghuan Lian <minghuan.l...@freescale.com>

Add support of SerDes framework for LayerScape Architecture.
    - Add support of 2 SerDes block
    - Add SerDes protocol parsing and detection
    - Create table of SerDes protocol supported by LS2085A

Signed-off-by: Prabhakar Kushwaha <prabha...@freescale.com>
Signed-off-by: Minghuan Lian <minghuan.l...@freescale.com>
---
 arch/arm/cpu/armv8/fsl-lsch3/Makefile              |    1 +
 arch/arm/cpu/armv8/fsl-lsch3/cpu.c                 |    4 +
 .../fsl-lsch3/fsl_lsch3_serdes.c}                  |   78 ++++++-------
 arch/arm/cpu/armv8/fsl-lsch3/ls2085a_serdes.c      |  117 ++++++++++++++++++++
 arch/arm/include/asm/arch-fsl-lsch3/config.h       |    4 +
 arch/arm/include/asm/arch-fsl-lsch3/fsl_serdes.h   |   67 +++++++++++
 arch/arm/include/asm/arch-fsl-lsch3/immap_lsch3.h  |    5 +
 include/configs/ls2085a_common.h                   |    5 +
 8 files changed, 237 insertions(+), 44 deletions(-)
 copy arch/arm/cpu/{armv7/ls102xa/fsl_ls1_serdes.c => 
armv8/fsl-lsch3/fsl_lsch3_serdes.c} (51%)
 create mode 100644 arch/arm/cpu/armv8/fsl-lsch3/ls2085a_serdes.c
 create mode 100644 arch/arm/include/asm/arch-fsl-lsch3/fsl_serdes.h

diff --git a/arch/arm/cpu/armv8/fsl-lsch3/Makefile 
b/arch/arm/cpu/armv8/fsl-lsch3/Makefile
index 6542590..9f7815b 100644
--- a/arch/arm/cpu/armv8/fsl-lsch3/Makefile
+++ b/arch/arm/cpu/armv8/fsl-lsch3/Makefile
@@ -8,5 +8,6 @@ obj-y += cpu.o
 obj-y += lowlevel.o
 obj-y += soc.o
 obj-y += speed.o
+obj-$(CONFIG_SYS_HAS_SERDES) += fsl_lsch3_serdes.o ls2085a_serdes.o
 obj-$(CONFIG_MP) += mp.o
 obj-$(CONFIG_OF_LIBFDT) += fdt.o
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c 
b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
index 595dbd1..caa48f2 100644
--- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
@@ -12,6 +12,7 @@
 #include <asm/arch-fsl-lsch3/immap_lsch3.h>
 #include <fsl_debug_server.h>
 #include <fsl-mc/fsl_mc.h>
+#include <asm/arch/fsl_serdes.h>
 #include "cpu.h"
 #include "mp.h"
 #include "speed.h"
@@ -415,6 +416,9 @@ int arch_early_init_r(void)
        if (rv)
                printf("Did not wake secondary cores\n");
 
+#ifdef CONFIG_SYS_HAS_SERDES
+       fsl_serdes_init();
+#endif
        return 0;
 }
 
diff --git a/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c 
b/arch/arm/cpu/armv8/fsl-lsch3/fsl_lsch3_serdes.c
similarity index 51%
copy from arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c
copy to arch/arm/cpu/armv8/fsl-lsch3/fsl_lsch3_serdes.c
index 9b78acb..78b9210 100644
--- a/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c
+++ b/arch/arm/cpu/armv8/fsl-lsch3/fsl_lsch3_serdes.c
@@ -1,32 +1,31 @@
 /*
- * Copyright 2014 Freescale Semiconductor, Inc.
+ * Copyright 2015 Freescale Semiconductor, Inc.
  *
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
-#include <asm/arch/fsl_serdes.h>
-#include <asm/arch/immap_ls102xa.h>
-#include <asm/errno.h>
 #include <asm/io.h>
-#include "fsl_ls1_serdes.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 u64 serdes1_prtcl_map;
+static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
 #endif
 #ifdef CONFIG_SYS_FSL_SRDS_2
-static u64 serdes2_prtcl_map;
+static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
 #endif
 
 int is_serdes_configured(enum srds_prtcl device)
 {
-       u64 ret = 0;
+       int ret = 0;
 
 #ifdef CONFIG_SYS_FSL_SRDS_1
-       ret |= (1ULL << device) & serdes1_prtcl_map;
+       ret |= serdes1_prtcl_map[device];
 #endif
 #ifdef CONFIG_SYS_FSL_SRDS_2
-       ret |= (1ULL << device) & serdes2_prtcl_map;
+       ret |= serdes2_prtcl_map[device];
 #endif
 
        return !!ret;
@@ -35,20 +34,20 @@ int is_serdes_configured(enum srds_prtcl device)
 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_be32(&gur->rcwsr[4]);
+       u32 cfg = in_le32(&gur->rcwsr[28]);
        int i;
 
        switch (sd) {
 #ifdef CONFIG_SYS_FSL_SRDS_1
        case FSL_SRDS_1:
-               cfg &= RCWSR4_SRDS1_PRTCL_MASK;
-               cfg >>= RCWSR4_SRDS1_PRTCL_SHIFT;
+               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 &= RCWSR4_SRDS2_PRTCL_MASK;
-               cfg >>= RCWSR4_SRDS2_PRTCL_SHIFT;
+               cfg &= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK;
+               cfg >>= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT;
                break;
 #endif
        default:
@@ -56,7 +55,7 @@ int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
                break;
        }
        /* Is serdes enabled at all? */
-       if (unlikely(cfg == 0))
+       if (cfg == 0)
                return -ENODEV;
 
        for (i = 0; i < SRDS_MAX_LANES; i++) {
@@ -67,14 +66,16 @@ int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
        return -ENODEV;
 }
 
-u64 serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift)
+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);
-       u64 serdes_prtcl_map = 0;
        u32 cfg;
        int lane;
 
-       cfg = in_be32(&gur->rcwsr[4]) & sd_prctl_mask;
+       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);
 
@@ -83,38 +84,27 @@ u64 serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 
sd_prctl_shift)
 
        for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
                enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
-
-               serdes_prtcl_map |= (1ULL << lane_prtcl);
+               if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
+                       debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
+               else
+                       serdes_prtcl_map[lane_prtcl] = 1;
        }
-
-       return serdes_prtcl_map;
 }
 
 void fsl_serdes_init(void)
 {
 #ifdef CONFIG_SYS_FSL_SRDS_1
-       serdes1_prtcl_map = serdes_init(FSL_SRDS_1,
-                                       CONFIG_SYS_FSL_SERDES_ADDR,
-                                       RCWSR4_SRDS1_PRTCL_MASK,
-                                       RCWSR4_SRDS1_PRTCL_SHIFT);
+       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
-       serdes2_prtcl_map = serdes_init(FSL_SRDS_2,
-                                       CONFIG_SYS_FSL_SERDES_ADDR +
-                                       FSL_SRDS_2 * 0x1000,
-                                       RCWSR4_SRDS2_PRTCL_MASK,
-                                       RCWSR4_SRDS2_PRTCL_SHIFT);
+       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
 }
-
-const char *serdes_clock_to_string(u32 clock)
-{
-       switch (clock) {
-       case SRDS_PLLCR0_RFCK_SEL_100:
-               return "100";
-       case SRDS_PLLCR0_RFCK_SEL_125:
-               return "125";
-       default:
-               return "100";
-       }
-}
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/ls2085a_serdes.c 
b/arch/arm/cpu/armv8/fsl-lsch3/ls2085a_serdes.c
new file mode 100644
index 0000000..098745b
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-lsch3/ls2085a_serdes.c
@@ -0,0 +1,117 @@
+/*
+ * 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;
+}
diff --git a/arch/arm/include/asm/arch-fsl-lsch3/config.h 
b/arch/arm/include/asm/arch-fsl-lsch3/config.h
index a81e3ed..98db1ef 100644
--- a/arch/arm/include/asm/arch-fsl-lsch3/config.h
+++ b/arch/arm/include/asm/arch-fsl-lsch3/config.h
@@ -38,6 +38,8 @@
 #define CONFIG_SYS_FSL_PMU_CLTBENR             (CONFIG_SYS_FSL_PMU_ADDR + \
                                                 0x18A0)
 
+#define CONFIG_SYS_FSL_LSCH3_SERDES_ADDR       (CONFIG_SYS_IMMR + 0xEA0000)
+
 /* SP (Cortex-A5) related */
 #define CONFIG_SYS_FSL_SP_ADDR                 (CONFIG_SYS_IMMR + 0x00F00000)
 #define CONFIG_SYS_FSL_SP_VSG_GIC_ADDR         (CONFIG_SYS_FSL_SP_ADDR)
@@ -133,6 +135,8 @@
 #define CONFIG_SYS_FSL_IFC_BANK_COUNT          8
 #define CONFIG_NUM_DDR_CONTROLLERS             3
 #define CONFIG_SYS_FSL_CLUSTER_CLOCKS          { 1, 1, 4, 4 }
+#define CONFIG_SYS_FSL_SRDS_1
+#define CONFIG_SYS_FSL_SRDS_2
 #else
 #error SoC not defined
 #endif
diff --git a/arch/arm/include/asm/arch-fsl-lsch3/fsl_serdes.h 
b/arch/arm/include/asm/arch-fsl-lsch3/fsl_serdes.h
new file mode 100644
index 0000000..2810f3f
--- /dev/null
+++ b/arch/arm/include/asm/arch-fsl-lsch3/fsl_serdes.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __FSL_SERDES_H
+#define __FSL_SERDES_H
+
+#include <config.h>
+
+#define        SRDS_MAX_LANES  8
+
+enum srds_prtcl {
+       NONE = 0,
+       PCIE1,
+       PCIE2,
+       PCIE3,
+       PCIE4,
+       SATA1,
+       SATA2,
+       XAUI1,
+       XAUI2,
+       XFI1,
+       XFI2,
+       XFI3,
+       XFI4,
+       XFI5,
+       XFI6,
+       XFI7,
+       XFI8,
+       SGMII1,
+       SGMII2,
+       SGMII3,
+       SGMII4,
+       SGMII5,
+       SGMII6,
+       SGMII7,
+       SGMII8,
+       SGMII9,
+       SGMII10,
+       SGMII11,
+       SGMII12,
+       SGMII13,
+       SGMII14,
+       SGMII15,
+       SGMII16,
+       QSGMII_A, /* A indicates MACs 1-4 */
+       QSGMII_B, /* B indicates MACs 5-8 */
+       QSGMII_C, /* C indicates MACs 9-12 */
+       QSGMII_D, /* D indicates MACs 12-16 */
+       SERDES_PRCTL_COUNT
+};
+
+enum srds {
+       FSL_SRDS_1  = 0,
+       FSL_SRDS_2  = 1,
+};
+
+int is_serdes_configured(enum srds_prtcl device);
+void fsl_serdes_init(void);
+
+int serdes_get_first_lane(u32 sd, enum srds_prtcl device);
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane);
+int is_serdes_prtcl_valid(int serdes, u32 prtcl);
+
+#endif /* __FSL_SERDES_H */
diff --git a/arch/arm/include/asm/arch-fsl-lsch3/immap_lsch3.h 
b/arch/arm/include/asm/arch-fsl-lsch3/immap_lsch3.h
index dd11ef7..91cf68b 100644
--- a/arch/arm/include/asm/arch-fsl-lsch3/immap_lsch3.h
+++ b/arch/arm/include/asm/arch-fsl-lsch3/immap_lsch3.h
@@ -63,6 +63,11 @@ struct ccsr_gur {
 #define FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK   0x3f
 #define FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_SHIFT 18
 #define FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_MASK  0x3f
+#define        FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK   0x00FF0000
+#define        FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT  16
+#define        FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK   0xFF000000
+#define        FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT  24
+
        u8      res_180[0x200-0x180];
        u32     scratchrw[32];  /* Scratch Read/Write */
        u8      res_280[0x300-0x280];
diff --git a/include/configs/ls2085a_common.h b/include/configs/ls2085a_common.h
index b47cf68..9bbcc64 100644
--- a/include/configs/ls2085a_common.h
+++ b/include/configs/ls2085a_common.h
@@ -19,6 +19,11 @@
 #define CONFIG_ARM_ERRATA_828024
 #define CONFIG_ARM_ERRATA_826974
 
+#include <asm/arch-fsl-lsch3/config.h>
+#if (defined(CONFIG_SYS_FSL_SRDS_1) || defined(CONFIG_SYS_FSL_SRDS_2))
+#define        CONFIG_SYS_HAS_SERDES
+#endif
+
 /* We need architecture specific misc initializations */
 #define CONFIG_ARCH_MISC_INIT
 
-- 
1.7.9.5

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to