[U-Boot] [PATCH 1/3] armv8: ls1088a: Add NXP LS1088A SoC support

Ashish Kumar Ashish.Kumar at nxp.com
Wed Feb 15 15:13:54 UTC 2017


    The QorIQ LS1088A processor is built on the Layerscape
    architecture combining eight ARM A53 processor cores
    with advanced, high-performance datapath acceleration
    and networks, peripheral interfaces required for
    networking, wireless infrastructure, and general-purpose
    embedded applications.

    LS1088A is compliant to the Layerscape Chassis Generation 3.

    Features summary:
     - Eight 32-bit / 64-bit ARM v8 Cortex-A53 CPUs
     - Cores are in 2 cluster of 4-cores each
     - Cache coherent interconnect (CCI-400)
     - One 64-bit DDR4 SDRAM memory controller with ECC
     - Data path acceleration architecture 2.0 (DPAA2)
     - Ethernet interfaces: SGMIIs, RGMIIs, QSGMIIs, XFIs
     - QSPI, IFC, 3 PCIe, 1 SATA, 2 USB, 1 SDXC, 2 DUARTs etc

Signed-off-by: Alison Wang <alison.wang at nxp.com>
Signed-off-by: Prabhakar Kushwaha <prabhakar.kushwaha at nxp.com>
Signed-off-by: Ashish Kumar <Ashish.Kumar at nxp.com>
---
 arch/arm/cpu/armv8/fsl-layerscape/Makefile         |   4 +
 .../cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c    |  10 ++
 arch/arm/cpu/armv8/fsl-layerscape/ls1088a_serdes.c | 124 +++++++++++++++++++++
 arch/arm/include/asm/arch-fsl-layerscape/config.h  |  46 ++++++++
 arch/arm/include/asm/arch-fsl-layerscape/cpu.h     |   4 +
 .../include/asm/arch-fsl-layerscape/fsl_serdes.h   |   1 +
 .../include/asm/arch-fsl-layerscape/immap_lsch3.h  |  11 ++
 arch/arm/include/asm/arch-fsl-layerscape/soc.h     |   4 +
 drivers/net/ldpaa_eth/Makefile                     |   1 +
 drivers/net/ldpaa_eth/ls1088a.c                    |  87 +++++++++++++++
 10 files changed, 292 insertions(+)
 create mode 100644 arch/arm/cpu/armv8/fsl-layerscape/ls1088a_serdes.c
 create mode 100644 drivers/net/ldpaa_eth/ls1088a.c

diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Makefile b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
index c9ab93e..cfad154 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Makefile
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
@@ -38,3 +38,7 @@ endif
 ifneq ($(CONFIG_ARCH_LS1046A),)
 obj-$(CONFIG_SYS_HAS_SERDES) += ls1046a_serdes.o
 endif
+
+ifneq ($(CONFIG_ARCH_LS1088A),)
+obj-$(CONFIG_SYS_HAS_SERDES) += ls1088a_serdes.o
+endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
index 955e0b7..d7e2d3c 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
@@ -28,6 +28,11 @@ __weak void wriop_init_dpmac_qsgmii(int sd, int lane_prtcl)
 	return;
 }
 
+__weak int serdes_get_number(int serdes, int cfg)
+{
+	return cfg;
+}
+
 int is_serdes_configured(enum srds_prtcl device)
 {
 	int ret = 0;
@@ -73,6 +78,9 @@ int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
 		printf("invalid SerDes%d\n", sd);
 		break;
 	}
+
+	cfg = serdes_get_number(sd, cfg);
+
 	/* Is serdes enabled at all? */
 	if (cfg == 0)
 		return -ENODEV;
