armv8: ls1046aqds: Add LS1046AQDS board support
LS1046AQDS Specification:
-------------------------
Memory subsystem:
* 8GByte DDR4 SDRAM (64bit bus)
* 128 Mbyte NOR flash single-chip memory
* 512 Mbyte NAND flash
* 64 Mbyte high-speed SPI flash
* SD connector to interface with the SD memory card
Ethernet:
* Two XFI 10G ports
* Two SGMII ports
* Two RGMII ports
PCIe: supports Gen 1 and Gen 2
SATA 3.0: one SATA 3.0 port
USB 3.0: two micro AB connector and one type A connector
UART: supports two UARTs up to 115200 bps for console
Signed-off-by: Shaohui Xie <Shaohui.Xie@nxp.com>
Signed-off-by: Mingkai Hu <mingkai.hu@nxp.com>
Signed-off-by: Gong Qianyu <Qianyu.Gong@nxp.com>
Reviewed-by: York Sun <york.sun@nxp.com>
diff --git a/board/freescale/common/vid.c b/board/freescale/common/vid.c
index 2f29795..1a50304 100644
--- a/board/freescale/common/vid.c
+++ b/board/freescale/common/vid.c
@@ -8,7 +8,7 @@
#include <command.h>
#include <i2c.h>
#include <asm/io.h>
-#ifdef CONFIG_LS1043A
+#ifdef CONFIG_FSL_LSCH2
#include <asm/arch/immap_lsch2.h>
#elif defined(CONFIG_FSL_LSCH3)
#include <asm/arch/immap_lsch3.h>
@@ -247,7 +247,7 @@
* SoC before converting into an IR VID value
*/
vdd += board_vdd_drop_compensation();
-#ifdef CONFIG_LS1043A
+#ifdef CONFIG_FSL_LSCH2
vid = DIV_ROUND_UP(vdd - 265, 5);
#else
vid = DIV_ROUND_UP(vdd - 245, 5);
@@ -287,7 +287,7 @@
int adjust_vdd(ulong vdd_override)
{
int re_enable = disable_interrupts();
-#if defined(CONFIG_LS1043A) || defined(CONFIG_FSL_LSCH3)
+#if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3)
struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
#else
ccsr_gur_t __iomem *gur =
@@ -386,7 +386,7 @@
* | T | | | | |
* ------------------------------------------------------
*/
-#ifdef CONFIG_LS1043A
+#ifdef CONFIG_FSL_LSCH2
vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_ALTVID_SHIFT) &
FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK;
if ((vid == 0) || (vid == FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK)) {
diff --git a/board/freescale/ls1046aqds/Kconfig b/board/freescale/ls1046aqds/Kconfig
new file mode 100644
index 0000000..723f4ba
--- /dev/null
+++ b/board/freescale/ls1046aqds/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_LS1046AQDS
+
+config SYS_BOARD
+ default "ls1046aqds"
+
+config SYS_VENDOR
+ default "freescale"
+
+config SYS_SOC
+ default "fsl-layerscape"
+
+config SYS_CONFIG_NAME
+ default "ls1046aqds"
+
+endif
diff --git a/board/freescale/ls1046aqds/MAINTAINERS b/board/freescale/ls1046aqds/MAINTAINERS
new file mode 100644
index 0000000..b4549ae
--- /dev/null
+++ b/board/freescale/ls1046aqds/MAINTAINERS
@@ -0,0 +1,10 @@
+LS1046AQDS BOARD
+M: Mingkai Hu <Mingkai.Hu@nxp.com>
+S: Maintained
+F: board/freescale/ls1046aqds/
+F: include/configs/ls1046aqds.h
+F: configs/ls1046aqds_defconfig
+F: configs/ls1046aqds_nand_defconfig
+F: configs/ls1046aqds_sdcard_ifc_defconfig
+F: configs/ls1046aqds_sdcard_qspi_defconfig
+F: configs/ls1046aqds_qspi_defconfig
diff --git a/board/freescale/ls1046aqds/Makefile b/board/freescale/ls1046aqds/Makefile
new file mode 100644
index 0000000..df6e546
--- /dev/null
+++ b/board/freescale/ls1046aqds/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright 2016 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += ddr.o
+obj-y += eth.o
+obj-y += ls1046aqds.o
diff --git a/board/freescale/ls1046aqds/README b/board/freescale/ls1046aqds/README
new file mode 100644
index 0000000..b8fa326
--- /dev/null
+++ b/board/freescale/ls1046aqds/README
@@ -0,0 +1,70 @@
+Overview
+--------
+The LS1046A Development System (QDS) is a high-performance computing,
+evaluation, and development platform that supports the QorIQ LS1046A
+LayerScape Architecture processor. The LS1046AQDS provides SW development
+platform for the Freescale LS1046A processor series, with a complete
+debugging environment.
+
+LS1046A SoC Overview
+--------------------
+Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS1046A
+SoC overview.
+
+ LS1046AQDS board Overview
+ -----------------------
+ - SERDES Connections, 8 lanes supporting:
+ - PCI Express - 3.0
+ - SGMII, SGMII 2.5
+ - QSGMII
+ - SATA 3.0
+ - XFI
+ - DDR Controller
+ - 8GB 64bits DDR4 SDRAM. Support rates of up to 2133MT/s
+ -IFC/Local Bus
+ - One in-socket 128 MB NOR flash 16-bit data bus
+ - One 512 MB NAND flash with ECC support
+ - PromJet Port
+ - FPGA connection
+ - USB 3.0
+ - Three high speed USB 3.0 ports
+ - First USB 3.0 port configured as Host with Type-A connector
+ - The other two USB 3.0 ports configured as OTG with micro-AB connector
+ - SDHC port connects directly to an adapter card slot, featuring:
+ - Optional clock feedback paths, and optional high-speed voltage translation assistance
+ - SD slots for SD, SDHC (1x, 4x, 8x), and/or MMC
+ - eMMC memory devices
+ - DSPI: Onboard support for three SPI flash memory devices
+ - 4 I2C controllers
+ - One SATA onboard connectors
+ - UART
+ - Two 4-pin serial ports at up to 115.2 Kbit/s
+ - Two DB9 D-Type connectors supporting one Serial port each
+ - ARM JTAG support
+
+Memory map from core's view
+----------------------------
+Start Address End Address Description Size
+0x00_0000_0000 - 0x00_000F_FFFF Secure Boot ROM 1MB
+0x00_0100_0000 - 0x00_0FFF_FFFF CCSRBAR 240MB
+0x00_1000_0000 - 0x00_1000_FFFF OCRAM0 64KB
+0x00_1001_0000 - 0x00_1001_FFFF OCRAM1 64KB
+0x00_2000_0000 - 0x00_20FF_FFFF DCSR 16MB
+0x00_6000_0000 - 0x00_67FF_FFFF IFC - NOR Flash 128MB
+0x00_7E80_0000 - 0x00_7E80_FFFF IFC - NAND Flash 64KB
+0x00_7FB0_0000 - 0x00_7FB0_0FFF IFC - FPGA 4KB
+0x00_8000_0000 - 0x00_FFFF_FFFF DRAM1 2GB
+0x05_0000_0000 - 0x05_07FF_FFFF QMAN S/W Portal 128M
+0x05_0800_0000 - 0x05_0FFF_FFFF BMAN S/W Portal 128M
+0x08_8000_0000 - 0x09_FFFF_FFFF DRAM2 6GB
+0x40_0000_0000 - 0x47_FFFF_FFFF PCI Express1 32G
+0x48_0000_0000 - 0x4F_FFFF_FFFF PCI Express2 32G
+0x50_0000_0000 - 0x57_FFFF_FFFF PCI Express3 32G
+
+Booting Options
+---------------
+a) Promjet Boot
+b) NOR boot
+c) NAND boot
+d) SD boot
+e) QSPI boot
diff --git a/board/freescale/ls1046aqds/ddr.c b/board/freescale/ls1046aqds/ddr.c
new file mode 100644
index 0000000..d813965
--- /dev/null
+++ b/board/freescale/ls1046aqds/ddr.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <fsl_ddr_sdram.h>
+#include <fsl_ddr_dimm_params.h>
+#ifdef CONFIG_FSL_DEEP_SLEEP
+#include <fsl_sleep.h>
+#endif
+#include "ddr.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void fsl_ddr_board_options(memctl_options_t *popts,
+ dimm_params_t *pdimm,
+ unsigned int ctrl_num)
+{
+ const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
+ ulong ddr_freq;
+
+ if (ctrl_num > 3) {
+ printf("Not supported controller number %d\n", ctrl_num);
+ return;
+ }
+ if (!pdimm->n_ranks)
+ return;
+
+ pbsp = udimms[0];
+
+ /* Get clk_adjust, wrlvl_start, wrlvl_ctl, according to the board ddr
+ * freqency and n_banks specified in board_specific_parameters table.
+ */
+ ddr_freq = get_ddr_freq(0) / 1000000;
+ while (pbsp->datarate_mhz_high) {
+ if (pbsp->n_ranks == pdimm->n_ranks) {
+ if (ddr_freq <= pbsp->datarate_mhz_high) {
+ popts->clk_adjust = pbsp->clk_adjust;
+ popts->wrlvl_start = pbsp->wrlvl_start;
+ popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
+ popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
+ goto found;
+ }
+ pbsp_highest = pbsp;
+ }
+ pbsp++;
+ }
+
+ if (pbsp_highest) {
+ printf("Error: board specific timing not found for %lu MT/s\n",
+ ddr_freq);
+ printf("Trying to use the highest speed (%u) parameters\n",
+ pbsp_highest->datarate_mhz_high);
+ popts->clk_adjust = pbsp_highest->clk_adjust;
+ popts->wrlvl_start = pbsp_highest->wrlvl_start;
+ popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
+ popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
+ } else {
+ panic("DIMM is not supported by this board");
+ }
+found:
+ debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n",
+ pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb);
+
+ popts->data_bus_width = 0; /* 64b data bus */
+ popts->otf_burst_chop_en = 0;
+ popts->burst_length = DDR_BL8;
+ popts->bstopre = 0; /* enable auto precharge */
+
+ popts->half_strength_driver_enable = 0;
+ /*
+ * Write leveling override
+ */
+ popts->wrlvl_override = 1;
+ popts->wrlvl_sample = 0xf;
+
+ /*
+ * Rtt and Rtt_WR override
+ */
+ popts->rtt_override = 0;
+
+ /* Enable ZQ calibration */
+ popts->zq_en = 1;
+
+ popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
+ popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) |
+ DDR_CDR2_VREF_TRAIN_EN | DDR_CDR2_VREF_RANGE_2;
+}
+
+phys_size_t initdram(int board_type)
+{
+ phys_size_t dram_size;
+
+#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
+ return fsl_ddr_sdram_size();
+#else
+ puts("Initializing DDR....using SPD\n");
+
+ dram_size = fsl_ddr_sdram();
+#endif
+
+#ifdef CONFIG_FSL_DEEP_SLEEP
+ fsl_dp_ddr_restore();
+#endif
+
+ erratum_a008850_post();
+
+ return dram_size;
+}
+
+void dram_init_banksize(void)
+{
+ /*
+ * gd->arch.secure_ram tracks the location of secure memory.
+ * It was set as if the memory starts from 0.
+ * The address needs to add the offset of its bank.
+ */
+ gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+ if (gd->ram_size > CONFIG_SYS_DDR_BLOCK1_SIZE) {
+ gd->bd->bi_dram[0].size = CONFIG_SYS_DDR_BLOCK1_SIZE;
+ gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE;
+ gd->bd->bi_dram[1].size = gd->ram_size -
+ CONFIG_SYS_DDR_BLOCK1_SIZE;
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+ gd->arch.secure_ram = gd->bd->bi_dram[1].start +
+ gd->arch.secure_ram -
+ CONFIG_SYS_DDR_BLOCK1_SIZE;
+ gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+#endif
+ } else {
+ gd->bd->bi_dram[0].size = gd->ram_size;
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+ gd->arch.secure_ram = gd->bd->bi_dram[0].start +
+ gd->arch.secure_ram;
+ gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+#endif
+ }
+}
diff --git a/board/freescale/ls1046aqds/ddr.h b/board/freescale/ls1046aqds/ddr.h
new file mode 100644
index 0000000..b594032
--- /dev/null
+++ b/board/freescale/ls1046aqds/ddr.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __DDR_H__
+#define __DDR_H__
+
+void erratum_a008850_post(void);
+
+struct board_specific_parameters {
+ u32 n_ranks;
+ u32 datarate_mhz_high;
+ u32 rank_gb;
+ u32 clk_adjust;
+ u32 wrlvl_start;
+ u32 wrlvl_ctl_2;
+ u32 wrlvl_ctl_3;
+};
+
+/*
+ * These tables contain all valid speeds we want to override with board
+ * specific parameters. datarate_mhz_high values need to be in ascending order
+ * for each n_ranks group.
+ */
+static const struct board_specific_parameters udimm0[] = {
+ /*
+ * memory controller 0
+ * num| hi| rank| clk| wrlvl | wrlvl | wrlvl |
+ * ranks| mhz| GB |adjst| start | ctl2 | ctl3 |
+ */
+ {2, 1350, 0, 8, 6, 0x0708090B, 0x0C0D0E09,},
+ {2, 1666, 0, 8, 7, 0x08090A0C, 0x0D0F100B,},
+ {2, 1900, 0, 8, 7, 0x09090B0D, 0x0E10120B,},
+ {2, 2300, 0, 8, 9, 0x0A0C0D11, 0x1214150E,},
+ {}
+};
+
+static const struct board_specific_parameters *udimms[] = {
+ udimm0,
+};
+
+#endif
diff --git a/board/freescale/ls1046aqds/eth.c b/board/freescale/ls1046aqds/eth.c
new file mode 100644
index 0000000..046db11
--- /dev/null
+++ b/board/freescale/ls1046aqds/eth.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <netdev.h>
+#include <fdt_support.h>
+#include <fm_eth.h>
+#include <fsl_mdio.h>
+#include <fsl_dtsec.h>
+#include <malloc.h>
+#include <asm/arch/fsl_serdes.h>
+
+#include "../common/qixis.h"
+#include "../common/fman.h"
+#include "ls1046aqds_qixis.h"
+
+#define EMI_NONE 0xFF
+#define EMI1_RGMII1 0
+#define EMI1_RGMII2 1
+#define EMI1_SLOT1 2
+#define EMI1_SLOT2 3
+#define EMI1_SLOT4 4
+
+static int mdio_mux[NUM_FM_PORTS];
+
+static const char * const mdio_names[] = {
+ "LS1046AQDS_MDIO_RGMII1",
+ "LS1046AQDS_MDIO_RGMII2",
+ "LS1046AQDS_MDIO_SLOT1",
+ "LS1046AQDS_MDIO_SLOT2",
+ "LS1046AQDS_MDIO_SLOT4",
+ "NULL",
+};
+
+/* Map SerDes 1 & 2 lanes to default slot. */
+static u8 lane_to_slot[] = {1, 1, 1, 1, 0, 4, 0 , 0};
+
+static const char *ls1046aqds_mdio_name_for_muxval(u8 muxval)
+{
+ return mdio_names[muxval];
+}
+
+struct mii_dev *mii_dev_for_muxval(u8 muxval)
+{
+ struct mii_dev *bus;
+ const char *name;
+
+ if (muxval > EMI1_SLOT4)
+ return NULL;
+
+ name = ls1046aqds_mdio_name_for_muxval(muxval);
+
+ if (!name) {
+ printf("No bus for muxval %x\n", muxval);
+ return NULL;
+ }
+
+ bus = miiphy_get_dev_by_name(name);
+
+ if (!bus) {
+ printf("No bus by name %s\n", name);
+ return NULL;
+ }
+
+ return bus;
+}
+
+struct ls1046aqds_mdio {
+ u8 muxval;
+ struct mii_dev *realbus;
+};
+
+static void ls1046aqds_mux_mdio(u8 muxval)
+{
+ u8 brdcfg4;
+
+ if (muxval < 7) {
+ brdcfg4 = QIXIS_READ(brdcfg[4]);
+ brdcfg4 &= ~BRDCFG4_EMISEL_MASK;
+ brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT);
+ QIXIS_WRITE(brdcfg[4], brdcfg4);
+ }
+}
+
+static int ls1046aqds_mdio_read(struct mii_dev *bus, int addr, int devad,
+ int regnum)
+{
+ struct ls1046aqds_mdio *priv = bus->priv;
+
+ ls1046aqds_mux_mdio(priv->muxval);
+
+ return priv->realbus->read(priv->realbus, addr, devad, regnum);
+}
+
+static int ls1046aqds_mdio_write(struct mii_dev *bus, int addr, int devad,
+ int regnum, u16 value)
+{
+ struct ls1046aqds_mdio *priv = bus->priv;
+
+ ls1046aqds_mux_mdio(priv->muxval);
+
+ return priv->realbus->write(priv->realbus, addr, devad,
+ regnum, value);
+}
+
+static int ls1046aqds_mdio_reset(struct mii_dev *bus)
+{
+ struct ls1046aqds_mdio *priv = bus->priv;
+
+ return priv->realbus->reset(priv->realbus);
+}
+
+static int ls1046aqds_mdio_init(char *realbusname, u8 muxval)
+{
+ struct ls1046aqds_mdio *pmdio;
+ struct mii_dev *bus = mdio_alloc();
+
+ if (!bus) {
+ printf("Failed to allocate ls1046aqds MDIO bus\n");
+ return -1;
+ }
+
+ pmdio = malloc(sizeof(*pmdio));
+ if (!pmdio) {
+ printf("Failed to allocate ls1046aqds private data\n");
+ free(bus);
+ return -1;
+ }
+
+ bus->read = ls1046aqds_mdio_read;
+ bus->write = ls1046aqds_mdio_write;
+ bus->reset = ls1046aqds_mdio_reset;
+ sprintf(bus->name, ls1046aqds_mdio_name_for_muxval(muxval));
+
+ pmdio->realbus = miiphy_get_dev_by_name(realbusname);
+
+ if (!pmdio->realbus) {
+ printf("No bus with name %s\n", realbusname);
+ free(bus);
+ free(pmdio);
+ return -1;
+ }
+
+ pmdio->muxval = muxval;
+ bus->priv = pmdio;
+ return mdio_register(bus);
+}
+
+void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
+ enum fm_port port, int offset)
+{
+ struct fixed_link f_link;
+
+ if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII) {
+ switch (port) {
+ case FM1_DTSEC9:
+ fdt_set_phy_handle(fdt, compat, addr, "sgmii_s1_p1");
+ break;
+ case FM1_DTSEC10:
+ fdt_set_phy_handle(fdt, compat, addr, "sgmii_s1_p2");
+ break;
+ case FM1_DTSEC5:
+ fdt_set_phy_handle(fdt, compat, addr, "sgmii_s1_p3");
+ break;
+ case FM1_DTSEC6:
+ fdt_set_phy_handle(fdt, compat, addr, "sgmii_s1_p4");
+ break;
+ case FM1_DTSEC2:
+ fdt_set_phy_handle(fdt, compat, addr, "sgmii_s4_p1");
+ break;
+ default:
+ break;
+ }
+ } else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII_2500) {
+ /* 2.5G SGMII interface */
+ f_link.phy_id = cpu_to_fdt32(port);
+ f_link.duplex = cpu_to_fdt32(1);
+ f_link.link_speed = cpu_to_fdt32(1000);
+ f_link.pause = 0;
+ f_link.asym_pause = 0;
+ /* no PHY for 2.5G SGMII on QDS */
+ fdt_delprop(fdt, offset, "phy-handle");
+ fdt_setprop(fdt, offset, "fixed-link", &f_link, sizeof(f_link));
+ fdt_setprop_string(fdt, offset, "phy-connection-type",
+ "sgmii-2500");
+ } else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_QSGMII) {
+ switch (port) {
+ case FM1_DTSEC1:
+ fdt_set_phy_handle(fdt, compat, addr, "qsgmii_s2_p4");
+ break;
+ case FM1_DTSEC5:
+ fdt_set_phy_handle(fdt, compat, addr, "qsgmii_s2_p2");
+ break;
+ case FM1_DTSEC6:
+ fdt_set_phy_handle(fdt, compat, addr, "qsgmii_s2_p1");
+ break;
+ case FM1_DTSEC10:
+ fdt_set_phy_handle(fdt, compat, addr, "qsgmii_s2_p3");
+ break;
+ default:
+ break;
+ }
+ fdt_delprop(fdt, offset, "phy-connection-type");
+ fdt_setprop_string(fdt, offset, "phy-connection-type",
+ "qsgmii");
+ } else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_XGMII &&
+ (port == FM1_10GEC1 || port == FM1_10GEC2)) {
+ /* XFI interface */
+ f_link.phy_id = cpu_to_fdt32(port);
+ f_link.duplex = cpu_to_fdt32(1);
+ f_link.link_speed = cpu_to_fdt32(10000);
+ f_link.pause = 0;
+ f_link.asym_pause = 0;
+ /* no PHY for XFI */
+ fdt_delprop(fdt, offset, "phy-handle");
+ fdt_setprop(fdt, offset, "fixed-link", &f_link, sizeof(f_link));
+ fdt_setprop_string(fdt, offset, "phy-connection-type", "xgmii");
+ }
+}
+
+void fdt_fixup_board_enet(void *fdt)
+{
+ int i;
+
+ for (i = FM1_DTSEC1; i < NUM_FM_PORTS; i++) {
+ switch (fm_info_get_enet_if(i)) {
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_QSGMII:
+ switch (mdio_mux[i]) {
+ case EMI1_SLOT1:
+ fdt_status_okay_by_alias(fdt, "emi1_slot1");
+ break;
+ case EMI1_SLOT2:
+ fdt_status_okay_by_alias(fdt, "emi1_slot2");
+ break;
+ case EMI1_SLOT4:
+ fdt_status_okay_by_alias(fdt, "emi1_slot4");
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+int board_eth_init(bd_t *bis)
+{
+#ifdef CONFIG_FMAN_ENET
+ int i, idx, lane, slot, interface;
+ struct memac_mdio_info dtsec_mdio_info;
+ struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+ u32 srds_s1, srds_s2;
+ u8 brdcfg12;
+
+ srds_s1 = in_be32(&gur->rcwsr[4]) &
+ FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
+ srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
+
+ srds_s2 = in_be32(&gur->rcwsr[4]) &
+ FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
+ srds_s2 >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
+
+ /* Initialize the mdio_mux array so we can recognize empty elements */
+ for (i = 0; i < NUM_FM_PORTS; i++)
+ mdio_mux[i] = EMI_NONE;
+
+ dtsec_mdio_info.regs =
+ (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
+
+ dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
+
+ /* Register the 1G MDIO bus */
+ fm_memac_mdio_init(bis, &dtsec_mdio_info);
+
+ /* Register the muxing front-ends to the MDIO buses */
+ ls1046aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII1);
+ ls1046aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII2);
+ ls1046aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT1);
+ ls1046aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT2);
+ ls1046aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT4);
+
+ /* Set the two on-board RGMII PHY address */
+ fm_info_set_phy_address(FM1_DTSEC3, RGMII_PHY1_ADDR);
+ fm_info_set_phy_address(FM1_DTSEC4, RGMII_PHY2_ADDR);
+
+ switch (srds_s1) {
+ case 0x3333:
+ /* SGMII on slot 1, MAC 9 */
+ fm_info_set_phy_address(FM1_DTSEC9, SGMII_CARD_PORT1_PHY_ADDR);
+ case 0x1333:
+ case 0x2333:
+ /* SGMII on slot 1, MAC 10 */
+ fm_info_set_phy_address(FM1_DTSEC10, SGMII_CARD_PORT2_PHY_ADDR);
+ case 0x1133:
+ case 0x2233:
+ /* SGMII on slot 1, MAC 5/6 */
+ fm_info_set_phy_address(FM1_DTSEC5, SGMII_CARD_PORT3_PHY_ADDR);
+ fm_info_set_phy_address(FM1_DTSEC6, SGMII_CARD_PORT4_PHY_ADDR);
+ break;
+ case 0x1040:
+ case 0x2040:
+ /* QSGMII on lane B, MAC 6/5/10/1 */
+ fm_info_set_phy_address(FM1_DTSEC6,
+ QSGMII_CARD_PORT1_PHY_ADDR_S2);
+ fm_info_set_phy_address(FM1_DTSEC5,
+ QSGMII_CARD_PORT2_PHY_ADDR_S2);
+ fm_info_set_phy_address(FM1_DTSEC10,
+ QSGMII_CARD_PORT3_PHY_ADDR_S2);
+ fm_info_set_phy_address(FM1_DTSEC1,
+ QSGMII_CARD_PORT4_PHY_ADDR_S2);
+ break;
+ case 0x3363:
+ /* SGMII on slot 1, MAC 9/10 */
+ fm_info_set_phy_address(FM1_DTSEC9, SGMII_CARD_PORT1_PHY_ADDR);
+ fm_info_set_phy_address(FM1_DTSEC10, SGMII_CARD_PORT2_PHY_ADDR);
+ case 0x1163:
+ case 0x2263:
+ case 0x2223:
+ /* SGMII on slot 1, MAC 6 */
+ fm_info_set_phy_address(FM1_DTSEC6, SGMII_CARD_PORT4_PHY_ADDR);
+ break;
+ default:
+ printf("Invalid SerDes protocol 0x%x for LS1046AQDS\n",
+ srds_s1);
+ break;
+ }
+
+ if (srds_s2 == 0x5a59 || srds_s2 == 0x5a06)
+ /* SGMII on slot 4, MAC 2 */
+ fm_info_set_phy_address(FM1_DTSEC2, SGMII_CARD_PORT1_PHY_ADDR);
+
+ for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
+ idx = i - FM1_DTSEC1;
+ interface = fm_info_get_enet_if(i);
+ switch (interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_QSGMII:
+ if (interface == PHY_INTERFACE_MODE_SGMII) {
+ if (i == FM1_DTSEC5) {
+ /* route lane 2 to slot1 so to have
+ * one sgmii riser card supports
+ * MAC5 and MAC6.
+ */
+ brdcfg12 = QIXIS_READ(brdcfg[12]);
+ QIXIS_WRITE(brdcfg[12],
+ brdcfg12 | 0x80);
+ }
+ lane = serdes_get_first_lane(FSL_SRDS_1,
+ SGMII_FM1_DTSEC1 + idx);
+ } else {
+ /* clear the bit 7 to route lane B on slot2. */
+ brdcfg12 = QIXIS_READ(brdcfg[12]);
+ QIXIS_WRITE(brdcfg[12], brdcfg12 & 0x7f);
+
+ lane = serdes_get_first_lane(FSL_SRDS_1,
+ QSGMII_FM1_A);
+ lane_to_slot[lane] = 2;
+ }
+
+ if (i == FM1_DTSEC2)
+ lane = 5;
+
+ if (lane < 0)
+ break;
+
+ slot = lane_to_slot[lane];
+ debug("FM1@DTSEC%u expects SGMII in slot %u\n",
+ idx + 1, slot);
+ if (QIXIS_READ(present2) & (1 << (slot - 1)))
+ fm_disable_port(i);
+
+ switch (slot) {
+ case 1:
+ mdio_mux[i] = EMI1_SLOT1;
+ fm_info_set_mdio(i, mii_dev_for_muxval(
+ mdio_mux[i]));
+ break;
+ case 2:
+ mdio_mux[i] = EMI1_SLOT2;
+ fm_info_set_mdio(i, mii_dev_for_muxval(
+ mdio_mux[i]));
+ break;
+ case 4:
+ mdio_mux[i] = EMI1_SLOT4;
+ fm_info_set_mdio(i, mii_dev_for_muxval(
+ mdio_mux[i]));
+ break;
+ default:
+ break;
+ }
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ if (i == FM1_DTSEC3)
+ mdio_mux[i] = EMI1_RGMII1;
+ else if (i == FM1_DTSEC4)
+ mdio_mux[i] = EMI1_RGMII2;
+ fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
+ break;
+ default:
+ break;
+ }
+ }
+
+ cpu_eth_init(bis);
+#endif /* CONFIG_FMAN_ENET */
+
+ return pci_eth_init(bis);
+}
diff --git a/board/freescale/ls1046aqds/ls1046aqds.c b/board/freescale/ls1046aqds/ls1046aqds.c
new file mode 100644
index 0000000..8c18538
--- /dev/null
+++ b/board/freescale/ls1046aqds/ls1046aqds.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <fdt_support.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/fdt.h>
+#include <asm/arch/soc.h>
+#include <ahci.h>
+#include <hwconfig.h>
+#include <mmc.h>
+#include <scsi.h>
+#include <fm_eth.h>
+#include <fsl_csu.h>
+#include <fsl_esdhc.h>
+#include <fsl_ifc.h>
+#include <spl.h>
+
+#include "../common/vid.h"
+#include "../common/qixis.h"
+#include "ls1046aqds_qixis.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+ MUX_TYPE_GPIO,
+};
+
+int checkboard(void)
+{
+ char buf[64];
+#ifndef CONFIG_SD_BOOT
+ u8 sw;
+#endif
+
+ puts("Board: LS1046AQDS, boot from ");
+
+#ifdef CONFIG_SD_BOOT
+ puts("SD\n");
+#else
+ sw = QIXIS_READ(brdcfg[0]);
+ sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT;
+
+ if (sw < 0x8)
+ printf("vBank: %d\n", sw);
+ else if (sw == 0x8)
+ puts("PromJet\n");
+ else if (sw == 0x9)
+ puts("NAND\n");
+ else if (sw == 0xF)
+ printf("QSPI\n");
+ else
+ printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH);
+#endif
+
+ printf("Sys ID: 0x%02x, Sys Ver: 0x%02x\n",
+ QIXIS_READ(id), QIXIS_READ(arch));
+
+ printf("FPGA: v%d (%s), build %d\n",
+ (int)QIXIS_READ(scver), qixis_read_tag(buf),
+ (int)qixis_read_minor());
+
+ return 0;
+}
+
+bool if_board_diff_clk(void)
+{
+ u8 diff_conf = QIXIS_READ(brdcfg[11]);
+
+ return diff_conf & 0x40;
+}
+
+unsigned long get_board_sys_clk(void)
+{
+ u8 sysclk_conf = QIXIS_READ(brdcfg[1]);
+
+ switch (sysclk_conf & 0x0f) {
+ case QIXIS_SYSCLK_64:
+ return 64000000;
+ case QIXIS_SYSCLK_83:
+ return 83333333;
+ case QIXIS_SYSCLK_100:
+ return 100000000;
+ case QIXIS_SYSCLK_125:
+ return 125000000;
+ case QIXIS_SYSCLK_133:
+ return 133333333;
+ case QIXIS_SYSCLK_150:
+ return 150000000;
+ case QIXIS_SYSCLK_160:
+ return 160000000;
+ case QIXIS_SYSCLK_166:
+ return 166666666;
+ }
+
+ return 66666666;
+}
+
+unsigned long get_board_ddr_clk(void)
+{
+ u8 ddrclk_conf = QIXIS_READ(brdcfg[1]);
+
+ if (if_board_diff_clk())
+ return get_board_sys_clk();
+ switch ((ddrclk_conf & 0x30) >> 4) {
+ case QIXIS_DDRCLK_100:
+ return 100000000;
+ case QIXIS_DDRCLK_125:
+ return 125000000;
+ case QIXIS_DDRCLK_133:
+ return 133333333;
+ }
+
+ return 66666666;
+}
+
+int select_i2c_ch_pca9547(u8 ch)
+{
+ int ret;
+
+ ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1);
+ if (ret) {
+ puts("PCA: failed to select proper channel\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+int dram_init(void)
+{
+ /*
+ * When resuming from deep sleep, the I2C channel may not be
+ * in the default channel. So, switch to the default channel
+ * before accessing DDR SPD.
+ */
+ select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
+ gd->ram_size = initdram(0);
+
+ return 0;
+}
+
+int i2c_multiplexer_select_vid_channel(u8 channel)
+{
+ return select_i2c_ch_pca9547(channel);
+}
+
+int board_early_init_f(void)
+{
+#ifdef CONFIG_HAS_FSL_XHCI_USB
+ struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
+ u32 usb_pwrfault;
+#endif
+
+#ifdef CONFIG_SYS_I2C_EARLY_INIT
+ i2c_early_init_f();
+#endif
+ fsl_lsch2_early_init_f();
+
+#ifdef CONFIG_HAS_FSL_XHCI_USB
+ out_be32(&scfg->rcwpmuxcr0, 0x3333);
+ out_be32(&scfg->usbdrvvbus_selcr, SCFG_USBDRVVBUS_SELCR_USB1);
+ usb_pwrfault = (SCFG_USBPWRFAULT_DEDICATED <<
+ SCFG_USBPWRFAULT_USB3_SHIFT) |
+ (SCFG_USBPWRFAULT_DEDICATED <<
+ SCFG_USBPWRFAULT_USB2_SHIFT) |
+ (SCFG_USBPWRFAULT_SHARED <<
+ SCFG_USBPWRFAULT_USB1_SHIFT);
+ out_be32(&scfg->usbpwrfault_selcr, usb_pwrfault);
+#endif
+
+ return 0;
+}
+
+#ifdef CONFIG_FSL_DEEP_SLEEP
+/* determine if it is a warm boot */
+bool is_warm_boot(void)
+{
+#define DCFG_CCSR_CRSTSR_WDRFR (1 << 3)
+ struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+
+ if (in_be32(&gur->crstsr) & DCFG_CCSR_CRSTSR_WDRFR)
+ return 1;
+
+ return 0;
+}
+#endif
+
+int config_board_mux(int ctrl_type)
+{
+ u8 reg14;
+
+ reg14 = QIXIS_READ(brdcfg[14]);
+
+ switch (ctrl_type) {
+ case MUX_TYPE_GPIO:
+ reg14 = (reg14 & (~0x6)) | 0x2;
+ break;
+ default:
+ puts("Unsupported mux interface type\n");
+ return -1;
+ }
+
+ QIXIS_WRITE(brdcfg[14], reg14);
+
+ return 0;
+}
+
+int config_serdes_mux(void)
+{
+ return 0;
+}
+
+#ifdef CONFIG_MISC_INIT_R
+int misc_init_r(void)
+{
+ if (hwconfig("gpio"))
+ config_board_mux(MUX_TYPE_GPIO);
+
+ return 0;
+}
+#endif
+
+int board_init(void)
+{
+ select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
+
+#ifdef CONFIG_SYS_FSL_SERDES
+ config_serdes_mux();
+#endif
+
+#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
+ enable_layerscape_ns_access();
+#endif
+
+ if (adjust_vdd(0))
+ printf("Warning: Adjusting core voltage failed.\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_OF_BOARD_SETUP
+int ft_board_setup(void *blob, bd_t *bd)
+{
+ u64 base[CONFIG_NR_DRAM_BANKS];
+ u64 size[CONFIG_NR_DRAM_BANKS];
+ u8 reg;
+
+ /* fixup DT for the two DDR banks */
+ base[0] = gd->bd->bi_dram[0].start;
+ size[0] = gd->bd->bi_dram[0].size;
+ base[1] = gd->bd->bi_dram[1].start;
+ size[1] = gd->bd->bi_dram[1].size;
+
+ fdt_fixup_memory_banks(blob, base, size, 2);
+ ft_cpu_setup(blob, bd);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+ fdt_fixup_fman_ethernet(blob);
+ fdt_fixup_board_enet(blob);
+#endif
+
+ reg = QIXIS_READ(brdcfg[0]);
+ reg = (reg & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT;
+
+ /* Disable IFC if QSPI is enabled */
+ if (reg == 0xF)
+ do_fixup_by_compat(blob, "fsl,ifc",
+ "status", "disabled", 8 + 1, 1);
+
+ return 0;
+}
+#endif
+
+u8 flash_read8(void *addr)
+{
+ return __raw_readb(addr + 1);
+}
+
+void flash_write16(u16 val, void *addr)
+{
+ u16 shftval = (((val >> 8) & 0xff) | ((val << 8) & 0xff00));
+
+ __raw_writew(shftval, addr);
+}
+
+u16 flash_read16(void *addr)
+{
+ u16 val = __raw_readw(addr);
+
+ return (((val) >> 8) & 0x00ff) | (((val) << 8) & 0xff00);
+}
diff --git a/board/freescale/ls1046aqds/ls1046aqds_pbi.cfg b/board/freescale/ls1046aqds/ls1046aqds_pbi.cfg
new file mode 100644
index 0000000..5a6b7b8
--- /dev/null
+++ b/board/freescale/ls1046aqds/ls1046aqds_pbi.cfg
@@ -0,0 +1,17 @@
+#Configure Scratch register
+09570600 00000000
+09570604 10000000
+#Alt base register
+09570158 00001000
+#Disable CCI barrier tranaction
+09570178 0000e010
+09180000 00000008
+#USB PHY frequency sel
+09570418 0000009e
+0957041c 0000009e
+09570420 0000009e
+#Serdes SATA
+09eb1300 80104e20
+09eb08dc 00502880
+#flush PBI data
+096100c0 000fffff
diff --git a/board/freescale/ls1046aqds/ls1046aqds_qixis.h b/board/freescale/ls1046aqds/ls1046aqds_qixis.h
new file mode 100644
index 0000000..58ab132
--- /dev/null
+++ b/board/freescale/ls1046aqds/ls1046aqds_qixis.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __LS1046AQDS_QIXIS_H__
+#define __LS1046AQDS_QIXIS_H__
+
+/* Definitions of QIXIS Registers for LS1046AQDS */
+
+/* BRDCFG4[4:7] select EC1 and EC2 as a pair */
+#define BRDCFG4_EMISEL_MASK 0xe0
+#define BRDCFG4_EMISEL_SHIFT 5
+
+/* SYSCLK */
+#define QIXIS_SYSCLK_66 0x0
+#define QIXIS_SYSCLK_83 0x1
+#define QIXIS_SYSCLK_100 0x2
+#define QIXIS_SYSCLK_125 0x3
+#define QIXIS_SYSCLK_133 0x4
+#define QIXIS_SYSCLK_150 0x5
+#define QIXIS_SYSCLK_160 0x6
+#define QIXIS_SYSCLK_166 0x7
+#define QIXIS_SYSCLK_64 0x8
+
+/* DDRCLK */
+#define QIXIS_DDRCLK_66 0x0
+#define QIXIS_DDRCLK_100 0x1
+#define QIXIS_DDRCLK_125 0x2
+#define QIXIS_DDRCLK_133 0x3
+
+/* BRDCFG2 - SD clock*/
+#define QIXIS_SDCLK1_100 0x0
+#define QIXIS_SDCLK1_125 0x1
+#define QIXIS_SDCLK1_165 0x2
+#define QIXIS_SDCLK1_100_SP 0x3
+
+#endif
diff --git a/board/freescale/ls1046aqds/ls1046aqds_rcw_nand.cfg b/board/freescale/ls1046aqds/ls1046aqds_rcw_nand.cfg
new file mode 100644
index 0000000..b5fc08c
--- /dev/null
+++ b/board/freescale/ls1046aqds/ls1046aqds_rcw_nand.cfg
@@ -0,0 +1,7 @@
+#PBL preamble and RCW header
+aa55aa55 01ee0100
+# serdes protocol
+0c150010 0e000000 00000000 00000000
+11335559 40005012 e0116000 c1000000
+00000000 00000000 00000000 00038800
+00000000 01001101 00000096 00000001
diff --git a/board/freescale/ls1046aqds/ls1046aqds_rcw_sd_ifc.cfg b/board/freescale/ls1046aqds/ls1046aqds_rcw_sd_ifc.cfg
new file mode 100644
index 0000000..59d24d6
--- /dev/null
+++ b/board/freescale/ls1046aqds/ls1046aqds_rcw_sd_ifc.cfg
@@ -0,0 +1,8 @@
+#PBL preamble and RCW header
+aa55aa55 01ee0100
+# RCW
+# Enable IFC; disable QSPI
+0c150010 0e000000 00000000 00000000
+11335559 40005012 60040000 c1000000
+00000000 00000000 00000000 00038800
+00000000 01001101 00000096 00000001
diff --git a/board/freescale/ls1046aqds/ls1046aqds_rcw_sd_qspi.cfg b/board/freescale/ls1046aqds/ls1046aqds_rcw_sd_qspi.cfg
new file mode 100644
index 0000000..9401a6f
--- /dev/null
+++ b/board/freescale/ls1046aqds/ls1046aqds_rcw_sd_qspi.cfg
@@ -0,0 +1,8 @@
+#PBL preamble and RCW header
+aa55aa55 01ee0100
+# RCW
+# Enable QSPI; disable IFC
+0c150010 0e000000 00000000 00000000
+11335559 40005012 60040000 c1000000
+00000000 00000000 00000000 00038800
+20124000 01001101 00000096 00000001