xilinx: board: Add support for additional card detection
authorMichal Simek <michal.simek@xilinx.com>
Mon, 3 Aug 2020 10:57:05 +0000 (12:57 +0200)
committerMichal Simek <michal.simek@xilinx.com>
Tue, 27 Oct 2020 07:13:32 +0000 (08:13 +0100)
The most of Xilinx evaluation boards have FMC connectors which contain
small eeprom for card identification. That's why read content of eeprom and
record it.
Also generate cardX_ variables for easier script handling.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
board/xilinx/common/board.c

index 0aed845..0d0c21c 100644 (file)
@@ -62,7 +62,8 @@ struct xilinx_board_description {
        u8 mac_addr[EEPROM_HDR_NO_OF_MAC_ADDR][EEPROM_HDR_ETH_ALEN + 1];
 };
 
-static struct xilinx_board_description *board_info;
+static int highest_id = -1;
+static struct xilinx_board_description **board_info;
 
 #define XILINX_I2C_DETECTION_BITS      8
 
@@ -191,15 +192,16 @@ static int xilinx_read_eeprom_single(char *name,
 
 __maybe_unused int xilinx_read_eeprom(void)
 {
-       int id, highest_id;
+       int id, ret;
        char name_buf[8]; /* 8 bytes should be enough for nvmem+number */
+       struct xilinx_board_description *desc;
 
        highest_id = dev_read_alias_highest_id("nvmem");
        /* No nvmem aliases present */
        if (highest_id < 0)
                return -EINVAL;
 
-       board_info = calloc(1, sizeof(*board_info));
+       board_info = calloc(1, sizeof(desc) * highest_id);
        if (!board_info)
                return -ENOMEM;
 
@@ -209,12 +211,28 @@ __maybe_unused int xilinx_read_eeprom(void)
        for (id = 0; id <= highest_id; id++) {
                snprintf(name_buf, sizeof(name_buf), "nvmem%d", id);
 
+               /* Alloc structure */
+               desc = board_info[id];
+               if (!desc) {
+                       desc = calloc(1, sizeof(*desc));
+                       if (!desc)
+                               return -ENOMEM;
+
+                       board_info[id] = desc;
+               }
+
                /* Ignoring return value for supporting multiple chips */
-               xilinx_read_eeprom_single(name_buf, board_info);
+               ret = xilinx_read_eeprom_single(name_buf, desc);
+               if (ret) {
+                       free(desc);
+                       board_info[id] = NULL;
+               }
        }
 
-       if (board_info->header != EEPROM_HEADER_MAGIC)
-               free(board_info);
+       /*
+        * Consider to clean board_info structure when board/cards are not
+        * detected.
+        */
 
        return 0;
 }
@@ -253,10 +271,23 @@ void *board_fdt_blob_setup(void)
 }
 #endif
 
+static int env_set_by_index(const char *name, int index, char *data)
+{
+       char var[32];
+
+       if (!index)
+               sprintf(var, "board_%s", name);
+       else
+               sprintf(var, "card%d_%s", index, name);
+
+       return env_set(var, data);
+}
+
 int board_late_init_xilinx(void)
 {
        u32 ret = 0;
-       int i;
+       int i, id, macid = 0;
+       struct xilinx_board_description *desc;
        phys_size_t bootm_size = gd->ram_size;
 
        if (CONFIG_IS_ENABLED(ARCH_ZYNQ))
@@ -267,27 +298,33 @@ int board_late_init_xilinx(void)
        ret |= env_set_addr("bootm_low", (void *)gd->ram_base);
        ret |= env_set_addr("bootm_size", (void *)bootm_size);
 
-       if (board_info) {
-               if (board_info->manufacturer)
-                       ret |= env_set("manufacturer",
-                                      board_info->manufacturer);
-               if (board_info->name)
-                       ret |= env_set("board_name", board_info->name);
-               if (board_info->revision)
-                       ret |= env_set("board_rev", board_info->revision);
-               if (board_info->serial)
-                       ret |= env_set("board_serial", board_info->serial);
-
-               for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) {
-                       if (!board_info->mac_addr[i])
-                               continue;
+       for (id = 0; id <= highest_id; id++) {
+               desc = board_info[id];
+               if (desc && desc->header == EEPROM_HEADER_MAGIC) {
+                       if (desc->manufacturer[0])
+                               ret |= env_set_by_index("manufacturer", id,
+                                                       desc->manufacturer);
+                       if (desc->name[0])
+                               ret |= env_set_by_index("name", id,
+                                                       desc->name);
+                       if (desc->revision[0])
+                               ret |= env_set_by_index("rev", id,
+                                                       desc->revision);
+                       if (desc->serial[0])
+                               ret |= env_set_by_index("serial", id,
+                                                       desc->serial);
 
                        if (!CONFIG_IS_ENABLED(NET))
                                continue;
 
-                       if (is_valid_ethaddr((const u8 *)board_info->mac_addr[i]))
-                               ret |= eth_env_set_enetaddr_by_index("eth", i,
-                                               board_info->mac_addr[i]);
+                       for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) {
+                               if (!desc->mac_addr[i])
+                                       continue;
+
+                               if (is_valid_ethaddr((const u8 *)desc->mac_addr[i]))
+                                       ret |= eth_env_set_enetaddr_by_index("eth",
+                                                       macid++, desc->mac_addr[i]);
+                       }
                }
        }