arm64: zynqmp: Add support for CG/EG/EV device detection

Version string has unused fields 31:20 which can be used for exporting 9
bits from efuse IPDISABLE regs to recognize eg/cg/ev devices.

These efuse bits are setup for certain devices.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
diff --git a/arch/arm/include/asm/arch-zynqmp/hardware.h b/arch/arm/include/asm/arch-zynqmp/hardware.h
index 5f2c98d..327046b 100644
--- a/arch/arm/include/asm/arch-zynqmp/hardware.h
+++ b/arch/arm/include/asm/arch-zynqmp/hardware.h
@@ -128,6 +128,8 @@
 #define ZYNQMP_CSU_VERSION_VELOCE	0x2
 #define ZYNQMP_CSU_VERSION_QEMU		0x3
 
+#define ZYNQMP_CSU_VERSION_EMPTY_SHIFT		20
+
 #define ZYNQMP_SILICON_VER_MASK		0xF000
 #define ZYNQMP_SILICON_VER_SHIFT	12
 
diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
index db1d5ef..f256c7d 100644
--- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
+++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
@@ -15,6 +15,7 @@
 enum {
 	IDCODE,
 	VERSION,
+	IDCODE2,
 };
 
 enum {
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index 5e22cc5..2b1d811 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -28,6 +28,7 @@
 
 static const struct {
 	u32 id;
+	u32 ver;
 	char *name;
 } zynqmp_devices[] = {
 	{
@@ -35,33 +36,88 @@
 		.name = "3eg",
 	},
 	{
+		.id = 0x10,
+		.ver = 0x2c,
+		.name = "3cg",
+	},
+	{
 		.id = 0x11,
 		.name = "2eg",
 	},
 	{
+		.id = 0x11,
+		.ver = 0x2c,
+		.name = "2cg",
+	},
+	{
 		.id = 0x20,
 		.name = "5ev",
 	},
 	{
+		.id = 0x20,
+		.ver = 0x100,
+		.name = "5eg",
+	},
+	{
+		.id = 0x20,
+		.ver = 0x12c,
+		.name = "5cg",
+	},
+	{
 		.id = 0x21,
 		.name = "4ev",
 	},
 	{
+		.id = 0x21,
+		.ver = 0x100,
+		.name = "4eg",
+	},
+	{
+		.id = 0x21,
+		.ver = 0x12c,
+		.name = "4cg",
+	},
+	{
 		.id = 0x30,
 		.name = "7ev",
 	},
 	{
+		.id = 0x30,
+		.ver = 0x100,
+		.name = "7eg",
+	},
+	{
+		.id = 0x30,
+		.ver = 0x12c,
+		.name = "7cg",
+	},
+	{
 		.id = 0x38,
 		.name = "9eg",
 	},
 	{
+		.id = 0x38,
+		.ver = 0x2c,
+		.name = "9cg",
+	},
+	{
 		.id = 0x39,
 		.name = "6eg",
 	},
 	{
+		.id = 0x39,
+		.ver = 0x2c,
+		.name = "6cg",
+	},
+	{
 		.id = 0x40,
 		.name = "11eg",
 	},
+	{ /* For testing purpose only */
+		.id = 0x50,
+		.ver = 0x2c,
+		.name = "15cg",
+	},
 	{
 		.id = 0x50,
 		.name = "15eg",
@@ -95,6 +151,7 @@
 		 * regs[0][31:0]  = status of the operation
 		 * regs[0][63:32] = CSU.IDCODE register
 		 * regs[1][31:0]  = CSU.version register
+		 * regs[1][63:32] = CSU.IDCODE2 register
 		 */
 		switch (id) {
 		case IDCODE:
@@ -109,6 +166,11 @@
 			regs.regs[1] &= ZYNQMP_CSU_SILICON_VER_MASK;
 			val = regs.regs[1];
 			break;
+		case IDCODE2:
+			regs.regs[1] = lower_32_bits(regs.regs[1]);
+			regs.regs[1] >>= ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
+			val = regs.regs[1];
+			break;
 		default:
 			printf("%s, Invalid Req:0x%x\n", __func__, id);
 		}
@@ -136,11 +198,13 @@
 	!defined(CONFIG_SPL_BUILD)
 static char *zynqmp_get_silicon_idcode_name(void)
 {
-	u32 i, id;
+	u32 i, id, ver;
 
 	id = chip_id(IDCODE);
+	ver = chip_id(IDCODE2);
+
 	for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
-		if (zynqmp_devices[i].id == id)
+		if (zynqmp_devices[i].id == id && zynqmp_devices[i].ver == ver)
 			return zynqmp_devices[i].name;
 	}
 	return "unknown";