armv8: lx2160a: Add LX2160A SoC Support

LX2160A Soc is based on Layerscape Chassis Generation 3.2
architecture with features:
 16 ARM v8 Cortex-A72 cores in 8 cluster, CCN508, SEC,
 2 64-bit DDR4 memory controller, RGMII, 8 I2C controllers,
 3 serdes modules, USB 3.0, SATA, 4 PL011 SBSA UARTs,
 4 TZASC instances, etc.

SoC personalites:
LX2120A is SoC with Twelve 64-bit ARM v8 Cortex-A72 CPUs
LX2080A is SoC with Eight 64-bit ARM v8 Cortex-A72 CPUs

Signed-off-by: Bao Xiaowei <xiaowei.bao@nxp.com>
Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
Signed-off-by: Sriram Dash <sriram.dash@nxp.com>
Signed-off-by: Priyanka Jain <priyanka.jain@nxp.com>
Reviewed-by: York Sun <york.sun@nxp.com>
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index 650ac94..2b086da 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -170,6 +170,42 @@
 	imply DISTRO_DEFAULTS
 	imply PANIC_HANG
 
+config ARCH_LX2160A
+	bool
+	select ARMV8_SET_SMPEN
+	select FSL_LSCH3
+	select NXP_LSCH3_2
+	select SYS_HAS_SERDES
+	select SYS_FSL_SRDS_1
+	select SYS_FSL_SRDS_2
+	select SYS_NXP_SRDS_3
+	select SYS_FSL_DDR
+	select SYS_FSL_DDR_LE
+	select SYS_FSL_DDR_VER_50
+	select SYS_FSL_EC1
+	select SYS_FSL_EC2
+	select SYS_FSL_HAS_RGMII
+	select SYS_FSL_HAS_SEC
+	select SYS_FSL_HAS_CCN508
+	select SYS_FSL_HAS_DDR4
+	select SYS_FSL_SEC_COMPAT_5
+	select SYS_FSL_SEC_LE
+	select ARCH_EARLY_INIT_R
+	select BOARD_EARLY_INIT_F
+	select SYS_I2C_MXC
+	select SYS_I2C_MXC_I2C1
+	select SYS_I2C_MXC_I2C2
+	select SYS_I2C_MXC_I2C3
+	select SYS_I2C_MXC_I2C4
+	select SYS_I2C_MXC_I2C5
+	select SYS_I2C_MXC_I2C6
+	select SYS_I2C_MXC_I2C7
+	select SYS_I2C_MXC_I2C8
+	imply DISTRO_DEFAULTS
+	imply PANIC_HANG
+	imply SCSI
+	imply SCSI_AHCI
+
 config FSL_LSCH2
 	bool
 	select SYS_FSL_HAS_CCI400
@@ -185,7 +221,7 @@
 
 config FSL_MC_ENET
 	bool "Management Complex network"
-	depends on ARCH_LS2080A || ARCH_LS1088A
+	depends on ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A
 	default y
 	select RESV_RAM
 	help
@@ -202,6 +238,7 @@
 	default "fsl,ls1046a-pcie" if ARCH_LS1046A
 	default "fsl,ls2080a-pcie" if ARCH_LS2080A
 	default "fsl,ls1088a-pcie" if ARCH_LS1088A
+	default "fsl,lx2160a-pcie" if ARCH_LX2160A
 	help
 	  This compatible is used to find pci controller node in Kernel DT
 	  to complete fixup.
@@ -300,6 +337,7 @@
 	default 4 if ARCH_LS1046A
 	default 16 if ARCH_LS2080A
 	default 8 if ARCH_LS1088A
+	default 16 if ARCH_LX2160A
 	default 1
 	help
 	  Set this number to the maximum number of possible CPUs in the SoC.
@@ -342,6 +380,9 @@
 config SYS_FSL_HAS_CCN504
 	bool
 
+config SYS_FSL_HAS_CCN508
+	bool
+
 config SYS_FSL_HAS_DP_DDR
 	bool
 
