Commit 03effad96d429331a075573083872675b4b60862
Committed by
Priyanka Jain
1 parent
242e690962
Exists in
smarc_8mq_lf_v2020.04
and in
4 other branches
armv8: ls1012a: Pass PPFE firmware to Linux through FDT.
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@nxp.com> Signed-off-by: Anji J <anji.jagarlmudi@nxp.com>
Showing 2 changed files with 205 additions and 1 deletions Side-by-side Diff
arch/arm/cpu/armv8/fsl-layerscape/fdt.c
... | ... | @@ -428,6 +428,151 @@ |
428 | 428 | } |
429 | 429 | #endif |
430 | 430 | |
431 | +#ifdef CONFIG_FSL_PFE | |
432 | +void pfe_set_firmware_in_fdt(void *blob, int pfenode, void *pfw, char *pename, | |
433 | + unsigned int len) | |
434 | +{ | |
435 | + int rc, fwnode; | |
436 | + unsigned int phandle; | |
437 | + char subnode_str[32], prop_str[32], phandle_str[32], s[64]; | |
438 | + | |
439 | + sprintf(subnode_str, "pfe-%s-firmware", pename); | |
440 | + sprintf(prop_str, "fsl,pfe-%s-firmware", pename); | |
441 | + sprintf(phandle_str, "fsl,%s-firmware", pename); | |
442 | + | |
443 | + /*Add PE FW to fdt.*/ | |
444 | + /* Increase the size of the fdt to make room for the node. */ | |
445 | + rc = fdt_increase_size(blob, len); | |
446 | + if (rc < 0) { | |
447 | + printf("Unable to make room for %s firmware: %s\n", pename, | |
448 | + fdt_strerror(rc)); | |
449 | + return; | |
450 | + } | |
451 | + | |
452 | + /* Create the firmware node. */ | |
453 | + fwnode = fdt_add_subnode(blob, pfenode, subnode_str); | |
454 | + if (fwnode < 0) { | |
455 | + fdt_get_path(blob, pfenode, s, sizeof(s)); | |
456 | + printf("Could not add firmware node to %s: %s\n", s, | |
457 | + fdt_strerror(fwnode)); | |
458 | + return; | |
459 | + } | |
460 | + | |
461 | + rc = fdt_setprop_string(blob, fwnode, "compatible", prop_str); | |
462 | + if (rc < 0) { | |
463 | + fdt_get_path(blob, fwnode, s, sizeof(s)); | |
464 | + printf("Could not add compatible property to node %s: %s\n", s, | |
465 | + fdt_strerror(rc)); | |
466 | + return; | |
467 | + } | |
468 | + | |
469 | + rc = fdt_setprop_u32(blob, fwnode, "length", len); | |
470 | + if (rc < 0) { | |
471 | + fdt_get_path(blob, fwnode, s, sizeof(s)); | |
472 | + printf("Could not add compatible property to node %s: %s\n", s, | |
473 | + fdt_strerror(rc)); | |
474 | + return; | |
475 | + } | |
476 | + | |
477 | + /*create phandle and set the property*/ | |
478 | + phandle = fdt_create_phandle(blob, fwnode); | |
479 | + if (!phandle) { | |
480 | + fdt_get_path(blob, fwnode, s, sizeof(s)); | |
481 | + printf("Could not add phandle property to node %s: %s\n", s, | |
482 | + fdt_strerror(rc)); | |
483 | + return; | |
484 | + } | |
485 | + | |
486 | + rc = fdt_setprop(blob, fwnode, phandle_str, pfw, len); | |
487 | + if (rc < 0) { | |
488 | + fdt_get_path(blob, fwnode, s, sizeof(s)); | |
489 | + printf("Could not add firmware property to node %s: %s\n", s, | |
490 | + fdt_strerror(rc)); | |
491 | + return; | |
492 | + } | |
493 | +} | |
494 | + | |
495 | +void fdt_fixup_pfe_firmware(void *blob) | |
496 | +{ | |
497 | + int pfenode; | |
498 | + unsigned int len_class = 0, len_tmu = 0, len_util = 0; | |
499 | + const char *p; | |
500 | + void *pclassfw, *ptmufw, *putilfw; | |
501 | + | |
502 | + /* The first PFE we find, will contain the actual firmware. */ | |
503 | + pfenode = fdt_node_offset_by_compatible(blob, -1, "fsl,pfe"); | |
504 | + if (pfenode < 0) | |
505 | + /* Exit silently if there are no PFE devices */ | |
506 | + return; | |
507 | + | |
508 | + /* If we already have a firmware node, then also exit silently. */ | |
509 | + if (fdt_node_offset_by_compatible(blob, -1, | |
510 | + "fsl,pfe-class-firmware") > 0) | |
511 | + return; | |
512 | + | |
513 | + /* If the environment variable is not set, then exit silently */ | |
514 | + p = env_get("class_elf_firmware"); | |
515 | + if (!p) | |
516 | + return; | |
517 | + | |
518 | + pclassfw = (void *)simple_strtoul(p, NULL, 16); | |
519 | + if (!pclassfw) | |
520 | + return; | |
521 | + | |
522 | + p = env_get("class_elf_size"); | |
523 | + if (!p) | |
524 | + return; | |
525 | + len_class = simple_strtoul(p, NULL, 16); | |
526 | + | |
527 | + /* If the environment variable is not set, then exit silently */ | |
528 | + p = env_get("tmu_elf_firmware"); | |
529 | + if (!p) | |
530 | + return; | |
531 | + | |
532 | + ptmufw = (void *)simple_strtoul(p, NULL, 16); | |
533 | + if (!ptmufw) | |
534 | + return; | |
535 | + | |
536 | + p = env_get("tmu_elf_size"); | |
537 | + if (!p) | |
538 | + return; | |
539 | + len_tmu = simple_strtoul(p, NULL, 16); | |
540 | + | |
541 | + if (len_class == 0 || len_tmu == 0) { | |
542 | + printf("PFE FW corrupted. CLASS FW size %d, TMU FW size %d\n", | |
543 | + len_class, len_tmu); | |
544 | + return; | |
545 | + } | |
546 | + | |
547 | + /*Add CLASS FW to fdt.*/ | |
548 | + pfe_set_firmware_in_fdt(blob, pfenode, pclassfw, "class", len_class); | |
549 | + | |
550 | + /*Add TMU FW to fdt.*/ | |
551 | + pfe_set_firmware_in_fdt(blob, pfenode, ptmufw, "tmu", len_tmu); | |
552 | + | |
553 | + /* Util PE firmware is handled separately as it is not a usual case*/ | |
554 | + p = env_get("util_elf_firmware"); | |
555 | + if (!p) | |
556 | + return; | |
557 | + | |
558 | + putilfw = (void *)simple_strtoul(p, NULL, 16); | |
559 | + if (!putilfw) | |
560 | + return; | |
561 | + | |
562 | + p = env_get("util_elf_size"); | |
563 | + if (!p) | |
564 | + return; | |
565 | + len_util = simple_strtoul(p, NULL, 16); | |
566 | + | |
567 | + if (len_util) { | |
568 | + printf("PFE Util PE firmware is not added to FDT.\n"); | |
569 | + return; | |
570 | + } | |
571 | + | |
572 | + pfe_set_firmware_in_fdt(blob, pfenode, putilfw, "util", len_util); | |
573 | +} | |
574 | +#endif | |
575 | + | |
431 | 576 | void ft_cpu_setup(void *blob, bd_t *bd) |
432 | 577 | { |
433 | 578 | struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); |
... | ... | @@ -479,6 +624,9 @@ |
479 | 624 | |
480 | 625 | #ifdef CONFIG_SYS_DPAA_FMAN |
481 | 626 | fdt_fixup_fman_firmware(blob); |
627 | +#endif | |
628 | +#ifdef CONFIG_FSL_PFE | |
629 | + fdt_fixup_pfe_firmware(blob); | |
482 | 630 | #endif |
483 | 631 | #ifndef CONFIG_ARCH_LS1012A |
484 | 632 | fsl_fdt_disable_usb(blob); |
drivers/net/pfe_eth/pfe_firmware.c
... | ... | @@ -182,7 +182,8 @@ |
182 | 182 | uintptr_t pfe_img_addr = 0; |
183 | 183 | #endif |
184 | 184 | int ret = 0; |
185 | - int fw_count; | |
185 | + int fw_count, max_fw_count; | |
186 | + const char *p; | |
186 | 187 | |
187 | 188 | ret = pfe_fit_check(); |
188 | 189 | if (ret) |
... | ... | @@ -209,6 +210,61 @@ |
209 | 210 | } |
210 | 211 | #endif |
211 | 212 | |
213 | + p = env_get("load_util"); | |
214 | + if (!p) { | |
215 | + max_fw_count = 2; | |
216 | + } else { | |
217 | + max_fw_count = simple_strtoul(p, NULL, 10); | |
218 | + if (max_fw_count) | |
219 | + max_fw_count = 3; | |
220 | + else | |
221 | + max_fw_count = 2; | |
222 | + } | |
223 | + | |
224 | + for (fw_count = 0; fw_count < max_fw_count; fw_count++) { | |
225 | + switch (fw_count) { | |
226 | + case 0: | |
227 | + pfe_firmware_name = "class_slowpath"; | |
228 | + break; | |
229 | + case 1: | |
230 | + pfe_firmware_name = "tmu_slowpath"; | |
231 | + break; | |
232 | + case 2: | |
233 | + pfe_firmware_name = "util_slowpath"; | |
234 | + break; | |
235 | + } | |
236 | + | |
237 | + if (pfe_get_fw(&raw_image_addr, &raw_image_size, | |
238 | + pfe_firmware_name)) { | |
239 | + printf("%s firmware couldn't be found in FIT image\n", | |
240 | + pfe_firmware_name); | |
241 | + break; | |
242 | + } | |
243 | + pfe_firmware = malloc(raw_image_size); | |
244 | + if (!pfe_firmware) | |
245 | + return -ENOMEM; | |
246 | + memcpy((void *)pfe_firmware, (void *)raw_image_addr, | |
247 | + raw_image_size); | |
248 | + | |
249 | + switch (fw_count) { | |
250 | + case 0: | |
251 | + env_set_addr("class_elf_firmware", pfe_firmware); | |
252 | + env_set_addr("class_elf_size", (void *)raw_image_size); | |
253 | + break; | |
254 | + case 1: | |
255 | + env_set_addr("tmu_elf_firmware", pfe_firmware); | |
256 | + env_set_addr("tmu_elf_size", (void *)raw_image_size); | |
257 | + break; | |
258 | + case 2: | |
259 | + env_set_addr("util_elf_firmware", pfe_firmware); | |
260 | + env_set_addr("util_elf_size", (void *)raw_image_size); | |
261 | + break; | |
262 | + } | |
263 | + } | |
264 | + | |
265 | + raw_image_addr = NULL; | |
266 | + pfe_firmware = NULL; | |
267 | + raw_image_size = 0; | |
212 | 268 | for (fw_count = 0; fw_count < 2; fw_count++) { |
213 | 269 | if (fw_count == 0) |
214 | 270 | pfe_firmware_name = "class"; |