powerpc/T104xD4RDB: Add T104xD4RDB boards support

T1040D4RDB is a Freescale reference board that hosts the T1040 SoC.
    T1040D4RDB is re-designed T1040RDB board with following changes :
    - Support of DDR4 memory
    - Support of 0x66 serdes protocol which can support following interfaces
        - 2 RGMII's on DTSEC4, DTSEC5
        - 1 SGMII on DTSEC3
    - Support of QE-TDM

    Similarily T1042D4RDB is a Freescale reference board that hosts the T1040
    SoC. T1042D4RDB is re-designed T1042RDB board with following changes :
    - Support of DDR4 memory
    - Support for 0x86 serdes protocol which can support following interfaces
        - 2 RGMII's on DTSEC4, DTSEC5
        - 3 SGMII on DTSEC1, DTSEC2 & DTSEC3
    - Support of DIU

Signed-off-by: Priyanka Jain <Priyanka.Jain@freescale.com>
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@freescale.com>
Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
Reviewed-by: York Sun <yorksun@freescale.com>
diff --git a/board/freescale/t104xrdb/MAINTAINERS b/board/freescale/t104xrdb/MAINTAINERS
index 13d9be9..32e044f 100644
--- a/board/freescale/t104xrdb/MAINTAINERS
+++ b/board/freescale/t104xrdb/MAINTAINERS
@@ -6,7 +6,13 @@
 F:	configs/T1040RDB_defconfig
 F:	configs/T1040RDB_NAND_defconfig
 F:	configs/T1040RDB_SPIFLASH_defconfig
+F:	configs/T1040D4RDB_defconfig
+F:	configs/T1040D4RDB_NAND_defconfig
+F:	configs/T1040D4RDB_SPIFLASH_defconfig
 F:	configs/T1042RDB_defconfig
+F:	configs/T1042D4RDB_defconfig
+F:	configs/T1042D4RDB_NAND_defconfig
+F:	configs/T1042D4RDB_SPIFLASH_defconfig
 F:	configs/T1042RDB_PI_defconfig
 F:	configs/T1042RDB_PI_NAND_defconfig
 F:	configs/T1042RDB_PI_SPIFLASH_defconfig
@@ -15,6 +21,8 @@
 #M:	-
 S:	Maintained
 F:	configs/T1040RDB_SDCARD_defconfig
+F:	configs/T1040D4RDB_SDCARD_defconfig
+F:	configs/T1042D4RDB_SDCARD_defconfig
 F:	configs/T1042RDB_PI_SDCARD_defconfig
 
 T1040RDB_SECURE_BOOT BOARD
diff --git a/board/freescale/t104xrdb/README b/board/freescale/t104xrdb/README
index ac95b5e..b9d2212 100644
--- a/board/freescale/t104xrdb/README
+++ b/board/freescale/t104xrdb/README
@@ -12,6 +12,17 @@
 (a personality of T1040 SoC). The board is similar to T1040RDB but is
 designed specially with low power features targeted for Printing Image Market.
 
+The T1040D4RDB is a Freescale reference board that hosts the T1040 SoC.
+The board is re-designed T1040RDB board with following changes :
+    - Support of DDR4 memory and some enhancements
+
+The T1042D4RDB is a Freescale reference board that hosts the T1042 SoC.
+The board is re-designed T1040RDB board with following changes :
+    - Support of DDR4 memory
+    - Support for 0x86 serdes protocol which can support following interfaces
+        - 2 RGMII's on DTSEC4, DTSEC5
+        - 3 SGMII on DTSEC1, DTSEC2 & DTSEC3
+
 Basic difference's among T1040RDB, T1042RDB_PI, T1042RDB
 -------------------------------------------------------------------------
 Board		Si		Protocol		Targeted Market
@@ -19,6 +30,8 @@
 T1040RDB	T1040		0x66                    Networking
 T1040RDB	T1042		0x86                    Networking
 T1042RDB_PI	T1042		0x06                    Printing & Imaging
+T1040D4RDB	T1040		0x66                    Networking
+T1042D4RDB	T1042		0x86                    Networking
 
 
 T1040 SoC Overview
@@ -70,7 +83,6 @@
 
 T1040 SoC Personalities
 -------------------------
-
 T1022 Personality:
 T1022 is a reduced personality of T1040 with less core/clusters.
 
@@ -268,8 +280,13 @@
 Please note QE Firmware is only valid for T1040RDB
 
 
