Add support for the NXP LS1021A-TSN board

The LS1021A-TSN is a development board built by VVDN/Argonboards in
partnership with NXP.

It features the LS1021A SoC and the first-generation SJA1105T Ethernet
switch for prototyping implementations of a subset of IEEE 802.1 TSN
standards.

Supported boot media: microSD card (via SPL), QSPI flash.

Rev. A of the board uses a Spansion S25FL512S_256K serial flash, which
is 64 MB in size and has an erase sector size of 256KB (therefore,
flashing the RCW would erase part of U-Boot).

Rev. B and C of the board use a Spansion S25FL256S1 serial flash, which
is only 32 MB in size but has an erase sector size of 64KB (therefore
the RCW image can be flashed without erasing U-Boot).

To avoid the problems above, the U-Boot base address has been selected
at 0x100000 (the start of the 5th 256KB erase sector), which works for
all board revisions. Actually 0x40000 would have been enough, but
0x100000 is common for all Layerscape devices.

eTSEC3 is connecting directly to SJA1105 via an RGMII fixed-link, but
SJA1105 is currently not supported by uboot. Therefore, eTSEC3 is
disabled.

Signed-off-by: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
Signed-off-by: Mingkai Hu <mingkai.hu@nxp.com>
Signed-off-by: Jianchao Wang <jianchao.wang@nxp.com>
Signed-off-by: Changming Huang <jerry.huang@nxp.com>
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>

[Vladimir] Code taken from https://github.com/openil/u-boot (which
itself is mostly copied from ls1021a-iot) and adapted with the following
changes:

