xilinx: zynqmp: refactor silicon name function
authorIbai Erkiaga <ibai.erkiaga-elorza@xilinx.com>
Tue, 4 Aug 2020 22:17:31 +0000 (23:17 +0100)
committerMichal Simek <michal.simek@xilinx.com>
Wed, 23 Sep 2020 08:31:40 +0000 (10:31 +0200)
Current algorithm used to get the silicon name is bit complicated and
hard to follow. Updated to use more straightforward mechanism based on
the Device ID code table (Table 1-2). The full IDCODE register is used
(except device revision bits [31:28]) to get the device name and IDCODE2
value is used for identifying the variant.

Additionally to make the algorithm bit more clear it also save some space
as the devices table is slightly bit smaller.

Signed-off-by: Ibai Erkiaga <ibai.erkiaga-elorza@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
board/xilinx/zynqmp/zynqmp.c

index b4e7301..006284f 100644 (file)
 
 #include "pm_cfg_obj.h"
 
+#define ZYNQMP_VERSION_SIZE    7
+#define EFUSE_VCU_DIS_MASK     0x100
+#define EFUSE_VCU_DIS_SHIFT    8
+#define EFUSE_GPU_DIS_MASK     0x20
+#define EFUSE_GPU_DIS_SHIFT    5
+#define IDCODE2_PL_INIT_MASK   0x200
+#define IDCODE2_PL_INIT_SHIFT  9
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
-    !defined(CONFIG_SPL_BUILD)
+    !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \
+    defined(CONFIG_SPL_BUILD))
+
 static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
 