-Switch Settings: (ON is 0, OFF is 1)
-===============
+Switch Settings for T104xRDB boards: (ON is 0, OFF is 1)
+==========================================================
+NOR boot SW setting:
+SW1: 00010011
+SW2: 10111011
+SW3: 11100001
+
 NAND boot SW setting:
 SW1: 10001000
 SW2: 00111011
@@ -284,3 +301,67 @@
 SW1: 00100000
 SW2: 00111011
 SW3: 11100001
+
+Switch Settings for T104xD4RDB boards: (ON is 0, OFF is 1)
+=============================================================
+NOR boot SW setting:
+SW1: 00010011
+SW2: 10111001
+SW3: 11100001
+
+NAND boot SW setting:
+SW1: 10001000
+SW2: 00111001
+SW3: 11110001
+
+SPI boot SW setting:
+SW1: 00100010
+SW2: 10111001
+SW3: 11100001
+
+SD boot SW setting:
+SW1: 00100000
+SW2: 00111001
+SW3: 11100001
+
+PBL-based image generation
+==========================
+Changes only the required register bit in in PBI commands.
+
+Provides reference code which might needs some
+modification as per requirement.
+example:
+By default PBI_SRC=14 (which is for IFC-NAND/NOR) in rcw.cfg file
+which needs to be changed for SPI and SD.
+
+For SD-boot
+==============
+1. Set RCW[192:195], PBI_SRC bits as 6 in RCW file (t1040d4_rcw.cfg type files)
+
+example:
+ RCW file: board/freescale/t104xrdb/t1040d4_rcw.cfg
+
+Change
+66000002 40000002 ec027000 01000000
+to
+66000002 40000002 6c027000 01000000
+
+2. SD does not support flush so remove flush from pbl, make changes in
+   tools/pblimage.c file, Update value of pbl_end_cmd[0] = 0x09138000
+   with 0x091380c0
+
+For SPI-boot
+==============
+1. Set RCW[192:195], PBI_SRC bits as 5 in RCW file (t1040d4_rcw.cfg type files)
+
+example:
+ RCW file: board/freescale/t104xrdb/t1040d4_rcw.cfg
+
+Change
+66000002 40000002 ec027000 01000000
+to
+66000002 40000002 5c027000 01000000
+
+2. SPI does not support flush so remove flush from pbl, make changes in
+   tools/pblimage.c file, Update value of pbl_end_cmd[0] = 0x09138000
+   with 0x091380c0
diff --git a/board/freescale/t104xrdb/cpld.c b/board/freescale/t104xrdb/cpld.c
index df0e348..0ce4e47 100644
--- a/board/freescale/t104xrdb/cpld.c
+++ b/board/freescale/t104xrdb/cpld.c
@@ -69,7 +69,11 @@
 	printf("int_status	 = 0x%02x\n", CPLD_READ(int_status));
 	printf("flash_ctl_status = 0x%02x\n", CPLD_READ(flash_ctl_status));
 	printf("fan_ctl_status	 = 0x%02x\n", CPLD_READ(fan_ctl_status));
+#if defined(CONFIG_T104XD4RDB)
+	printf("int_mask	 = 0x%02x\n", CPLD_READ(int_mask));
+#else
 	printf("led_ctl_status	 = 0x%02x\n", CPLD_READ(led_ctl_status));
+#endif
 	printf("sfp_ctl_status	 = 0x%02x\n", CPLD_READ(sfp_ctl_status));
 	printf("misc_ctl_status	 = 0x%02x\n", CPLD_READ(misc_ctl_status));
 	printf("boot_override	 = 0x%02x\n", CPLD_READ(boot_override));
diff --git a/board/freescale/t104xrdb/cpld.h b/board/freescale/t104xrdb/cpld.h
index 0da9a01..2fb4105 100644
--- a/board/freescale/t104xrdb/cpld.h
+++ b/board/freescale/t104xrdb/cpld.h
@@ -21,7 +21,11 @@
 	u8 int_status;		/* 0x12 - Interrupt status Register */
 	u8 flash_ctl_status;	/* 0x13 - Flash control and status register */
 	u8 fan_ctl_status;	/* 0x14 - Fan control and status register  */
+#if defined(CONFIG_T104XD4RDB)
+	u8 int_mask;		/* 0x15 - Interrupt mask Register */
+#else
 	u8 led_ctl_status;	/* 0x15 - LED control and status register */
