]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
armv8: ls1012a: Pass PPFE firmware to Linux through FDT
authorChaitanya Sakinam <chaitanya.sakinam@nxp.com>
Fri, 7 May 2021 04:22:05 +0000 (12:22 +0800)
committerPriyanka Jain <priyanka.jain@nxp.com>
Thu, 17 Jun 2021 06:16:11 +0000 (11:46 +0530)
Read Linux PPFE firmware from flash partition and pass it to Linux through
FDT entry. So that we can avoid placing PPFE firmware in Linux rootfs.
(FDT may increase at max by 64KB)

Signed-off-by: Chaitanya Sakinam <chaitanya.sakinam@nxp.com>
Signed-off-by: Anji J <anji.jagarlmudi@nxp.com>
Signed-off-by: Biwen Li <biwen.li@nxp.com>
Reviewed-by: Priyanka Jain <priyanka.jain@nxp.com>
arch/arm/cpu/armv8/fsl-layerscape/fdt.c
drivers/net/pfe_eth/pfe_firmware.c

index 7f29aa4725a126da391638034a210082f83ae654..f1624ff30ae8858850c45d31cd377f7dcc525468 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2014-2015 Freescale Semiconductor, Inc.
- * Copyright 2020 NXP
+ * Copyright 2020-2021 NXP
  */
 
 #include <common.h>
@@ -478,6 +478,151 @@ static bool crypto_is_disabled(unsigned int svr)
        return false;
 }
 
