armv8: ls1028a: Add NXP LS1028A SoC support

Ls1028a SoC is based on Layerscape Chassis Generation 3.2
architecture with features:
 2 ARM v8 Cortex-A72 cores, CCI400, SEC, DDR3L/4, LCD, GPU, TSN
 ENETC, 2 USB 3.0, 2 eSDHC, 2 FlexCAN, 2 SPI, SATA, 8 I2C controllers,
 6 LPUARTs, GPIO, SAI, qDMA, eDMA, GIC, TMU etc.

Signed-off-by: Sudhanshu Gupta <sudhanshu.gupta@nxp.com>
Signed-off-by: Rai Harninder <harninder.rai@nxp.com>
Signed-off-by: Rajesh Bhagat <rajesh.bhagat@nxp.com>
Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
Signed-off-by: Tang Yuantian <andy.tang@nxp.com>
Reviewed-by: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index d37e367..a843c1e 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -20,6 +20,40 @@
 	select SYS_I2C_MXC_I2C2
 	imply PANIC_HANG
 
+config ARCH_LS1028A
+	bool
+	select ARMV8_SET_SMPEN
+	select FSL_LSCH3
+	select NXP_LSCH3_2
+	select SYS_FSL_HAS_CCI400
+	select SYS_FSL_SRDS_1
+	select SYS_HAS_SERDES
+	select SYS_FSL_DDR
+	select SYS_FSL_DDR_LE
+	select SYS_FSL_DDR_VER_50
+	select SYS_FSL_HAS_DDR3
+	select SYS_FSL_HAS_DDR4
+	select SYS_FSL_HAS_SEC
+	select SYS_FSL_SEC_COMPAT_5
+	select SYS_FSL_SEC_LE
+	select FSL_TZASC_1
+	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
+	select SYS_FSL_ERRATUM_A009007
+	select SYS_FSL_ERRATUM_A008514 if !TFABOOT
+	select SYS_FSL_ERRATUM_A009663 if !TFABOOT
+	select SYS_FSL_ERRATUM_A009942 if !TFABOOT
+	imply PANIC_HANG
+
 config ARCH_LS1043A
 	bool
 	select ARMV8_SET_SMPEN
@@ -244,6 +278,7 @@
 	string "PCIe compatible of Kernel DT"
 	depends on PCIE_LAYERSCAPE || PCIE_LAYERSCAPE_GEN4
 	default "fsl,ls1012a-pcie" if ARCH_LS1012A
+	default "fsl,ls1028a-pcie" if ARCH_LS1028A
 	default "fsl,ls1043a-pcie" if ARCH_LS1043A
 	default "fsl,ls1046a-pcie" if ARCH_LS1046A
 	default "fsl,ls2080a-pcie" if ARCH_LS2080A
@@ -343,6 +378,7 @@
 
 config MAX_CPUS
 	int "Maximum number of CPUs permitted for Layerscape"
+	default 2 if ARCH_LS1028A
 	default 4 if ARCH_LS1043A
 	default 4 if ARCH_LS1046A
 	default 16 if ARCH_LS2080A
@@ -377,7 +413,7 @@
 config SYS_CCI400_OFFSET
 	hex "Offset for CCI400 base"
 	depends on SYS_FSL_HAS_CCI400
-	default 0x3090000 if ARCH_LS1088A
+	default 0x3090000 if ARCH_LS1088A || ARCH_LS1028A
 	default 0x180000 if FSL_LSCH2
 	help
 	  Offset for CCI400 base
@@ -446,6 +482,7 @@
 
 config SYS_FSL_PCLK_DIV
 	int "Platform clock divider"
+	default 1 if ARCH_LS1028A
 	default 1 if ARCH_LS1043A
 	default 1 if ARCH_LS1046A
 	default 1 if ARCH_LS1088A
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Makefile b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
index e9bc987..a8d3cf9 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Makefile
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
@@ -48,3 +48,7 @@
 ifneq ($(CONFIG_ARCH_LS1088A),)
 obj-$(CONFIG_SYS_HAS_SERDES) += ls1088a_serdes.o
 endif
+
+ifneq ($(CONFIG_ARCH_LS1028A),)
+obj-$(CONFIG_SYS_HAS_SERDES) += ls1028a_serdes.o
+endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index 9801e64..bbe3c88 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -58,6 +58,7 @@
 	CPU_TYPE_ENTRY(LS1026A, LS1026A, 2),
 	CPU_TYPE_ENTRY(LS2040A, LS2040A, 4),
 	CPU_TYPE_ENTRY(LS1012A, LS1012A, 1),
+	CPU_TYPE_ENTRY(LS1028A, LS1028A, 2),
 	CPU_TYPE_ENTRY(LS1088A, LS1088A, 8),
 	CPU_TYPE_ENTRY(LS1084A, LS1084A, 8),
 	CPU_TYPE_ENTRY(LS1048A, LS1048A, 4),
@@ -246,11 +247,13 @@
 	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	},
+#ifdef CONFIG_SYS_PCIE3_PHYS_ADDR
 	{ CONFIG_SYS_PCIE3_PHYS_ADDR, CONFIG_SYS_PCIE3_PHYS_ADDR,
 	  CONFIG_SYS_PCIE3_PHYS_SIZE,
 	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	},
+#endif
 #ifdef CONFIG_SYS_PCIE4_PHYS_ADDR
 	{ CONFIG_SYS_PCIE4_PHYS_ADDR, CONFIG_SYS_PCIE4_PHYS_ADDR,
 	  CONFIG_SYS_PCIE4_PHYS_SIZE,
@@ -355,11 +358,13 @@
 	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	},
