driver/ddr/fsl: Add DDR4 support to Freescale DDR driver

Mostly reusing DDR3 driver, this patch adds DDR4 SPD handling, register
calculation and programming.

Signed-off-by: York Sun <yorksun@freescale.com>
diff --git a/drivers/ddr/fsl/util.c b/drivers/ddr/fsl/util.c
index ad53658..7a22aa3 100644
--- a/drivers/ddr/fsl/util.c
+++ b/drivers/ddr/fsl/util.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -23,6 +23,18 @@
 
 #define ULL_8FS 0xFFFFFFFFULL
 
+u32 fsl_ddr_get_version(void)
+{
+	struct ccsr_ddr __iomem *ddr;
+	u32 ver_major_minor_errata;
+
+	ddr = (void *)_DDR_ADDR;
+	ver_major_minor_errata = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8;
+	ver_major_minor_errata |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8;
+
+	return ver_major_minor_errata;
+}
+
 /*
  * Round up mclk_ps to nearest 1 ps in memory controller code
  * if the error is 0.5ps or more.
@@ -175,6 +187,9 @@
 	case SDRAM_TYPE_DDR3:
 		puts("3");
 		break;
+	case SDRAM_TYPE_DDR4:
+		puts("4");
+		break;
 	default:
 		puts("?");
 		break;
@@ -188,9 +203,12 @@
 		puts(", 64-bit");
 
 	/* Calculate CAS latency based on timing cfg values */
-	cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf) + 1;
-	if ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 1)
-		cas_lat += (8 << 1);
+	cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf);
+	if (fsl_ddr_get_version() <= 0x40400)
+		cas_lat += 1;
+	else
+		cas_lat += 2;
+	cas_lat += ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 3) << 4;
 	printf(", CL=%d", cas_lat >> 1);
 	if (cas_lat & 0x1)
 		puts(".5");