@@ -99,6 +107,8 @@ void serdes_init(u32 sd, u32 sd_addr, u32 rcwsr, u32 sd_prctl_mask,
 
 	cfg = gur_in32(&gur->rcwsr[rcwsr - 1]) & sd_prctl_mask;
 	cfg >>= sd_prctl_shift;
+
+	cfg = serdes_get_number(sd, cfg);
 	printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
 
 	if (!is_serdes_prtcl_valid(sd, cfg))
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1088a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1088a_serdes.c
new file mode 100644
index 0000000..9f89bd0
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1088a_serdes.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+
+struct serdes_config {
+	u8 ip_protocol;
+	u8 lanes[SRDS_MAX_LANES];
+	u8 rcw_lanes[SRDS_MAX_LANES];
+};
+
+static struct serdes_config serdes1_cfg_tbl[] = {
+	/* SerDes 1 */
+	{0x12, {SGMII3, SGMII7, SGMII1, SGMII2 }, {3, 3, 3, 3 }  },
+	{0x15, {SGMII3, SGMII7, XFI1, XFI2 }, {3, 3, 1, 1 } },
+	{0x16, {SGMII3, SGMII7, SGMII1, XFI2 }, {3, 3, 3, 1 } },
+	{0x17, {SGMII3, SGMII7, SGMII1, SGMII2 }, {3, 3, 3, 2 } },
+	{0x18, {SGMII3, SGMII7, SGMII1, SGMII2 }, {3, 3, 2, 2 } },
+	{0x19, {SGMII3, QSGMII_B, XFI1, XFI2}, {3, 4, 1, 1 } },
+	{0x1A, {SGMII3, QSGMII_B, SGMII1, XFI2 }, {3, 4, 3, 1 } },
+	{0x1B, {SGMII3, QSGMII_B, SGMII1, SGMII2 }, {3, 4, 3, 2 } },
+	{0x1C, {SGMII3, QSGMII_B, SGMII1, SGMII2 }, {3, 4, 2, 2 } },
+	{0x1D, {QSGMII_A, QSGMII_B, XFI1, XFI2 }, {4, 4, 1, 1 } },
+	{0x1E, {QSGMII_A, QSGMII_B, SGMII1, XFI2  }, {4, 4, 3, 1 } },
+	{0x1F, {QSGMII_A, QSGMII_B, SGMII1, SGMII2  }, {4, 4, 3, 2 } },
+	{0x20, {QSGMII_A, QSGMII_B, SGMII1, SGMII2 }, {4, 4, 2, 2 } },
+	{0x35, {SGMII3, QSGMII_B, SGMII1, SGMII2 }, {3, 4, 3, 3 } },
+	{0x36, {QSGMII_A, QSGMII_B, SGMII1, SGMII2 }, {4, 4, 3, 3 } },
+		{}
+};
+static struct serdes_config serdes2_cfg_tbl[] = {
+	/* SerDes 2 */
+	{0x0C, {PCIE1, PCIE1, PCIE1, PCIE1 }, {8, 8, 8, 8 } },
+	{0x0D, {PCIE1, PCIE2, PCIE3, SATA1 }, {5, 5, 5, 9 }  },
+	{0x0E, {PCIE1, PCIE1, PCIE2, SATA1 }, {7, 7, 6, 9 }  },
+	{0x13, {PCIE1, PCIE1, PCIE3, PCIE3 }, {7, 7, 7, 7 }  },
+	{0x14, {PCIE1, PCIE2, PCIE3, PCIE3 }, {5, 5, 7, 7 }  },
+	{}
+};
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+	serdes1_cfg_tbl,
+	serdes2_cfg_tbl,
+};
+
+int serdes_get_number(int serdes, int cfg)
+{
+	struct serdes_config *ptr;
+	int i, j, index, lnk;
+	int is_found, max_lane = SRDS_MAX_LANES;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+
+	while (ptr->ip_protocol) {
+		is_found = 1;
+		for (i = 0, j = max_lane - 1; i < max_lane; i++, j--) {
+			lnk = cfg & (0xf << 4 * i);
+			lnk = lnk >> (4 * i);
+
+			index = (serdes == FSL_SRDS_1) ? j : i;
+
+			if (ptr->rcw_lanes[index] == lnk && is_found)
+				is_found = 1;
+			else
+				is_found = 0;
+		}
+
+		if (is_found)
+			return ptr->ip_protocol;
+		ptr++;
+	}
+
+	return 0;
+}
+
+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->ip_protocol) {
+		if (ptr->ip_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->ip_protocol) {
+		if (ptr->ip_protocol == prtcl)
+			break;
+		ptr++;
+	}
+
+	if (!ptr->ip_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-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h
index 83f5501..3aed123 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/config.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h
@@ -219,6 +219,52 @@
 
 #define CONFIG_SYS_FSL_MAX_NUM_OF_SEC		1
 
+#elif defined(CONFIG_ARCH_LS1088A)
+#define CONFIG_MAX_CPUS				8
+#define CONFIG_SYS_FSL_NUM_CC_PLLS		3
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT		8
+#define CONFIG_NUM_DDR_CONTROLLERS		1
+#define CONFIG_SYS_FSL_CLUSTER_CLOCKS		{ 1, 1 }
+#define CONFIG_SYS_FSL_PLATFORM_CLK_RATIO	1
+#define CONFIG_GICV3
+#define CONFIG_FSL_TZPC_BP147
+#define CONFIG_FSL_TZASC_400
+#define CONFIG_FSL_TZASC_1
+
+#define	SRDS_MAX_LANES	4
+#define CONFIG_SYS_FSL_SRDS_1
+#define CONFIG_SYS_FSL_SRDS_2
+
+/* DDR */
+#define CONFIG_SYS_FSL_DDR_LE
+#define CONFIG_SYS_LS2_DDR_BLOCK1_SIZE	((phys_size_t)2 << 30)
+#define CONFIG_MAX_MEM_MAPPED		CONFIG_SYS_LS2_DDR_BLOCK1_SIZE
+
+#define CONFIG_SYS_FSL_CCSR_GUR_LE
+#define CONFIG_SYS_FSL_CCSR_SCFG_LE
+#define CONFIG_SYS_FSL_ESDHC_LE
+#define CONFIG_SYS_FSL_IFC_LE
+#define CONFIG_SYS_FSL_PEX_LUT_LE
+
+#define CONFIG_SYS_MEMAC_LITTLE_ENDIAN
+
+/* SFP */
+#define CONFIG_SYS_FSL_SFP_VER_3_4
+#define CONFIG_SYS_FSL_SFP_LE
+#define CONFIG_SYS_FSL_SRK_LE
+
+/* SEC */
+#define CONFIG_SYS_FSL_SEC_LE
+#define CONFIG_SYS_FSL_SEC_COMPAT	5
+
+/* Security Monitor */
+#define CONFIG_SYS_FSL_SEC_MON_LE
+
+/* Secure Boot */
+#define CONFIG_ESBC_HDR_LS
+
+/* DCFG - GUR */
+#define CONFIG_SYS_FSL_CCSR_GUR_LE
 #else
 #error SoC not defined
 #endif
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
index 4ea4aea..104a5b0 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
@@ -21,6 +21,10 @@ static struct cpu_type cpu_type_list[] = {
 	CPU_TYPE_ENTRY(LS1026A, LS1026A, 2),
 	CPU_TYPE_ENTRY(LS2040A, LS2040A, 4),
 	CPU_TYPE_ENTRY(LS1012A, LS1012A, 1),
+	CPU_TYPE_ENTRY(LS1088A, LS1088A, 8),
+	CPU_TYPE_ENTRY(LS1084A, LS1084A, 8),
+	CPU_TYPE_ENTRY(LS1048A, LS1048A, 4),
+	CPU_TYPE_ENTRY(LS1044A, LS1048A, 4),
 };
 
 #ifndef CONFIG_SYS_DCACHE_OFF
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
index 70181c5..8e18246 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
@@ -158,6 +158,7 @@ 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);
+int serdes_get_number(int serdes, int cfg);
 
 #ifdef CONFIG_FSL_LSCH2
 const char *serdes_clock_to_string(u32 clock);
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
index 04add3b..71dd7b5 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
@@ -245,6 +245,17 @@ struct ccsr_gur {
 #define FSL_CHASSIS3_SRDS2_PRTCL_SHIFT	FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT
 #define FSL_CHASSIS3_SRDS1_REGSR	29
 #define FSL_CHASSIS3_SRDS2_REGSR	29
+#elif defined(CONFIG_ARCH_LS1088A)
+#define	FSL_CHASSIS3_RCWSR29_SRDS1_PRTCL_MASK	0xFFFF0000
+#define	FSL_CHASSIS3_RCWSR29_SRDS1_PRTCL_SHIFT	16
+#define	FSL_CHASSIS3_RCWSR30_SRDS2_PRTCL_MASK	0x0000FFFF
+#define	FSL_CHASSIS3_RCWSR30_SRDS2_PRTCL_SHIFT	0
+#define FSL_CHASSIS3_SRDS1_PRTCL_MASK	FSL_CHASSIS3_RCWSR29_SRDS1_PRTCL_MASK
+#define FSL_CHASSIS3_SRDS1_PRTCL_SHIFT	FSL_CHASSIS3_RCWSR29_SRDS1_PRTCL_SHIFT
+#define FSL_CHASSIS3_SRDS2_PRTCL_MASK	FSL_CHASSIS3_RCWSR30_SRDS2_PRTCL_MASK
+#define FSL_CHASSIS3_SRDS2_PRTCL_SHIFT	FSL_CHASSIS3_RCWSR30_SRDS2_PRTCL_SHIFT
+#define FSL_CHASSIS3_SRDS1_REGSR	29
+#define FSL_CHASSIS3_SRDS2_REGSR	30
 #endif
 #define RCW_SB_EN_REG_INDEX	9
 #define RCW_SB_EN_MASK		0x00000400
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/soc.h b/arch/arm/include/asm/arch-fsl-layerscape/soc.h
index 426fe8e..2531d45 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/soc.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/soc.h
@@ -54,6 +54,10 @@ struct cpu_type {
 #define SVR_LS2084A		0x870910
 #define SVR_LS2048A		0x870920
 #define SVR_LS2044A		0x870930
+#define SVR_LS1048A		0x870320
+#define SVR_LS1084A		0x870302
+#define SVR_LS1088A		0x870300
+#define SVR_LS1044A		0x870322
 
 #define SVR_DEV_LS2080A		0x8701
 
diff --git a/drivers/net/ldpaa_eth/Makefile b/drivers/net/ldpaa_eth/Makefile
index 5587aa6..125d6c2 100644
--- a/drivers/net/ldpaa_eth/Makefile
+++ b/drivers/net/ldpaa_eth/Makefile
@@ -7,3 +7,4 @@
 obj-y += ldpaa_wriop.o
 obj-y += ldpaa_eth.o
 obj-$(CONFIG_LS2080A) += ls2080a.o
+obj-$(CONFIG_ARCH_LS1088A) += ls1088a.o
diff --git a/drivers/net/ldpaa_eth/ls1088a.c b/drivers/net/ldpaa_eth/ls1088a.c
new file mode 100644
index 0000000..703945c
--- /dev/null
+++ b/drivers/net/ldpaa_eth/ls1088a.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <phy.h>
+#include <fsl-mc/ldpaa_wriop.h>
+#include <asm/io.h>
+#include <asm/arch/fsl_serdes.h>
+
+u32 dpmac_to_devdisr[] = {
+	[WRIOP1_DPMAC1] = FSL_CHASSIS3_DEVDISR2_DPMAC1,
+	[WRIOP1_DPMAC2] = FSL_CHASSIS3_DEVDISR2_DPMAC2,
+	[WRIOP1_DPMAC3] = FSL_CHASSIS3_DEVDISR2_DPMAC3,
+	[WRIOP1_DPMAC4] = FSL_CHASSIS3_DEVDISR2_DPMAC4,
+	[WRIOP1_DPMAC5] = FSL_CHASSIS3_DEVDISR2_DPMAC5,
+	[WRIOP1_DPMAC6] = FSL_CHASSIS3_DEVDISR2_DPMAC6,
+	[WRIOP1_DPMAC7] = FSL_CHASSIS3_DEVDISR2_DPMAC7,
+	[WRIOP1_DPMAC8] = FSL_CHASSIS3_DEVDISR2_DPMAC8,
+	[WRIOP1_DPMAC9] = FSL_CHASSIS3_DEVDISR2_DPMAC9,
+	[WRIOP1_DPMAC10] = FSL_CHASSIS3_DEVDISR2_DPMAC10,
+};
+
+static int is_device_disabled(int dpmac_id)
+{
+	struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+	u32 devdisr2 = in_le32(&gur->devdisr2);
+
+	return dpmac_to_devdisr[dpmac_id] & devdisr2;
+}
+
+void wriop_dpmac_disable(int dpmac_id)
+{
+	struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+
+	setbits_le32(&gur->devdisr2, dpmac_to_devdisr[dpmac_id]);
+}
+
+void wriop_dpmac_enable(int dpmac_id)
+{
+	struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+
+	clrbits_le32(&gur->devdisr2, dpmac_to_devdisr[dpmac_id]);
+}
+
+phy_interface_t wriop_dpmac_enet_if(int dpmac_id, int lane_prtcl)
+{
+	enum srds_prtcl;
+
+	if (is_device_disabled(dpmac_id + 1))
+		return PHY_INTERFACE_MODE_NONE;
+
+	switch (lane_prtcl) {
+	case SGMII1:
+	case SGMII2:
+	case SGMII3:
+	case SGMII7:
+		return PHY_INTERFACE_MODE_SGMII;
+	}
+
+	if (lane_prtcl >= XFI1 && lane_prtcl <= XFI2)
+		return PHY_INTERFACE_MODE_XGMII;
+
+	if (lane_prtcl >= QSGMII_A && lane_prtcl <= QSGMII_B)
+		return PHY_INTERFACE_MODE_QSGMII;
+
+	return PHY_INTERFACE_MODE_NONE;
+}
+
+void wriop_init_dpmac_qsgmii(int sd, int lane_prtcl)
+{
+	switch (lane_prtcl) {
+	case QSGMII_A:
+		wriop_init_dpmac(sd, 3, (int)lane_prtcl);
+		wriop_init_dpmac(sd, 4, (int)lane_prtcl);
+		wriop_init_dpmac(sd, 5, (int)lane_prtcl);
+		wriop_init_dpmac(sd, 6, (int)lane_prtcl);
+		break;
+	case QSGMII_B:
+		wriop_init_dpmac(sd, 7, (int)lane_prtcl);
+		wriop_init_dpmac(sd, 8, (int)lane_prtcl);
+		wriop_init_dpmac(sd, 9, (int)lane_prtcl);
+		wriop_init_dpmac(sd, 10, (int)lane_prtcl);
+		break;
+	}
+}
-- 
1.9.1



More information about the U-Boot mailing list