diff options
-rw-r--r-- | arch/arm/cpu/armv8/fsl-layerscape/fdt.c | 150 | ||||
-rw-r--r-- | drivers/net/pfe_eth/pfe_firmware.c | 60 |
2 files changed, 207 insertions, 3 deletions
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c index 7f29aa4725..f1624ff30a 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c @@ -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 diff --git a/drivers/net/pfe_eth/pfe_firmware.c b/drivers/net/pfe_eth/pfe_firmware.c index eee70a2e73..ac86e33c55 100644 --- a/drivers/net/pfe_eth/pfe_firmware.c +++ b/drivers/net/pfe_eth/pfe_firmware.c @@ -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"; |