+#ifdef CONFIG_SYS_PCIE3_PHYS_ADDR
 	{ CONFIG_SYS_PCIE3_PHYS_ADDR, CONFIG_SYS_PCIE3_PHYS_ADDR,
 	  CONFIG_SYS_PCIE3_PHYS_SIZE,
 	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	},
+#endif
 	{ CONFIG_SYS_FSL_DRAM_BASE3, CONFIG_SYS_FSL_DRAM_BASE3,
 	  CONFIG_SYS_FSL_DRAM_SIZE3,
 	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
@@ -462,11 +467,13 @@
 				final_map[i].virt = 0x2800000000ULL;
 				final_map[i].size = 0x800000000ULL;
 				break;
+#ifdef CONFIG_SYS_PCIE3_PHYS_ADDR
 			case CONFIG_SYS_PCIE3_PHYS_ADDR:
 				final_map[i].phys = 0x3000000000ULL;
 				final_map[i].virt = 0x3000000000ULL;
 				final_map[i].size = 0x800000000ULL;
 				break;
+#endif
 #ifdef CONFIG_SYS_PCIE4_PHYS_ADDR
 			case CONFIG_SYS_PCIE4_PHYS_ADDR:
 				final_map[i].phys = 0x3800000000ULL;
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
index a0e2621..ad55573 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
+++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
@@ -8,6 +8,7 @@
 	6. LS2088A
 	7. LS2081A
 	8. LX2160A
+	9. LS1028A
 
 LS1043A
 ---------
@@ -328,3 +329,53 @@
 
 2)LX2080A, few difference w.r.t. LX2160A:
        a) Eight 64-bit ARM v8 Cortex-A72 CPUs
+
+
+LS1028A
+--------
+The QorIQ LS1028A processor integrates two 64-bit Arm Cortex-A72 cores with
+a GPU and LCD controller, as well as two TSN-enabled Ethernet controllers and
+a TSNenabled 4-port switch.
+
+The high performance Cortex-A72 cores, performing above 16,000 CoreMarks,
+combined with 2.5 Gbit Ethernet, PCI express Gen 3.0, SATA 3.0, USB 3.0 and
+Octal/Quad SPI interfaces provide capabilities for a number of industrial and
+embedded applications. The device provides excellent integration with the
+new Time-Sensitive Networking standard, and enables a number of
+TSN applications.
+
+The LS1028A SoC includes the following function and features:
+ - Two 64-bit ARM v8 A72 CPUs
+ - Cache Coherent interconnect (CCI-400)
+ - One 32-bit DDR3L/DDR4 SDRAM memory controller with ECC
+ - eDP/Displayport interface
+ - Graphics processing unit
+ - One Configurable x4 SerDes
+ - Ethernet interfaces
+   - Non-switched: One Ethernet MAC supporting 2.5G, 1G, 100M, 10M, one
+   ethernet MAC supporting 1G, 100M, 10M.
+   - Switched: TSN IP to support four 2.5/1G interfaces.
+   - None of the MACs support MACSEC
+   - Support for RGMII, SGMII (and 1000Base-KX), SGMII 2.5x, QSGMII
+   - Support for 10G-SXGMII and 10G-QXGMII.
+   - Energy efficient Ethernet support (802.3az)
+   - IEEE 1588 support
+  - High-speed peripheral interfaces
+    - Two PCIe 3.0 controllers, one supporting x4 operation
+    - One serial ATA (SATA 3.0) controller
+  - Additional peripheral interfaces
+    - Two high-speed USB 2.0/3.0 controllers with integrated PHY each
+      supporting host or device modes
+    - Two Enhanced secure digital host controllers (SD/SDIO/eMMC)
+    - Two Serial peripheral interface (SPI) controllers
+    - Eight I2C controllers
+    - Two UART controllers
+    - Additional six Industrual UARTs (LPUART).
+    - One FlexSPI controller
+    - General Purpose IO (GPIO)
+    - Two CAN-FD interfaces
+    - Eight Flextimers with PWM I/O
+  - Support for hardware virtualization and partitioning enforcement
+  - Layerscape Trust Architecture
+  - Service Processor (SP) provides pre-boot initialization and secure-boot
+    capabilities
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1028a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1028a_serdes.c
new file mode 100644
index 0000000..ef598c4
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1028a_serdes.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+
+struct serdes_config {
+	u32 protocol;
+	u8 lanes[SRDS_MAX_LANES];
+	u8 rcw_lanes[SRDS_MAX_LANES];
+};
+
+static struct serdes_config serdes1_cfg_tbl[] = {
+	/* SerDes 1 */
+	{0xCC5B, {PCIE1, QSGMII_B, PCIE2, PCIE2} },
+	{0xEB99, {SGMII1, SGMII1, PCIE2, SATA1} },
+	{0xCC99, {SGMII1, SGMII1, PCIE2, PCIE2} },
+	{0xBB99, {SGMII1, SGMII1, PCIE2, PCIE1} },
+	{0x9999, {SGMII1, SGMII2, SGMII3, SGMII4} },
+	{0xEBCC, {PCIE1, PCIE1, PCIE2, SATA1} },
+	{0xCCCC, {PCIE1, PCIE1, PCIE2, PCIE2} },
+	{0xDDDD, {PCIE1, PCIE1, PCIE1, PCIE1} },
+	{}
+};
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+	serdes1_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;
+}