fdt.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2016 Freescale Semiconductor, Inc.
  4. */
  5. #include <asm/io.h>
  6. #include <env.h>
  7. #include <fdt_support.h>
  8. #include <fsl_qe.h> /* For struct qe_firmware */
  9. #include <u-boot/crc.h>
  10. #ifdef CONFIG_SYS_DPAA_FMAN
  11. /**
  12. * fdt_fixup_fman_firmware -- insert the Fman firmware into the device tree
  13. *
  14. * The binding for an Fman firmware node is documented in
  15. * Documentation/powerpc/dts-bindings/fsl/dpaa/fman.txt. This node contains
  16. * the actual Fman firmware binary data. The operating system is expected to
  17. * be able to parse the binary data to determine any attributes it needs.
  18. */
  19. void fdt_fixup_fman_firmware(void *blob)
  20. {
  21. int rc, fmnode, fwnode = -1;
  22. uint32_t phandle;
  23. struct qe_firmware *fmanfw;
  24. const struct qe_header *hdr;
  25. unsigned int length;
  26. uint32_t crc;
  27. const char *p;
  28. /* The first Fman we find will contain the actual firmware. */
  29. fmnode = fdt_node_offset_by_compatible(blob, -1, "fsl,fman");
  30. if (fmnode < 0)
  31. /* Exit silently if there are no Fman devices */
  32. return;
  33. /* If we already have a firmware node, then also exit silently. */
  34. if (fdt_node_offset_by_compatible(blob, -1, "fsl,fman-firmware") > 0)
  35. return;
  36. /* If the environment variable is not set, then exit silently */
  37. p = env_get("fman_ucode");
  38. if (!p)
  39. return;
  40. fmanfw = (struct qe_firmware *)simple_strtoul(p, NULL, 16);
  41. if (!fmanfw)
  42. return;
  43. hdr = &fmanfw->header;
  44. length = fdt32_to_cpu(hdr->length);
  45. /* Verify the firmware. */
  46. if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
  47. (hdr->magic[2] != 'F')) {
  48. printf("Data at %p is not an Fman firmware\n", fmanfw);
  49. return;
  50. }
  51. if (length > CONFIG_SYS_QE_FMAN_FW_LENGTH) {
  52. printf("Fman firmware at %p is too large (size=%u)\n",
  53. fmanfw, length);
  54. return;
  55. }
  56. length -= sizeof(u32); /* Subtract the size of the CRC */
  57. crc = fdt32_to_cpu(*(u32 *)((void *)fmanfw + length));
  58. if (crc != crc32_no_comp(0, (void *)fmanfw, length)) {
  59. printf("Fman firmware at %p has invalid CRC\n", fmanfw);
  60. return;
  61. }
  62. length += sizeof(u32);
  63. /* Increase the size of the fdt to make room for the node. */
  64. rc = fdt_increase_size(blob, length);
  65. if (rc < 0) {
  66. printf("Unable to make room for Fman firmware: %s\n",
  67. fdt_strerror(rc));
  68. return;
  69. }
  70. /* Create the firmware node. */
  71. fwnode = fdt_add_subnode(blob, fmnode, "fman-firmware");
  72. if (fwnode < 0) {
  73. char s[64];
  74. fdt_get_path(blob, fmnode, s, sizeof(s));
  75. printf("Could not add firmware node to %s: %s\n", s,
  76. fdt_strerror(fwnode));
  77. return;
  78. }
  79. rc = fdt_setprop_string(blob, fwnode, "compatible",
  80. "fsl,fman-firmware");
  81. if (rc < 0) {
  82. char s[64];
  83. fdt_get_path(blob, fwnode, s, sizeof(s));
  84. printf("Could not add compatible property to node %s: %s\n", s,
  85. fdt_strerror(rc));
  86. return;
  87. }
  88. phandle = fdt_create_phandle(blob, fwnode);
  89. if (!phandle) {
  90. char s[64];
  91. fdt_get_path(blob, fwnode, s, sizeof(s));
  92. printf("Could not add phandle property to node %s: %s\n", s,
  93. fdt_strerror(rc));
  94. return;
  95. }
  96. rc = fdt_setprop(blob, fwnode, "fsl,firmware", fmanfw, length);
  97. if (rc < 0) {
  98. char s[64];
  99. fdt_get_path(blob, fwnode, s, sizeof(s));
  100. printf("Could not add firmware property to node %s: %s\n", s,
  101. fdt_strerror(rc));
  102. return;
  103. }
  104. /* Find all other Fman nodes and point them to the firmware node. */
  105. while ((fmnode = fdt_node_offset_by_compatible(blob, fmnode,
  106. "fsl,fman")) > 0) {
  107. rc = fdt_setprop_cell(blob, fmnode, "fsl,firmware-phandle",
  108. phandle);
  109. if (rc < 0) {
  110. char s[64];
  111. fdt_get_path(blob, fmnode, s, sizeof(s));
  112. printf("Could not add pointer property to node %s: %s\n",
  113. s, fdt_strerror(rc));
  114. return;
  115. }
  116. }
  117. }
  118. #endif