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