+#endif
 	u8 sfp_ctl_status;	/* 0x16 - SFP control and status register  */
 	u8 misc_ctl_status;	/* 0x17 - Miscellanies ctrl & status register*/
 	u8 boot_override;	/* 0x18 - Boot override register */
@@ -38,3 +42,5 @@
 #define CPLD_READ(reg) cpld_read(offsetof(struct cpld_data, reg))
 #define CPLD_WRITE(reg, value)\
 		cpld_write(offsetof(struct cpld_data, reg), value)
+#define MISC_CTL_SG_SEL		0x80
+#define MISC_CTL_AURORA_SEL	0x02
diff --git a/board/freescale/t104xrdb/ddr.c b/board/freescale/t104xrdb/ddr.c
index e1148e5..cf79d2d 100644
--- a/board/freescale/t104xrdb/ddr.c
+++ b/board/freescale/t104xrdb/ddr.c
@@ -75,7 +75,11 @@
 	 * Factors to consider for half-strength driver enable:
 	 *	- number of DIMMs installed
 	 */
+#ifdef CONFIG_SYS_FSL_DDR4
+	popts->half_strength_driver_enable = 1;
+#else
 	popts->half_strength_driver_enable = 0;
+#endif
 	/*
 	 * Write leveling override
 	 */
@@ -91,8 +95,14 @@
 	popts->zq_en = 1;
 
 	/* DHC_EN =1, ODT = 75 Ohm */
+#ifdef CONFIG_SYS_FSL_DDR4
+	popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_120OHM);
+	popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_120OHM) |
+		DDR_CDR2_VREF_OVRD(70);       /* Vref = 70% */
+#else
 	popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_75ohm);
 	popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_75ohm);
+#endif
 }
 
 #if defined(CONFIG_DEEP_SLEEP)
diff --git a/board/freescale/t104xrdb/ddr.h b/board/freescale/t104xrdb/ddr.h
index ab1c32d..b9c02f7 100644
--- a/board/freescale/t104xrdb/ddr.h
+++ b/board/freescale/t104xrdb/ddr.h
@@ -28,6 +28,9 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl
 	 * ranks| mhz| GB  |adjst| start |   ctl2
 	 */
+#ifdef CONFIG_SYS_FSL_DDR4
+	{2,  1600, 4, 4,     6, 0x07090A0c, 0x0e0f100a},
+#elif defined(CONFIG_SYS_FSL_DDR3)
 	{2,  833,  4, 4,     6, 0x06060607, 0x08080807},
 	{2,  833,  0, 4,     6, 0x06060607, 0x08080807},
 	{2,  1350, 4, 4,     7, 0x0708080A, 0x0A0B0C09},
@@ -40,10 +43,14 @@
 	{1,  1350, 0, 4,     7, 0x0708080A, 0x0A0B0C09},
 	{1,  1666, 4, 4,     7, 0x0808090B, 0x0C0D0E0A},
 	{1,  1666, 0, 4,     7, 0x0808090B, 0x0C0D0E0A},
+#else
+#error DDR type not defined
+#endif
 	{}
 };
 
+#endif
+
 static const struct board_specific_parameters *udimms[] = {
 	udimm0,
 };
-#endif
diff --git a/board/freescale/t104xrdb/eth.c b/board/freescale/t104xrdb/eth.c
index 7581a4cd..71d0457 100644
--- a/board/freescale/t104xrdb/eth.c
+++ b/board/freescale/t104xrdb/eth.c
@@ -43,9 +43,11 @@
 		int idx = i - FM1_DTSEC1;
 
 		switch (fm_info_get_enet_if(i)) {
-#ifdef CONFIG_T1040RDB
+#if defined(CONFIG_T1040RDB) || defined(CONFIG_T1040D4RDB)
 		case PHY_INTERFACE_MODE_SGMII:
-			/* T1040RDB only supports SGMII on DTSEC3 */
+			/* T1040RDB & T1040D4RDB only supports SGMII on
+			 * DTSEC3
+			 */
 			fm_info_set_phy_address(FM1_DTSEC3,
 						CONFIG_SYS_SGMII1_PHY_ADDR);
 			break;
@@ -60,6 +62,20 @@
 						CONFIG_SYS_SGMII1_PHY_ADDR);
 			break;
 #endif