@@ -404,6 +445,7 @@
 config SYS_FSL_DUART_CLK_DIV
 	int "DUART clock divider"
 	default 1 if ARCH_LS1043A
+	default 4 if ARCH_LX2160A
 	default 2
 	help
 	  This is the divider that is used to derive DUART clock from Platform
@@ -464,13 +506,15 @@
 config SYS_FSL_EC1
 	bool
 	help
-	  Ethernet controller 1, this is connected to MAC3.
+	  Ethernet controller 1, this is connected to
+	  MAC17 for LX2160A or to MAC3 for other SoCs
 	  Provides DPAA2 capabilities
 
 config SYS_FSL_EC2
 	bool
 	help
-	  Ethernet controller 2, this is connected to MAC4.
+	  Ethernet controller 2, this is connected to
+	  MAC18 for LX2160A or to MAC4 for other SoCs
 	  Provides DPAA2 capabilities
 
 config SYS_FSL_ERRATUM_A008336
@@ -506,7 +550,7 @@
 config SYS_MC_RSV_MEM_ALIGN
 	hex "Management Complex reserved memory alignment"
 	depends on RESV_RAM
-	default 0x20000000 if ARCH_LS2080A || ARCH_LS1088A
+	default 0x20000000 if ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A
 	help
 	  Reserved memory needs to be aligned for MC to use. Default value
 	  is 512MB.
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Makefile b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
index 91fdbad..e9bc987 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Makefile
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0+
-#
+# Copyright 2016-2018 NXP
 # Copyright 2014-2015, Freescale Semiconductor
 
 obj-y += cpu.o
@@ -22,6 +22,10 @@
 endif
 endif
 
+ifneq ($(CONFIG_ARCH_LX2160A),)
+obj-$(CONFIG_SYS_HAS_SERDES) += lx2160a_serdes.o
+endif
+
 ifneq ($(CONFIG_ARCH_LS2080A),)
 obj-$(CONFIG_SYS_HAS_SERDES) += ls2080a_serdes.o
 endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index 5c62bcc..1fc025b 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -60,6 +60,9 @@
 	CPU_TYPE_ENTRY(LS1084A, LS1084A, 8),
 	CPU_TYPE_ENTRY(LS1048A, LS1048A, 4),
 	CPU_TYPE_ENTRY(LS1044A, LS1044A, 4),
+	CPU_TYPE_ENTRY(LX2160A, LX2160A, 16),
+	CPU_TYPE_ENTRY(LX2120A, LX2120A, 12),
+	CPU_TYPE_ENTRY(LX2080A, LX2080A, 8),
 };
 
 #define EARLY_PGTABLE_SIZE 0x5000
@@ -246,7 +249,7 @@
 	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	},
-#ifdef CONFIG_ARCH_LS2080A
+#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LX2160A)
 	{ CONFIG_SYS_PCIE4_PHYS_ADDR, CONFIG_SYS_PCIE4_PHYS_ADDR,
 	  CONFIG_SYS_PCIE4_PHYS_SIZE,
 	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
@@ -366,6 +369,10 @@
 	for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++)
 		if ((cpu_type_list[i].soc_ver & SVR_WO_E) == ver) {
 			strcpy(name, cpu_type_list[i].name);
+#ifdef CONFIG_ARCH_LX2160A
+			if (IS_C_PROCESSOR(svr))
+				strcat(name, "C");
+#endif
 
 			if (IS_E_PROCESSOR(svr))
 				strcat(name, "E");
@@ -1164,10 +1171,16 @@
 {
 	u32 val;
 
+#ifdef CONFIG_ARCH_LX2160A
+	val = in_le32(rstcr);
+	val |= 0x01;
+	out_le32(rstcr, val);
+#else
 	/* Raise RESET_REQ_B */
 	val = scfg_in32(rstcr);
 	val |= 0x02;
 	scfg_out32(rstcr, val);
+#endif
 }
 
 #ifdef CONFIG_EFI_LOADER
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
index 276ab90..a0e2621 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
+++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
@@ -7,6 +7,7 @@
 	5. LS1046A
 	6. LS2088A
 	7. LS2081A
+	8. LX2160A
 
 LS1043A
 ---------
@@ -271,3 +272,59 @@
 It has one more similar SoC personality
 1)LS2041A, few difference w.r.t. LS2081A:
        a) Four 64-bit ARM v8 Cortex-A72 CPUs