+enum {
+       ZYNQMP_VARIANT_EG = BIT(0U),
+       ZYNQMP_VARIANT_EV = BIT(1U),
+       ZYNQMP_VARIANT_CG = BIT(2U),
+       ZYNQMP_VARIANT_DR = BIT(3U),
+};
+
 static const struct {
        u32 id;
-       u32 ver;
-       char *name;
-       bool evexists;
+       u8 device;
+       u8 variants;
 } zynqmp_devices[] = {
        {
-               .id = 0x10,
-               .name = "3eg",
-       },
-       {
-               .id = 0x10,
-               .ver = 0x2c,
-               .name = "3cg",
-       },
-       {
-               .id = 0x11,
-               .name = "2eg",
-       },
-       {
-               .id = 0x11,
-               .ver = 0x2c,
-               .name = "2cg",
-       },
-       {
-               .id = 0x20,
-               .name = "5ev",
-               .evexists = 1,
-       },
-       {
-               .id = 0x20,
-               .ver = 0x100,
-               .name = "5eg",
-               .evexists = 1,
-       },
-       {
-               .id = 0x20,
-               .ver = 0x12c,
-               .name = "5cg",
-               .evexists = 1,
-       },
-       {
-               .id = 0x21,
-               .name = "4ev",
-               .evexists = 1,
-       },
-       {
-               .id = 0x21,
-               .ver = 0x100,
-               .name = "4eg",
-               .evexists = 1,
-       },
-       {
-               .id = 0x21,
-               .ver = 0x12c,
-               .name = "4cg",
-               .evexists = 1,
-       },
-       {
-               .id = 0x30,
-               .name = "7ev",
-               .evexists = 1,
+               .id = 0x04711093,
+               .device = 2,
+               .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
        },
        {
-               .id = 0x30,
-               .ver = 0x100,
-               .name = "7eg",
-               .evexists = 1,
+               .id = 0x04710093,
+               .device = 3,
+               .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
        },
        {
-               .id = 0x30,
-               .ver = 0x12c,
-               .name = "7cg",
-               .evexists = 1,
+               .id = 0x04721093,
+               .device = 4,
+               .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG |
+                       ZYNQMP_VARIANT_EV,
        },
        {
-               .id = 0x38,
-               .name = "9eg",
+               .id = 0x04720093,
+               .device = 5,
+               .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG |
+                       ZYNQMP_VARIANT_EV,
        },
        {
-               .id = 0x38,
-               .ver = 0x2c,
-               .name = "9cg",
+               .id = 0x04739093,
+               .device = 6,
+               .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
        },
        {
-               .id = 0x39,
-               .name = "6eg",
+               .id = 0x04730093,
+               .device = 7,
+               .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG |
+                       ZYNQMP_VARIANT_EV,
        },
        {
-               .id = 0x39,
-               .ver = 0x2c,
-               .name = "6cg",
+               .id = 0x04738093,
+               .device = 9,
+               .variants = ZYNQMP_VARIANT_EG,
        },
        {
-               .id = 0x40,
-               .name = "11eg",
-       },
-       { /* For testing purpose only */
-               .id = 0x50,
-               .ver = 0x2c,
-               .name = "15cg",
+               .id = 0x04740093,
+               .device = 11,
+               .variants = ZYNQMP_VARIANT_EG,
        },
        {
-               .id = 0x50,
-               .name = "15eg",
+               .id = 0x04750093,
+               .device = 15,
+               .variants = ZYNQMP_VARIANT_EG,
        },
        {
-               .id = 0x58,
-               .name = "19eg",
+               .id = 0x04759093,
+               .device = 17,
+               .variants = ZYNQMP_VARIANT_EG,
        },
        {
-               .id = 0x59,
-               .name = "17eg",
+               .id = 0x04758093,
+               .device = 19,
+               .variants = ZYNQMP_VARIANT_EG,
        },
        {
-               .id = 0x61,
-               .name = "21dr",
+               .id = 0x047E1093,
+               .device = 21,
+               .variants = ZYNQMP_VARIANT_DR,
        },
        {
-               .id = 0x63,
-               .name = "23dr",
+               .id = 0x047E3093,
+               .device = 23,
+               .variants = ZYNQMP_VARIANT_DR,
        },
        {
-               .id = 0x65,
-               .name = "25dr",
+               .id = 0x047E5093,
+               .device = 25,
+               .variants = ZYNQMP_VARIANT_DR,
        },
        {
-               .id = 0x64,
-               .name = "27dr",
+               .id = 0x047E4093,
+               .device = 27,
+               .variants = ZYNQMP_VARIANT_DR,
        },
        {
-               .id = 0x60,
-               .name = "28dr",
+               .id = 0x047E0093,
+               .device = 28,
+               .variants = ZYNQMP_VARIANT_DR,
        },
        {
-               .id = 0x62,
-               .name = "29dr",
+               .id = 0x047E2093,
+               .device = 29,
+               .variants = ZYNQMP_VARIANT_DR,
        },
        {
-               .id = 0x66,
-               .name = "39dr",
+               .id = 0x047E6093,
+               .device = 39,
+               .variants = ZYNQMP_VARIANT_DR,
        },
        {
-               .id = 0x7b,
-               .name = "48dr",
+               .id = 0x047FB093,
+               .device = 48,
+               .variants = ZYNQMP_VARIANT_DR,
        },
        {
-               .id = 0x7e,
-               .name = "49dr",
+               .id = 0x047FE093,
+               .device = 49,
+               .variants = ZYNQMP_VARIANT_DR,
        },
 };
-#endif
-
-#define ZYNQMP_VERSION_SIZE            9
-#define ZYNQMP_PL_STATUS_BIT           9
-#define ZYNQMP_IPDIS_VCU_BIT           8
-#define ZYNQMP_PL_STATUS_MASK          BIT(ZYNQMP_PL_STATUS_BIT)
-#define ZYNQMP_CSU_VERSION_MASK                ~(ZYNQMP_PL_STATUS_MASK)
-#define ZYNQMP_CSU_VCUDIS_VER_MASK     ZYNQMP_CSU_VERSION_MASK & \
-                                       ~BIT(ZYNQMP_IPDIS_VCU_BIT)
-#define MAX_VARIANTS_EV                        3
 