+#ifdef CONFIG_FSL_PFE
+void pfe_set_firmware_in_fdt(void *blob, int pfenode, void *pfw, char *pename,
+                            unsigned int len)
+{
+       int rc, fwnode;
+       unsigned int phandle;
+       char subnode_str[32], prop_str[32], phandle_str[32], s[64];
+
+       sprintf(subnode_str, "pfe-%s-firmware", pename);
+       sprintf(prop_str, "fsl,pfe-%s-firmware", pename);
+       sprintf(phandle_str, "fsl,%s-firmware", pename);
+
+       /*Add PE FW to fdt.*/
+       /* Increase the size of the fdt to make room for the node. */
+       rc = fdt_increase_size(blob, len);
+       if (rc < 0) {
+               printf("Unable to make room for %s firmware: %s\n", pename,
+                      fdt_strerror(rc));
+               return;
+       }
+
+       /* Create the firmware node. */
+       fwnode = fdt_add_subnode(blob, pfenode, subnode_str);
+       if (fwnode < 0) {
+               fdt_get_path(blob, pfenode, s, sizeof(s));
+               printf("Could not add firmware node to %s: %s\n", s,
+                      fdt_strerror(fwnode));
+               return;
+       }
+
+       rc = fdt_setprop_string(blob, fwnode, "compatible", prop_str);
+       if (rc < 0) {
+               fdt_get_path(blob, fwnode, s, sizeof(s));
+               printf("Could not add compatible property to node %s: %s\n", s,
+                      fdt_strerror(rc));
+               return;
+       }
+
+       rc = fdt_setprop_u32(blob, fwnode, "length", len);
+       if (rc < 0) {
+               fdt_get_path(blob, fwnode, s, sizeof(s));
+               printf("Could not add compatible property to node %s: %s\n", s,
+                      fdt_strerror(rc));
+               return;
+       }
+
+       /*create phandle and set the property*/
+       phandle = fdt_create_phandle(blob, fwnode);
+       if (!phandle) {
+               fdt_get_path(blob, fwnode, s, sizeof(s));
+               printf("Could not add phandle property to node %s: %s\n", s,
+                      fdt_strerror(rc));
+               return;
+       }
+
+       rc = fdt_setprop(blob, fwnode, phandle_str, pfw, len);
+       if (rc < 0) {
+               fdt_get_path(blob, fwnode, s, sizeof(s));
+               printf("Could not add firmware property to node %s: %s\n", s,
+                      fdt_strerror(rc));
+               return;
+       }
+}
+
+void fdt_fixup_pfe_firmware(void *blob)
+{
+       int pfenode;
+       unsigned int len_class = 0, len_tmu = 0, len_util = 0;
+       const char *p;
+       void *pclassfw, *ptmufw, *putilfw;
+
+       /* The first PFE we find, will contain the actual firmware. */
+       pfenode = fdt_node_offset_by_compatible(blob, -1, "fsl,pfe");
+       if (pfenode < 0)
+               /* Exit silently if there are no PFE devices */
+               return;
+
+       /* If we already have a firmware node, then also exit silently. */
+       if (fdt_node_offset_by_compatible(blob, -1,
+                                         "fsl,pfe-class-firmware") > 0)
+               return;
+
+       /* If the environment variable is not set, then exit silently */
+       p = env_get("class_elf_firmware");
+       if (!p)
+               return;
+
+       pclassfw = (void *)simple_strtoul(p, NULL, 16);
+       if (!pclassfw)
+               return;
+
+       p = env_get("class_elf_size");
+       if (!p)
+               return;
+       len_class = simple_strtoul(p, NULL, 16);
+
+       /* If the environment variable is not set, then exit silently */
+       p = env_get("tmu_elf_firmware");
+       if (!p)
+               return;
+
+       ptmufw = (void *)simple_strtoul(p, NULL, 16);
+       if (!ptmufw)
+               return;
+
+       p = env_get("tmu_elf_size");
+       if (!p)
+               return;
+       len_tmu = simple_strtoul(p, NULL, 16);
+
+       if (len_class == 0 || len_tmu == 0) {
+               printf("PFE FW corrupted. CLASS FW size %d, TMU FW size %d\n",
+                      len_class, len_tmu);
+               return;
+       }
+
+       /*Add CLASS FW to fdt.*/
+       pfe_set_firmware_in_fdt(blob, pfenode, pclassfw, "class", len_class);
+
+       /*Add TMU FW to fdt.*/
+       pfe_set_firmware_in_fdt(blob, pfenode, ptmufw, "tmu", len_tmu);
+
+       /* Util PE firmware is handled separately as it is not a usual case*/
+       p = env_get("util_elf_firmware");
+       if (!p)
+               return;
+
+       putilfw = (void *)simple_strtoul(p, NULL, 16);
+       if (!putilfw)
+               return;
+
+       p = env_get("util_elf_size");
+       if (!p)
+               return;
+       len_util = simple_strtoul(p, NULL, 16);
+
+       if (len_util) {
+               printf("PFE Util PE firmware is not added to FDT.\n");
+               return;
+       }
+
+       pfe_set_firmware_in_fdt(blob, pfenode, putilfw, "util", len_util);
+}
+#endif
+
 void ft_cpu_setup(void *blob, struct bd_info *bd)
 {
        struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
@@ -534,6 +679,9 @@ void ft_cpu_setup(void *blob, struct bd_info *bd)
 #ifdef CONFIG_SYS_DPAA_FMAN
        fdt_fixup_fman_firmware(blob);
 #endif
+#ifdef CONFIG_FSL_PFE
+       fdt_fixup_pfe_firmware(blob);
+#endif
 #ifndef CONFIG_ARCH_LS1012A
        fsl_fdt_disable_usb(blob);
 #endif
index eee70a2e73a2091720ac1655152f7e82fc1002d5..ac86e33c5507ec588711b770bc9440adcf7ed4b8 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2015-2016 Freescale Semiconductor, Inc.
- * Copyright 2017 NXP
+ * Copyright 2017,2021 NXP
  */
 
 /*
@@ -262,7 +262,8 @@ int pfe_firmware_init(void)
        uintptr_t pfe_img_addr = 0;
 #endif
        int ret = 0;
-       int fw_count;
+       int fw_count, max_fw_count;
+       const char *p;
 
        ret = pfe_spi_flash_init();
        if (ret)
@@ -293,6 +294,61 @@ int pfe_firmware_init(void)
        }
 #endif
 
+       p = env_get("load_util");
+       if (!p) {
+               max_fw_count = 2;
+       } else {
+               max_fw_count = simple_strtoul(p, NULL, 10);
+               if (max_fw_count)
+                       max_fw_count = 3;
+               else
+                       max_fw_count = 2;
+       }
+
+       for (fw_count = 0; fw_count < max_fw_count; fw_count++) {
+               switch (fw_count) {
+               case 0:
+                       pfe_firmware_name = "class_slowpath";
+                       break;
+               case 1:
+                       pfe_firmware_name = "tmu_slowpath";
+                       break;
+               case 2:
+                       pfe_firmware_name = "util_slowpath";
+                       break;
+               }
+
+               if (pfe_get_fw(&raw_image_addr, &raw_image_size,
+                              pfe_firmware_name)) {
+                       printf("%s firmware couldn't be found in FIT image\n",
+                              pfe_firmware_name);
+                       break;
+               }
+               pfe_firmware = malloc(raw_image_size);
+               if (!pfe_firmware)
+                       return -ENOMEM;
+               memcpy((void *)pfe_firmware, (void *)raw_image_addr,
+                      raw_image_size);
+
+               switch (fw_count) {
+               case 0:
+                       env_set_addr("class_elf_firmware", pfe_firmware);
+                       env_set_addr("class_elf_size", (void *)raw_image_size);
+                       break;
+               case 1:
+                       env_set_addr("tmu_elf_firmware", pfe_firmware);
+                       env_set_addr("tmu_elf_size", (void *)raw_image_size);
+                       break;
+               case 2:
+                       env_set_addr("util_elf_firmware", pfe_firmware);
+                       env_set_addr("util_elf_size", (void *)raw_image_size);
+                       break;
+               }
+       }
+
+       raw_image_addr = NULL;
+       pfe_firmware = NULL;
+       raw_image_size = 0;
        for (fw_count = 0; fw_count < 2; fw_count++) {
                if (fw_count == 0)
                        pfe_firmware_name = "class";