+
+LX2160A
+--------
+The QorIQ LX2160A processor is built in the 16FFC process on
+the Layerscape architecture combining sixteen ARM A72 processor
+cores with advanced, high-performance datapath acceleration and
+network, peripheral interfaces required for networking, wireless
+infrastructure, storage, and general-purpose embedded applications.
+
+LX2160A is compliant with the Layerscape Chassis Generation 3.2.
+
+The LX2160A SoC includes the following function and features:
+  Sixteen 32-bit / 64-bit ARM v8 A72 CPUs
+  Cache Coherent Interconnect Fabric (CCN508 aka “Eliot”)
+  Two 64-bit 3.2GT/s DDR4 SDRAM memory controllers with ECC.
+  Data path acceleration architecture (DPAA2)
+  24 Serdes lanes at up to 25 GHz
+  Ethernet interfaces
+  Single WRIOP tile supporting 130Gbps using 18 MACs
+  Support for 10G-SXGMII (aka USXGMII).
+  Support for SGMII (and 1000Base-KX)
+  Support for XFI (and 10GBase-KR)
+  Support for CAUI4 (100G); CAUI2 (50G) and 25G-AUI(25G).
+  Support for XLAUI (and 40GBase-KR4) for 40G.
+  Support for two RGMII parallel interfaces.
+  Energy efficient Ethernet support (802.3az)
+  IEEE 1588 support.
+  High-speed peripheral interfaces
+	Two PCIe Gen 4.0 8-lane controllers supporting SR-IOV,
+	Four PCIe Gen 4.0 4-lane controllers.
+	Four serial ATA (SATA 3.0) controllers.
+	Two USB 3.0 controllers with integrated PHY
+	Two Enhanced secure digital host controllers
+	Two Controller Area Network (CAN) modules
+	Flexible Serial peripheral interface (FlexSPI) controller.
+	Three Serial peripheral interface (SPI) controllers.
+	Eight I2C Controllers.
+	Four PL011 UARTs supporting two 4-pin UART ports or four 2-pin UART ports.
+	General Purpose IO (GPIO)
+  Support for hardware virtualization and partitioning (ARM MMU-500)
+  Support for GIC (ARM GIC-500)
+  QorIQ platform Trust Architecture 3.0
+  One Secure WatchDog timer and one Non-Secure Watchdog timer.
+  ARM Generic Timer
+  Two Flextimers
+  Debug supporting run control, data acquisition, high-speed trace,
+  performance/event monitoring
+  Thermal Monitor Unit (TMU) with +/- 2C accuracy
+  Support for Voltage ID (VID) for yield improvement
+
+LX2160A SoC has 2 more similar SoC personalities
+1)LX2120A, few difference w.r.t. LX2160A:
+       a) Twelve 64-bit ARM v8 Cortex-A72 CPUs
+
+2)LX2080A, few difference w.r.t. LX2160A:
+       a) Eight 64-bit ARM v8 Cortex-A72 CPUs
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 bb50e3d..ab1be3f 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
@@ -22,9 +22,18 @@
 #endif
 
 #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
+#ifdef CONFIG_ARCH_LX2160A
+int xfi_dpmac[XFI14 + 1];
+int sgmii_dpmac[SGMII18 + 1];
+int a25gaui_dpmac[_25GE10 + 1];
+int xlaui_dpmac[_40GE2 + 1];
+int caui2_dpmac[_50GE2 + 1];
+int caui4_dpmac[_100GE2 + 1];
+#else
 int xfi_dpmac[XFI8 + 1];
 int sgmii_dpmac[SGMII16 + 1];
 #endif
