]> Git Repo - u-boot.git/blob - arch/arm/mach-imx/imx8/fdt.c
common: Drop asm/global_data.h from common header
[u-boot.git] / arch / arm / mach-imx / imx8 / fdt.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2019 NXP
4  */
5
6 #include <common.h>
7 #include <log.h>
8 #include <asm/arch/sci/sci.h>
9 #include <asm/arch/sys_proto.h>
10 #include <asm/global_data.h>
11 #include <dm/ofnode.h>
12 #include <fdt_support.h>
13 #include <linux/libfdt.h>
14
15 DECLARE_GLOBAL_DATA_PTR;
16
17 static bool check_owned_resource(sc_rsrc_t rsrc_id)
18 {
19         bool owned;
20
21         owned = sc_rm_is_resource_owned(-1, rsrc_id);
22
23         return owned;
24 }
25
26 static int disable_fdt_node(void *blob, int nodeoffset)
27 {
28         int rc, ret;
29         const char *status = "disabled";
30
31         do {
32                 rc = fdt_setprop(blob, nodeoffset, "status", status,
33                                  strlen(status) + 1);
34                 if (rc) {
35                         if (rc == -FDT_ERR_NOSPACE) {
36                                 ret = fdt_increase_size(blob, 512);
37                                 if (ret)
38                                         return ret;
39                         }
40                 }
41         } while (rc == -FDT_ERR_NOSPACE);
42
43         return rc;
44 }
45
46 static void update_fdt_with_owned_resources(void *blob)
47 {
48         /*
49          * Traverses the fdt nodes, check its power domain and use
50          * the resource id in the power domain for checking whether
51          * it is owned by current partition
52          */
53         struct fdtdec_phandle_args args;
54         int offset = 0, depth = 0;
55         u32 rsrc_id;
56         int rc, i;
57
58         for (offset = fdt_next_node(blob, offset, &depth); offset > 0;
59              offset = fdt_next_node(blob, offset, &depth)) {
60                 debug("Node name: %s, depth %d\n",
61                       fdt_get_name(blob, offset, NULL), depth);
62
63                 if (!fdt_get_property(blob, offset, "power-domains", NULL)) {
64                         debug("   - ignoring node %s\n",
65                               fdt_get_name(blob, offset, NULL));
66                         continue;
67                 }
68
69                 if (!fdtdec_get_is_enabled(blob, offset)) {
70                         debug("   - ignoring node %s\n",
71                               fdt_get_name(blob, offset, NULL));
72                         continue;
73                 }
74
75                 i = 0;
76                 while (true) {
77                         rc = fdtdec_parse_phandle_with_args(blob, offset,
78                                                             "power-domains",
79                                                             "#power-domain-cells",
80                                                             0, i++, &args);
81                         if (rc == -ENOENT) {
82                                 break;
83                         } else if (rc) {
84                                 printf("Parse power-domains of %s wrong: %d\n",
85                                        fdt_get_name(blob, offset, NULL), rc);
86                                 continue;
87                         }
88
89                         rsrc_id = args.args[0];
90
91                         if (!check_owned_resource(rsrc_id)) {
92                                 rc = disable_fdt_node(blob, offset);
93                                 if (!rc) {
94                                         printf("Disable %s rsrc %u not owned\n",
95                                                fdt_get_name(blob, offset, NULL),
96                                                rsrc_id);
97                                 } else {
98                                         printf("Unable to disable %s, err=%s\n",
99                                                fdt_get_name(blob, offset, NULL),
100                                                fdt_strerror(rc));
101                                 }
102                         }
103                 }
104         }
105 }
106
107 static int config_smmu_resource_sid(int rsrc, int sid)
108 {
109         int err;
110
111         err = sc_rm_set_master_sid(-1, rsrc, sid);
112         debug("set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err);
113         if (err != SC_ERR_NONE) {
114                 if (!check_owned_resource(rsrc)) {
115                         printf("%s rsrc[%d] not owned\n", __func__, rsrc);
116                         return -1;
117                 }
118                 pr_err("fail set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err);
119                 return -EINVAL;
120         }
121
122         return 0;
123 }
124
125 static int config_smmu_fdt_device_sid(void *blob, int device_offset, int sid)
126 {
127         const char *name = fdt_get_name(blob, device_offset, NULL);
128         struct fdtdec_phandle_args args;
129         int rsrc, ret;
130         int proplen;
131         const fdt32_t *prop;
132         int i;
133
134         prop = fdt_getprop(blob, device_offset, "fsl,sc_rsrc_id", &proplen);
135         if (prop) {
136                 int i;
137
138                 debug("configure node %s sid 0x%x for %d resources\n",
139                       name, sid, (int)(proplen / sizeof(fdt32_t)));
140                 for (i = 0; i < proplen / sizeof(fdt32_t); ++i) {
141                         ret = config_smmu_resource_sid(fdt32_to_cpu(prop[i]),
142                                                        sid);
143                         if (ret)
144                                 return ret;
145                 }
146
147                 return 0;
148         }
149
150         i = 0;
151         while (true) {
152                 ret = fdtdec_parse_phandle_with_args(blob, device_offset,
153                                                      "power-domains",
154                                                      "#power-domain-cells",
155                                                      0, i++, &args);
156                 if (ret == -ENOENT) {
157                         break;
158                 } else if (ret) {
159                         printf("Parse power-domains of node %s wrong: %d\n",
160                                fdt_get_name(blob, device_offset, NULL), ret);
161                         continue;
162                 }
163
164                 debug("configure node %s sid 0x%x rsrc=%d\n",
165                       name, sid, rsrc);
166                 rsrc = args.args[0];
167
168                 ret = config_smmu_resource_sid(rsrc, sid);
169                 if (ret)
170                         break;
171         }
172
173         return ret;
174 }
175
176 static int config_smmu_fdt(void *blob)
177 {
178         int offset, proplen, i, ret;
179         const fdt32_t *prop;
180         const char *name;
181
182         /* Legacy smmu bindings, still used by xen. */
183         offset = fdt_node_offset_by_compatible(blob, 0, "arm,mmu-500");
184         prop = fdt_getprop(blob, offset, "mmu-masters", &proplen);
185         if (offset > 0 && prop) {
186                 debug("found legacy mmu-masters property\n");
187
188                 for (i = 0; i < proplen / 8; ++i) {
189                         u32 phandle = fdt32_to_cpu(prop[2 * i]);
190                         int sid = fdt32_to_cpu(prop[2 * i + 1]);
191                         int device_offset;
192
193                         device_offset = fdt_node_offset_by_phandle(blob,
194                                                                    phandle);
195                         if (device_offset < 0) {
196                                 pr_err("Not find device from mmu_masters: %d",
197                                        device_offset);
198                                 continue;
199                         }
200                         ret = config_smmu_fdt_device_sid(blob, device_offset,
201                                                          sid);
202                         if (ret)
203                                 return ret;
204                 }
205
206                 /* Ignore new bindings if old bindings found, just like linux. */
207                 return 0;
208         }
209
210         /* Generic smmu bindings */
211         offset = 0;
212         while ((offset = fdt_next_node(blob, offset, NULL)) > 0) {
213                 name = fdt_get_name(blob, offset, NULL);
214                 prop = fdt_getprop(blob, offset, "iommus", &proplen);
215                 if (!prop)
216                         continue;
217                 debug("node %s iommus proplen %d\n", name, proplen);
218
219                 if (proplen == 12) {
220                         int sid = fdt32_to_cpu(prop[1]);
221
222                         config_smmu_fdt_device_sid(blob, offset, sid);
223                 } else if (proplen != 4) {
224                         debug("node %s ignore unexpected iommus proplen=%d\n",
225                               name, proplen);
226                 }
227         }
228
229         return 0;
230 }
231
232 static int ft_add_optee_node(void *fdt, struct bd_info *bd)
233 {
234         const char *path, *subpath;
235         int offs;
236
237         /*
238          * No TEE space allocated indicating no TEE running, so no
239          * need to add optee node in dts
240          */
241         if (!boot_pointer[1])
242                 return 0;
243
244         offs = fdt_increase_size(fdt, 512);
245         if (offs) {
246                 printf("No Space for dtb\n");
247                 return 1;
248         }
249
250         path = "/firmware";
251         offs = fdt_path_offset(fdt, path);
252         if (offs < 0) {
253                 path = "/";
254                 offs = fdt_path_offset(fdt, path);
255
256                 if (offs < 0) {
257                         printf("Could not find root node.\n");
258                         return offs;
259                 }
260
261                 subpath = "firmware";
262                 offs = fdt_add_subnode(fdt, offs, subpath);
263                 if (offs < 0) {
264                         printf("Could not create %s node.\n", subpath);
265                         return offs;
266                 }
267         }
268
269         subpath = "optee";
270         offs = fdt_add_subnode(fdt, offs, subpath);
271         if (offs < 0) {
272                 printf("Could not create %s node.\n", subpath);
273                 return offs;
274         }
275
276         fdt_setprop_string(fdt, offs, "compatible", "linaro,optee-tz");
277         fdt_setprop_string(fdt, offs, "method", "smc");
278
279         return 0;
280 }
281
282 int ft_system_setup(void *blob, struct bd_info *bd)
283 {
284         int ret;
285         int off;
286
287         if (CONFIG_BOOTAUX_RESERVED_MEM_BASE) {
288                 off = fdt_add_mem_rsv(blob, CONFIG_BOOTAUX_RESERVED_MEM_BASE,
289                                       CONFIG_BOOTAUX_RESERVED_MEM_SIZE);
290                 if (off < 0)
291                         printf("Failed  to reserve memory for bootaux: %s\n",
292                                fdt_strerror(off));
293         }
294
295         update_fdt_with_owned_resources(blob);
296
297         if (is_imx8qm()) {
298                 ret = config_smmu_fdt(blob);
299                 if (ret)
300                         return ret;
301         }
302
303         return ft_add_optee_node(blob, bd);
304 }
This page took 0.045763 seconds and 4 git commands to generate.