-#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
-       !defined(CONFIG_SPL_BUILD)
 static char *zynqmp_get_silicon_idcode_name(void)
 {
-       u32 i, id, ver, j;
-       char *buf;
+       u32 i;
+       u32 idcode, idcode2;
        static char name[ZYNQMP_VERSION_SIZE];
        u32 ret_payload[PAYLOAD_ARG_CNT];
 
@@ -226,58 +189,68 @@ static char *zynqmp_get_silicon_idcode_name(void)
         * payload[2][29] = PL_INIT
         */
 
-       /* Get IDCODE field */
-       id = ret_payload[1];
-       id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK;
-       id >>=  ZYNQMP_CSU_IDCODE_SVD_SHIFT;
-
-       /* Shift silicon version info */
-       ver = ret_payload[2] >> ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
-
-       debug("%s, ID: 0x%0X, Ver: 0x%0X\r\n", __func__, id, ver);
+       idcode  = ret_payload[1];
+       idcode2 = ret_payload[2] >> ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
+       debug("%s, IDCODE: 0x%0X, IDCODE2: 0x%0X\r\n", __func__, idcode,
+             idcode2);
 
        for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
-               if (zynqmp_devices[i].id == id) {
-                       if (zynqmp_devices[i].evexists &&
-                           !(ver & ZYNQMP_PL_STATUS_MASK))
-                               break;
-                       if (zynqmp_devices[i].ver == (ver &
-                           ZYNQMP_CSU_VERSION_MASK))
-                               break;
-               }
+               if (zynqmp_devices[i].id == (idcode & 0x0FFFFFFF))
+                       break;
        }
 
        if (i >= ARRAY_SIZE(zynqmp_devices))
                return "unknown";
 
+       /* Add device prefix to the name */
        strncat(name, "zu", 2);
-       if (!zynqmp_devices[i].evexists ||
-           (ver & ZYNQMP_PL_STATUS_MASK)) {
-               strncat(name, zynqmp_devices[i].name,
-                       ZYNQMP_VERSION_SIZE - 3);
-               return name;
-       }
-
-       /*
-        * Here we are means, PL not powered up and ev variant
-        * exists. So, we need to ignore VCU disable bit(8) in
-        * version and findout if its CG or EG/EV variant.
-        */
-       for (j = 0; j < MAX_VARIANTS_EV; j++, i++) {
-               if ((zynqmp_devices[i].ver & ~BIT(ZYNQMP_IPDIS_VCU_BIT)) ==
-                   (ver & ZYNQMP_CSU_VCUDIS_VER_MASK)) {
-                       strncat(name, zynqmp_devices[i].name,
-                               ZYNQMP_VERSION_SIZE - 3);
-                       break;
+       strncat(&name[2], simple_itoa(zynqmp_devices[i].device), 2);
+
+       if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_EV) {
+               /* Devices with EV variant might be EG/CG/EV family */
+               if (idcode2 & IDCODE2_PL_INIT_MASK) {
+                       u32 family = ((idcode2 & EFUSE_VCU_DIS_MASK) >>
+                                     EFUSE_VCU_DIS_SHIFT) << 1 |
+                                    ((idcode2 & EFUSE_GPU_DIS_MASK) >>
+                                     EFUSE_GPU_DIS_SHIFT);
+
+                       /*
+                        * Get family name based on extended idcode values as
+                        * determined on UG1087, EXTENDED_IDCODE register
+                        * description
+                        */
+                       switch (family) {
+                       case 0x00:
+                               strncat(name, "ev", 2);
+                               break;
+                       case 0x10:
+                               strncat(name, "eg", 2);
+                               break;
+                       case 0x11:
+                               strncat(name, "cg", 2);
+                               break;
+                       default:
+                               /* Do not append family name*/
+                               break;
+                       }
+               } else {
+                       /*
+                        * When PL powered down the VCU Disable efuse cannot be
+                        * read. So, ignore the bit and just findout if it is CG
+                        * or EG/EV variant.
+                        */
+                       strncat(name, (idcode2 & EFUSE_GPU_DIS_MASK) ? "cg" :
+                               "e", 2);
                }
-       }
-
-       if (j >= MAX_VARIANTS_EV)
-               return "unknown";
-
-       if (strstr(name, "eg") || strstr(name, "ev")) {
-               buf = strstr(name, "e");
-               *buf = '\0';
+       } else if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_CG) {
+               /* Devices with CG variant might be EG or CG family */
+               strncat(name, (idcode2 & EFUSE_GPU_DIS_MASK) ? "cg" : "eg", 2);
+       } else if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_EG) {
+               strncat(name, "eg", 2);
+       } else if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_DR) {
+               strncat(name, "dr", 2);
+       } else {
+               debug("Variant not identified\n");
        }
 
        return name;