+#endif
 
 __weak void wriop_init_dpmac_qsgmii(int sd, int lane_prtcl)
 {
@@ -146,6 +155,32 @@
 		else {
 			serdes_prtcl_map[lane_prtcl] = 1;
 #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
+#ifdef CONFIG_ARCH_LX2160A
+			if (lane_prtcl >= XFI1 && lane_prtcl <= XFI14)
+				wriop_init_dpmac(sd, xfi_dpmac[lane_prtcl],
+						 (int)lane_prtcl);
+
+			if (lane_prtcl >= SGMII1 && lane_prtcl <= SGMII18)
+				wriop_init_dpmac(sd, sgmii_dpmac[lane_prtcl],
+						 (int)lane_prtcl);
+
+			if (lane_prtcl >= _25GE1 && lane_prtcl <= _25GE10)
+				wriop_init_dpmac(sd, a25gaui_dpmac[lane_prtcl],
+						 (int)lane_prtcl);
+
+			if (lane_prtcl >= _40GE1 && lane_prtcl <= _40GE2)
+				wriop_init_dpmac(sd, xlaui_dpmac[lane_prtcl],
+						 (int)lane_prtcl);
+
+			if (lane_prtcl >= _50GE1 && lane_prtcl <= _50GE2)
+				wriop_init_dpmac(sd, caui2_dpmac[lane_prtcl],
+						 (int)lane_prtcl);
+
+			if (lane_prtcl >= _100GE1 && lane_prtcl <= _100GE2)
+				wriop_init_dpmac(sd, caui4_dpmac[lane_prtcl],
+						 (int)lane_prtcl);
+
+#else
 			switch (lane_prtcl) {
 			case QSGMII_A:
 			case QSGMII_B:
@@ -167,6 +202,7 @@
 				break;
 			}
 #endif
+#endif
 		}
 	}
 
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
index cbc9112..6721a57 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
+++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
@@ -354,7 +354,7 @@
 	ret
 #endif
 
