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