- Add a008850 errata workaround
- Converted eTSEC, MMC to DM to avoid all build warnings
- Plugged in distro boot feature, including support for extlinux.conf
- Added defconfig for QSPI boot
- Added the board/freescale/ls1021atsn/README.rst for initial setup
- Increased CONFIG_SYS_MONITOR_LEN so that the SPL malloc pool does not
  get overwritten during copying of the u-boot.bin payload from MMC to
  DDR.
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
diff --git a/board/freescale/ls1021atsn/ls1021atsn.c b/board/freescale/ls1021atsn/ls1021atsn.c
new file mode 100644
index 0000000..39e825c
--- /dev/null
+++ b/board/freescale/ls1021atsn/ls1021atsn.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2016-2019 NXP Semiconductors
+ */
+#include <common.h>
+#include <asm/arch-ls102xa/ls102xa_soc.h>
+#include <asm/arch/ls102xa_devdis.h>
+#include <asm/arch/immap_ls102xa.h>
+#include <asm/arch/ls102xa_soc.h>
+#include <asm/arch/fsl_serdes.h>
+#include "../common/sleep.h"
+#include <fsl_validate.h>
+#include <fsl_immap.h>
+#include <fsl_csu.h>
+#include <netdev.h>
+#include <spl.h>
+#ifdef CONFIG_U_QE
+#include <fsl_qe.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void ddrmc_init(void)
+{
+#if (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
+	struct ccsr_ddr *ddr = (struct ccsr_ddr *)CONFIG_SYS_FSL_DDR_ADDR;
+	u32 temp_sdram_cfg, tmp;
+
+	out_be32(&ddr->sdram_cfg, DDR_SDRAM_CFG);
+
+	out_be32(&ddr->cs0_bnds, DDR_CS0_BNDS);
+	out_be32(&ddr->cs0_config, DDR_CS0_CONFIG);
+
+	out_be32(&ddr->timing_cfg_0, DDR_TIMING_CFG_0);
+	out_be32(&ddr->timing_cfg_1, DDR_TIMING_CFG_1);
+	out_be32(&ddr->timing_cfg_2, DDR_TIMING_CFG_2);
+	out_be32(&ddr->timing_cfg_3, DDR_TIMING_CFG_3);
+	out_be32(&ddr->timing_cfg_4, DDR_TIMING_CFG_4);
+	out_be32(&ddr->timing_cfg_5, DDR_TIMING_CFG_5);
+
+#ifdef CONFIG_DEEP_SLEEP
+	if (is_warm_boot()) {
+		out_be32(&ddr->sdram_cfg_2,
+			 DDR_SDRAM_CFG_2 & ~SDRAM_CFG2_D_INIT);
+		out_be32(&ddr->init_addr, CONFIG_SYS_SDRAM_BASE);
+		out_be32(&ddr->init_ext_addr, (1 << 31));
+
+		/* DRAM VRef will not be trained */
+		out_be32(&ddr->ddr_cdr2,
+			 DDR_DDR_CDR2 & ~DDR_CDR2_VREF_TRAIN_EN);
+	} else
+#endif
+	{
+		out_be32(&ddr->sdram_cfg_2, DDR_SDRAM_CFG_2);
+		out_be32(&ddr->ddr_cdr2, DDR_DDR_CDR2);
+	}
+
+	out_be32(&ddr->sdram_mode, DDR_SDRAM_MODE);
+	out_be32(&ddr->sdram_mode_2, DDR_SDRAM_MODE_2);
+
+	out_be32(&ddr->sdram_interval, DDR_SDRAM_INTERVAL);
+
+	out_be32(&ddr->ddr_wrlvl_cntl, DDR_DDR_WRLVL_CNTL);
+
+	out_be32(&ddr->ddr_wrlvl_cntl_2, DDR_DDR_WRLVL_CNTL_2);
+	out_be32(&ddr->ddr_wrlvl_cntl_3, DDR_DDR_WRLVL_CNTL_3);
+
+	out_be32(&ddr->ddr_cdr1, DDR_DDR_CDR1);
+
+	out_be32(&ddr->sdram_clk_cntl, DDR_SDRAM_CLK_CNTL);
+	out_be32(&ddr->ddr_zq_cntl, DDR_DDR_ZQ_CNTL);
+
+	out_be32(&ddr->cs0_config_2, DDR_CS0_CONFIG_2);
+
+	/* DDR erratum A-009942 */
+	tmp = in_be32(&ddr->debug[28]);
+	out_be32(&ddr->debug[28], tmp | 0x0070006f);
+
+	udelay(1);
+
+#ifdef CONFIG_DEEP_SLEEP
+	if (is_warm_boot()) {
+		/* enter self-refresh */
+		temp_sdram_cfg = in_be32(&ddr->sdram_cfg_2);
+		temp_sdram_cfg |= SDRAM_CFG2_FRC_SR;
+		out_be32(&ddr->sdram_cfg_2, temp_sdram_cfg);
+
+		temp_sdram_cfg = (DDR_SDRAM_CFG_MEM_EN | SDRAM_CFG_BI);
+	} else
+#endif
+		temp_sdram_cfg = (DDR_SDRAM_CFG_MEM_EN & ~SDRAM_CFG_BI);
+
+	out_be32(&ddr->sdram_cfg, DDR_SDRAM_CFG | temp_sdram_cfg);
+
+#ifdef CONFIG_DEEP_SLEEP
+	if (is_warm_boot()) {
+		/* exit self-refresh */
+		temp_sdram_cfg = in_be32(&ddr->sdram_cfg_2);
+		temp_sdram_cfg &= ~SDRAM_CFG2_FRC_SR;
+		out_be32(&ddr->sdram_cfg_2, temp_sdram_cfg);
+	}
+#endif
+#endif /* !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) */
+}
+
+int dram_init(void)
+{
+	ddrmc_init();
+
+	erratum_a008850_post();
+
+	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+
+#if defined(CONFIG_DEEP_SLEEP) && !defined(CONFIG_SPL_BUILD)
+	fsl_dp_resume();
+#endif
+
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	return pci_eth_init(bis);
+}
+
+int board_early_init_f(void)
+{
+	struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
+
+#ifdef CONFIG_TSEC_ENET
+	/*
+	 * Clear BD & FR bits for big endian BD's and frame data (aka set
+	 * correct eTSEC endianness). This is crucial in ensuring that it does
+	 * not report Data Parity Errors in its RX/TX FIFOs when attempting to
+	 * send traffic.
+	 */
+	clrbits_be32(&scfg->etsecdmamcr, SCFG_ETSECDMAMCR_LE_BD_FR);
+	/* EC3_GTX_CLK125 (of enet2) used for all RGMII interfaces */
+	out_be32(&scfg->etsecmcr, SCFG_ETSECCMCR_GE2_CLK125);
+#endif
+
+	arch_soc_init();
+
+#if defined(CONFIG_DEEP_SLEEP)
+	if (is_warm_boot()) {
+		timer_init();
+		dram_init();
+	}
+#endif
+
+	return 0;
+}
+
+#ifdef CONFIG_SPL_BUILD
+void board_init_f(ulong dummy)
+{
+	void (*second_uboot)(void);
+
+	/* Clear the BSS */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	get_clocks();
+
+#if defined(CONFIG_DEEP_SLEEP)
+	if (is_warm_boot())
+		fsl_dp_disable_console();
+#endif
+
+	preloader_console_init();
+
+	dram_init();
+
+	/* Allow OCRAM access permission as R/W */
+#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
+	enable_layerscape_ns_access();
+	enable_layerscape_ns_access();
+#endif
+
+	/*
+	 * if it is woken up from deep sleep, then jump to second
+	 * stage U-Boot and continue executing without recopying
+	 * it from SD since it has already been reserved in memory
+	 * in last boot.
+	 */
+	if (is_warm_boot()) {
+		second_uboot = (void (*)(void))CONFIG_SYS_TEXT_BASE;
+		second_uboot();
+	}
+
+	board_init_r(NULL, 0);
+}
+#endif
+
+int board_init(void)
+{
+#ifndef CONFIG_SYS_FSL_NO_SERDES
+	fsl_serdes_init();
+#endif
+	ls102xa_smmu_stream_id_init();
+
+#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
+	enable_layerscape_ns_access();
+#endif
+
+#ifdef CONFIG_U_QE
+	u_qe_init();
+#endif
+
+	return 0;
+}
+
+#if defined(CONFIG_SPL_BUILD)
+void spl_board_init(void)
+{
+	ls102xa_smmu_stream_id_init();
+}
+#endif
+
+#ifdef CONFIG_BOARD_LATE_INIT
+int board_late_init(void)
+{
+#ifdef CONFIG_CHAIN_OF_TRUST
+	fsl_setenv_chain_of_trust();
+#endif
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_MISC_INIT_R)
+int misc_init_r(void)
+{
+#ifdef CONFIG_FSL_DEVICE_DISABLE
+	device_disable(devdis_tbl, ARRAY_SIZE(devdis_tbl));
+#endif
+
+#ifdef CONFIG_FSL_CAAM
+	return sec_init();
+#endif
+}
+#endif
+
+#if defined(CONFIG_DEEP_SLEEP)
+void board_sleep_prepare(void)
+{
+#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
+	enable_layerscape_ns_access();
+#endif
+}
+#endif
+
+int ft_board_setup(void *blob, bd_t *bd)
+{
+	ft_cpu_setup(blob, bd);
+
+#ifdef CONFIG_PCI
+	ft_pci_setup(blob, bd);
+#endif
+
+	return 0;
+}