-#ifdef CONFIG_SYS_FSL_HAS_CCN504
+#if defined(CONFIG_SYS_FSL_HAS_CCN504) || defined(CONFIG_SYS_FSL_HAS_CCN508)
 hnf_pstate_poll:
 	/* x0 has the desired status, return 0 for success, 1 for timeout
 	 * clobber x1, x2, x3, x4, x6, x7
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c
new file mode 100644
index 0000000..a04a370
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+
+struct serdes_config {
+	u8 protocol;
+	u8 lanes[SRDS_MAX_LANES];
+};
+
+static struct serdes_config serdes1_cfg_tbl[] = {
+	/* SerDes 1 */
+	{0x01, {PCIE2, PCIE2, PCIE2, PCIE2, PCIE1, PCIE1, PCIE1, PCIE1 } },
+	{0x02, {PCIE2, PCIE2, PCIE2, PCIE2, SGMII6, SGMII5, SGMII4, SGMII3 } },
+	{0x03, {PCIE2, PCIE2, PCIE2, PCIE2, XFI6, XFI5, XFI4,
+		XFI3 } },
+	{0x04, {SGMII10, SGMII9, SGMII8, SGMII7, SGMII6, SGMII5, SGMII4,
+		SGMII3 } },
+	{0x05, {XFI10, XFI9, XFI8, XFI7, PCIE1, PCIE1, PCIE1,
+		PCIE1 } },
+	{0x06, {SGMII10, SGMII9, SGMII8, SGMII7, SGMII6, SGMII5, XFI4,
+		XFI3 } },
+	{0x07, {SGMII10, SGMII9, SGMII8, SGMII7, XFI6, XFI5, XFI4,
+		XFI3 } },
+	{0x08, {XFI10, XFI9, XFI8, XFI7, XFI6, XFI5, XFI4, XFI3 } },
+	{0x09, {SGMII10, SGMII9, SGMII8, PCIE2, SGMII6, SGMII5, SGMII4,
+		PCIE1 } },
+	{0x0A, {XFI10, XFI9, XFI8, PCIE2, XFI6, XFI5, XFI4, PCIE1 } },
+	{0x0B, {SGMII10, SGMII9, PCIE2, PCIE2, SGMII6, SGMII5, PCIE1, PCIE1 } },
+	{0x0C, {SGMII10, SGMII9, PCIE2, PCIE2, PCIE1, PCIE1, PCIE1, PCIE1 } },
+	{0x0D, {_100GE2, _100GE2, _100GE2, _100GE2, _100GE1, _100GE1, _100GE1,
+		_100GE1 } },
+	{0x0E, {PCIE2, PCIE2, PCIE2, PCIE2, _100GE1, _100GE1, _100GE1,
+		_100GE1 } },
+	{0x0F, {PCIE2, PCIE2, PCIE2, PCIE2, _50GE2, _50GE2, _50GE1, _50GE1 } },
+	{0x10, {PCIE2, PCIE2, PCIE2, PCIE2, _25GE6, _25GE5, _50GE1, _50GE1 } },
+	{0x11, {PCIE2, PCIE2, PCIE2, PCIE2, _25GE6, _25GE5, _25GE4, _25GE3 } },
+	{0x12, {XFI10, XFI9, XFI8, XFI7, _25GE6, _25GE5, XFI4,
+		XFI3 } },
+	{0x13, {_40GE2, _40GE2, _40GE2, _40GE2, _25GE6, _25GE5, XFI4, XFI3 } },
+	{0x14, {_40GE2, _40GE2, _40GE2, _40GE2, _40GE1, _40GE1, _40GE1,
+		_40GE1 } },
+	{0x15, {_25GE10, _25GE9, PCIE2, PCIE2, _25GE6, _25GE5, _25GE4,
+		_25GE3 } },
+	{0x16, {XFI10, XFI9, PCIE2, PCIE2, XFI6, XFI5, XFI4, XFI3 } },
+	{}
+};
+
+static struct serdes_config serdes2_cfg_tbl[] = {
+	/* SerDes 2 */
+	{0x01, {PCIE3, PCIE3, SATA1, SATA2, PCIE4, PCIE4, PCIE4, PCIE4 } },
+	{0x02, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } },
+	{0x03, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } },
+	{0x04, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } },
+	{0x05, {PCIE3, PCIE3, PCIE3, PCIE3, SATA3, SATA4, SATA1, SATA2 } },
+	{0x06, {PCIE3, PCIE3, PCIE3, PCIE3, SGMII15, SGMII16, XFI13,
+		XFI14 } },
+	{0x07, {PCIE3, SGMII12, SGMII17, SGMII18, PCIE4, SGMII16, XFI13,
+		XFI14 } },
+	{0x08, {NONE, NONE, SATA1, SATA2, SATA3, SATA4, XFI13, XFI14 } },
+	{0x09, {SGMII11, SGMII12, SGMII17, SGMII18, SGMII15, SGMII16, SGMII13,
+		SGMII14} },
+	{0x0A, {SGMII11, SGMII12, SGMII17, SGMII18, PCIE4, PCIE4, PCIE4,
+		PCIE4 } },
+	{0x0B, {PCIE3, SGMII12, SGMII17, SGMII18, PCIE4, SGMII16, SGMII13,
+		SGMII14 } },
+	{0x0C, {SGMII11, SGMII12, SGMII17, SGMII18, PCIE4, PCIE4, SATA1,
+		SATA2 } },
+	{0x0D, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SGMII13, SGMII14 } },
+	{0x0E, {PCIE3, PCIE3, SGMII17, SGMII18, PCIE4, PCIE4, SGMII13,
+		SGMII14 } },
+	{}
+};
+
+static struct serdes_config serdes3_cfg_tbl[] = {
+	/* SerDes 3 */
+	{0x02, {PCIE5, PCIE5, PCIE5, PCIE5, PCIE5, PCIE5, PCIE5, PCIE5 } },
+	{0x03, {PCIE5, PCIE5, PCIE5, PCIE5, PCIE6, PCIE6, PCIE6, PCIE6 } },
+	{}
+};
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+	serdes1_cfg_tbl,
+	serdes2_cfg_tbl,
+	serdes3_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;
+}