+#ifdef CONFIG_T1042D4RDB
+		case PHY_INTERFACE_MODE_SGMII:
+			/* T1042D4RDB supports SGMII on DTSEC1, DTSEC2
+			 *  & DTSEC3
+			 */
+			if (FM1_DTSEC1 == i)
+				phy_addr = CONFIG_SYS_SGMII1_PHY_ADDR;
+			if (FM1_DTSEC2 == i)
+				phy_addr = CONFIG_SYS_SGMII2_PHY_ADDR;
+			if (FM1_DTSEC3 == i)
+				phy_addr = CONFIG_SYS_SGMII3_PHY_ADDR;
+			fm_info_set_phy_address(i, phy_addr);
+			break;
+#endif
 		case PHY_INTERFACE_MODE_RGMII:
 			if (FM1_DTSEC4 == i)
 				phy_addr = CONFIG_SYS_RGMII1_PHY_ADDR;
diff --git a/board/freescale/t104xrdb/t1040d4_rcw.cfg b/board/freescale/t104xrdb/t1040d4_rcw.cfg
new file mode 100644
index 0000000..c1034b3
--- /dev/null
+++ b/board/freescale/t104xrdb/t1040d4_rcw.cfg
@@ -0,0 +1,7 @@
+#PBL preamble and RCW header
+aa55aa55 010e0100
+# serdes protocol 0x66
+0c18000e 0e000000 00000000 00000000
+66000002 40000002 ec027000 01000000
+00000000 00000000 00000000 00030810
+00000000 0342580f 00000000 00000000
diff --git a/board/freescale/t104xrdb/t1042d4_rcw.cfg b/board/freescale/t104xrdb/t1042d4_rcw.cfg
new file mode 100644
index 0000000..9e0ee27
--- /dev/null
+++ b/board/freescale/t104xrdb/t1042d4_rcw.cfg
@@ -0,0 +1,7 @@
+#PBL preamble and RCW header
+aa55aa55 010e0100
+# serdes protocol 0x86
+0c18000e 0e000000 00000000 00000000
+86000002 40000002 ec027000 01000000
+00000000 00000000 00000000 00030810
+00000000 0342500f 00000000 00000000
diff --git a/board/freescale/t104xrdb/t104xrdb.c b/board/freescale/t104xrdb/t104xrdb.c
index 9cd5e15..c4b658d 100644
--- a/board/freescale/t104xrdb/t104xrdb.c
+++ b/board/freescale/t104xrdb/t104xrdb.c
@@ -28,7 +28,11 @@
 	struct cpu_type *cpu = gd->arch.cpu;
 	u8 sw;
 
+#ifdef CONFIG_T104XD4RDB
+	printf("Board: %sD4RDB\n", cpu->name);
+#else
 	printf("Board: %sRDB\n", cpu->name);
+#endif
 	printf("Board rev: 0x%02x CPLD ver: 0x%02x, ",
 	       CPLD_READ(hw_ver), CPLD_READ(sw_ver));
 
@@ -91,6 +95,34 @@
 
 int misc_init_r(void)
 {
+	ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	u32 srds_s1;
+
+	srds_s1 = in_be32(&gur->rcwsr[4]) >> 24;
+
+	printf("SERDES Reference : 0x%X\n", srds_s1);
+
+	/* select SGMII*/
+	if (srds_s1 == 0x86)
+		CPLD_WRITE(misc_ctl_status, CPLD_READ(misc_ctl_status) |
+					 MISC_CTL_SG_SEL);
+
+	/* select SGMII and Aurora*/
+	if (srds_s1 == 0x8E)
+		CPLD_WRITE(misc_ctl_status, CPLD_READ(misc_ctl_status) |
+					 MISC_CTL_SG_SEL | MISC_CTL_AURORA_SEL);
+
+#if defined(CONFIG_T1040D4RDB)
+	/* Mask all CPLD interrupt sources, except QSGMII interrupts */
+	if (CPLD_READ(sw_ver) < 0x03) {
+		debug("CPLD SW version 0x%02x doesn't support int_mask\n",
+		      CPLD_READ(sw_ver));
+	} else {
+		CPLD_WRITE(int_mask, CPLD_INT_MASK_ALL &
+			   ~(CPLD_INT_MASK_QSGMII1 | CPLD_INT_MASK_QSGMII2));
+	}
+#endif
+
 	return 0;
 }