[PATCH] armv8: ls1012a: Pass PPFE firmware to Linux through FDT.

Chaitanya Sakinam chaitanya.sakinam at nxp.com
Tue Apr 28 11:54:38 CEST 2020


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.

Signed-off-by: Chaitanya Sakinam <chaitanya.sakinam at nxp.com>
Signed-off-by: Anji J <anji.jagarlmudi at nxp.com>
---
 arch/arm/cpu/armv8/fsl-layerscape/fdt.c | 148 ++++++++++++++++++++++++++++++++
 drivers/net/pfe_eth/pfe_firmware.c      |  58 ++++++++++++-
 2 files changed, 205 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
index a1d5dc6..f874b1f 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
@@ -427,6 +427,151 @@ __weak void fdt_fixup_ecam(void *blob)
 }
 #endif
 
+#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, bd_t *bd)
 {
 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
@@ -479,6 +624,9 @@ void ft_cpu_setup(void *blob, bd_t *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 adb2d06..947e2cd 100644
--- a/drivers/net/pfe_eth/pfe_firmware.c
+++ b/drivers/net/pfe_eth/pfe_firmware.c
@@ -181,7 +181,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_fit_check();
 	if (ret)
@@ -208,6 +209,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";
-- 
2.7.4



More information about the U-Boot mailing list