[U-Boot] [PATCH v5 12/28] armv8: Add SerDes framework for Layerscape Architecture

York Sun yorksun at freescale.com
Sat Mar 21 03:28:16 CET 2015


From: Minghuan Lian <Minghuan.Lian at 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 <prabhakar at freescale.com>
Signed-off-by: Minghuan Lian <Minghuan.Lian at freescale.com>

---

Changes in v5:
  s/LayerScape/Layerscape/g

Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/arm/cpu/armv8/fsl-lsch3/Makefile             |    1 +
 arch/arm/cpu/armv8/fsl-lsch3/cpu.c                |    4 +
 arch/arm/cpu/armv8/fsl-lsch3/fsl_lsch3_serdes.c   |  110 +++++++++++++++++++
 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, 313 insertions(+)
 create mode 100644 arch/arm/cpu/armv8/fsl-lsch3/fsl_lsch3_serdes.c
 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/armv8/fsl-lsch3/fsl_lsch3_serdes.c b/arch/arm/cpu/armv8/fsl-lsch3/fsl_lsch3_serdes.c
new file mode 100644
index 0000000..78b9210
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-lsch3/fsl_lsch3_serdes.c
@@ -0,0 +1,110 @@
+/*
+ * 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
+}
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 f6b3ed0..5ce5e1c 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



More information about the U-Boot mailing list