command: Remove the cmd_tbl_t typedef
[oweals/u-boot.git] / drivers / net / fsl-mc / mc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2014 Freescale Semiconductor, Inc.
4  * Copyright 2017-2018 NXP
5  */
6 #include <common.h>
7 #include <command.h>
8 #include <cpu_func.h>
9 #include <env.h>
10 #include <errno.h>
11 #include <image.h>
12 #include <malloc.h>
13 #include <linux/bug.h>
14 #include <asm/io.h>
15 #include <linux/libfdt.h>
16 #include <net.h>
17 #include <fdt_support.h>
18 #include <fsl-mc/fsl_mc.h>
19 #include <fsl-mc/fsl_mc_sys.h>
20 #include <fsl-mc/fsl_mc_private.h>
21 #include <fsl-mc/fsl_dpmng.h>
22 #include <fsl-mc/fsl_dprc.h>
23 #include <fsl-mc/fsl_dpio.h>
24 #include <fsl-mc/fsl_dpni.h>
25 #include <fsl-mc/fsl_dpsparser.h>
26 #include <fsl-mc/fsl_qbman_portal.h>
27 #include <fsl-mc/ldpaa_wriop.h>
28
29 #define MC_RAM_BASE_ADDR_ALIGNMENT  (512UL * 1024 * 1024)
30 #define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1))
31 #define MC_RAM_SIZE_ALIGNMENT       (256UL * 1024 * 1024)
32
33 #define MC_MEM_SIZE_ENV_VAR     "mcmemsize"
34 #define MC_BOOT_TIMEOUT_ENV_VAR "mcboottimeout"
35 #define MC_BOOT_ENV_VAR         "mcinitcmd"
36 #define MC_DRAM_BLOCK_DEFAULT_SIZE (512UL * 1024 * 1024)
37
38 DECLARE_GLOBAL_DATA_PTR;
39 static int mc_memset_resv_ram;
40 static struct mc_version mc_ver_info;
41 static int mc_boot_status = -1;
42 static int mc_dpl_applied = -1;
43 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
44 static int mc_aiop_applied = -1;
45 #endif
46 struct fsl_mc_io *root_mc_io = NULL;
47 struct fsl_mc_io *dflt_mc_io = NULL; /* child container */
48 uint16_t root_dprc_handle = 0;
49 uint16_t dflt_dprc_handle = 0;
50 int child_dprc_id;
51 struct fsl_dpbp_obj *dflt_dpbp = NULL;
52 struct fsl_dpio_obj *dflt_dpio = NULL;
53 struct fsl_dpni_obj *dflt_dpni = NULL;
54 static u64 mc_lazy_dpl_addr;
55 static u32 dpsparser_obj_id;
56 static u16 dpsparser_handle;
57 static char *mc_err_msg_apply_spb[] = MC_ERROR_MSG_APPLY_SPB;
58
59 #ifdef DEBUG
60 void dump_ram_words(const char *title, void *addr)
61 {
62         int i;
63         uint32_t *words = addr;
64
65         printf("Dumping beginning of %s (%p):\n", title, addr);
66         for (i = 0; i < 16; i++)
67                 printf("%#x ", words[i]);
68
69         printf("\n");
70 }
71
72 void dump_mc_ccsr_regs(struct mc_ccsr_registers __iomem *mc_ccsr_regs)
73 {
74         printf("MC CCSR registers:\n"
75                 "reg_gcr1 %#x\n"
76                 "reg_gsr %#x\n"
77                 "reg_sicbalr %#x\n"
78                 "reg_sicbahr %#x\n"
79                 "reg_sicapr %#x\n"
80                 "reg_mcfbalr %#x\n"
81                 "reg_mcfbahr %#x\n"
82                 "reg_mcfapr %#x\n"
83                 "reg_psr %#x\n",
84                 mc_ccsr_regs->reg_gcr1,
85                 mc_ccsr_regs->reg_gsr,
86                 mc_ccsr_regs->reg_sicbalr,
87                 mc_ccsr_regs->reg_sicbahr,
88                 mc_ccsr_regs->reg_sicapr,
89                 mc_ccsr_regs->reg_mcfbalr,
90                 mc_ccsr_regs->reg_mcfbahr,
91                 mc_ccsr_regs->reg_mcfapr,
92                 mc_ccsr_regs->reg_psr);
93 }
94 #else
95
96 #define dump_ram_words(title, addr)
97 #define dump_mc_ccsr_regs(mc_ccsr_regs)
98
99 #endif /* DEBUG */
100
101 /**
102  * Copying MC firmware or DPL image to DDR
103  */
104 static int mc_copy_image(const char *title,
105                          u64 image_addr, u32 image_size, u64 mc_ram_addr)
106 {
107         debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
108         memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
109         flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size);
110         return 0;
111 }
112
113 #ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
114 /**
115  * MC firmware FIT image parser checks if the image is in FIT
116  * format, verifies integrity of the image and calculates
117  * raw image address and size values.
118  * Returns 0 on success and a negative errno on error.
119  * task fail.
120  **/
121 int parse_mc_firmware_fit_image(u64 mc_fw_addr,
122                                 const void **raw_image_addr,
123                                 size_t *raw_image_size)
124 {
125         int format;
126         void *fit_hdr;
127         int node_offset;
128         const void *data;
129         size_t size;
130         const char *uname = "firmware";
131
132         fit_hdr = (void *)mc_fw_addr;
133
134         /* Check if Image is in FIT format */
135         format = genimg_get_format(fit_hdr);
136
137         if (format != IMAGE_FORMAT_FIT) {
138                 printf("fsl-mc: ERR: Bad firmware image (not a FIT image)\n");
139                 return -EINVAL;
140         }
141
142         if (!fit_check_format(fit_hdr)) {
143                 printf("fsl-mc: ERR: Bad firmware image (bad FIT header)\n");
144                 return -EINVAL;
145         }
146
147         node_offset = fit_image_get_node(fit_hdr, uname);
148
149         if (node_offset < 0) {
150                 printf("fsl-mc: ERR: Bad firmware image (missing subimage)\n");
151                 return -ENOENT;
152         }
153
154         /* Verify MC firmware image */
155         if (!(fit_image_verify(fit_hdr, node_offset))) {
156                 printf("fsl-mc: ERR: Bad firmware image (bad CRC)\n");
157                 return -EINVAL;
158         }
159
160         /* Get address and size of raw image */
161         fit_image_get_data(fit_hdr, node_offset, &data, &size);
162
163         *raw_image_addr = data;
164         *raw_image_size = size;
165
166         return 0;
167 }
168 #endif
169
170 #define MC_DT_INCREASE_SIZE     64
171
172 enum mc_fixup_type {
173         MC_FIXUP_DPL,
174         MC_FIXUP_DPC
175 };
176
177 static int mc_fixup_mac_addr(void *blob, int nodeoffset,
178 #ifdef CONFIG_DM_ETH
179                              const char *propname, struct udevice *eth_dev,
180 #else
181                              const char *propname, struct eth_device *eth_dev,
182 #endif
183                              enum mc_fixup_type type)
184 {
185 #ifdef CONFIG_DM_ETH
186         struct eth_pdata *plat = dev_get_platdata(eth_dev);
187         unsigned char *enetaddr = plat->enetaddr;
188         int eth_index = eth_dev->seq;
189 #else
190         unsigned char *enetaddr = eth_dev->enetaddr;
191         int eth_index = eth_dev->index;
192 #endif
193         int err = 0, len = 0, size, i;
194         unsigned char env_enetaddr[ARP_HLEN];
195         unsigned int enetaddr_32[ARP_HLEN];
196         void *val = NULL;
197
198         switch (type) {
199         case MC_FIXUP_DPL:
200                 /* DPL likes its addresses on 32 * ARP_HLEN bits */
201                 for (i = 0; i < ARP_HLEN; i++)
202                         enetaddr_32[i] = cpu_to_fdt32(enetaddr[i]);
203                 val = enetaddr_32;
204                 len = sizeof(enetaddr_32);
205                 break;
206         case MC_FIXUP_DPC:
207                 val = enetaddr;
208                 len = ARP_HLEN;
209                 break;
210         }
211
212         /* MAC address property present */
213         if (fdt_get_property(blob, nodeoffset, propname, NULL)) {
214                 /* u-boot MAC addr randomly assigned - leave the present one */
215                 if (!eth_env_get_enetaddr_by_index("eth", eth_index,
216                                                    env_enetaddr))
217                         return err;
218         } else {
219                 size = MC_DT_INCREASE_SIZE + strlen(propname) + len;
220                 /* make room for mac address property */
221                 err = fdt_increase_size(blob, size);
222                 if (err) {
223                         printf("fdt_increase_size: err=%s\n",
224                                fdt_strerror(err));
225                         return err;
226                 }
227         }
228
229         err = fdt_setprop(blob, nodeoffset, propname, val, len);
230         if (err) {
231                 printf("fdt_setprop: err=%s\n", fdt_strerror(err));
232                 return err;
233         }
234
235         return err;
236 }
237
238 #define is_dpni(s) (s != NULL ? !strncmp(s, "dpni@", 5) : 0)
239
240 const char *dpl_get_connection_endpoint(void *blob, char *endpoint)
241 {
242         int connoffset = fdt_path_offset(blob, "/connections"), off;
243         const char *s1, *s2;
244
245         for (off = fdt_first_subnode(blob, connoffset);
246              off >= 0;
247              off = fdt_next_subnode(blob, off)) {
248                 s1 = fdt_stringlist_get(blob, off, "endpoint1", 0, NULL);
249                 s2 = fdt_stringlist_get(blob, off, "endpoint2", 0, NULL);
250
251                 if (!s1 || !s2)
252                         continue;
253
254                 if (strcmp(endpoint, s1) == 0)
255                         return s2;
256
257                 if (strcmp(endpoint, s2) == 0)
258                         return s1;
259         }
260
261         return NULL;
262 }
263
264 static int mc_fixup_dpl_mac_addr(void *blob, int dpmac_id,
265 #ifdef CONFIG_DM_ETH
266                                  struct udevice *eth_dev)
267 #else
268                                  struct eth_device *eth_dev)
269 #endif
270 {
271         int objoff = fdt_path_offset(blob, "/objects");
272         int dpmacoff = -1, dpnioff = -1;
273         const char *endpoint;
274         char mac_name[10];
275         int err;
276
277         sprintf(mac_name, "dpmac@%d", dpmac_id);
278         dpmacoff = fdt_subnode_offset(blob, objoff, mac_name);
279         if (dpmacoff < 0)
280                 /* dpmac not defined in DPL, so skip it. */
281                 return 0;
282
283         err = mc_fixup_mac_addr(blob, dpmacoff, "mac_addr", eth_dev,
284                                 MC_FIXUP_DPL);
285         if (err) {
286                 printf("Error fixing up dpmac mac_addr in DPL\n");
287                 return err;
288         }
289
290         /* now we need to figure out if there is any
291          * DPNI connected to this MAC, so we walk the
292          * connection list
293          */
294         endpoint = dpl_get_connection_endpoint(blob, mac_name);
295         if (!is_dpni(endpoint))
296                 return 0;
297
298         /* let's see if we can fixup the DPNI as well */
299         dpnioff = fdt_subnode_offset(blob, objoff, endpoint);
300         if (dpnioff < 0)
301                 /* DPNI not defined in DPL in the objects area */
302                 return 0;
303
304         return mc_fixup_mac_addr(blob, dpnioff, "mac_addr", eth_dev,
305                                  MC_FIXUP_DPL);
306 }
307
308 void fdt_fixup_mc_ddr(u64 *base, u64 *size)
309 {
310         u64 mc_size = mc_get_dram_block_size();
311
312         if (mc_size < MC_DRAM_BLOCK_DEFAULT_SIZE) {
313                 *base = mc_get_dram_addr() + mc_size;
314                 *size = MC_DRAM_BLOCK_DEFAULT_SIZE - mc_size;
315         }
316 }
317
318 void fdt_fsl_mc_fixup_iommu_map_entry(void *blob)
319 {
320         u32 *prop;
321         u32 iommu_map[4];
322         int offset;
323         int lenp;
324
325         /* find fsl-mc node */
326         offset = fdt_path_offset(blob, "/soc/fsl-mc");
327         if (offset < 0)
328                 offset = fdt_path_offset(blob, "/fsl-mc");
329         if (offset < 0) {
330                 printf("%s: fsl-mc: ERR: fsl-mc node not found in DT, err %d\n",
331                        __func__, offset);
332                 return;
333         }
334
335         prop = fdt_getprop_w(blob, offset, "iommu-map", &lenp);
336         if (!prop) {
337                 debug("%s: fsl-mc: ERR: missing iommu-map in fsl-mc bus node\n",
338                       __func__);
339                 return;
340         }
341
342         iommu_map[0] = cpu_to_fdt32(FSL_DPAA2_STREAM_ID_START);
343         iommu_map[1] = *++prop;
344         iommu_map[2] = cpu_to_fdt32(FSL_DPAA2_STREAM_ID_START);
345         iommu_map[3] = cpu_to_fdt32(FSL_DPAA2_STREAM_ID_END -
346                 FSL_DPAA2_STREAM_ID_START + 1);
347
348         fdt_setprop_inplace(blob, offset, "iommu-map",
349                             iommu_map, sizeof(iommu_map));
350 }
351
352 static int mc_fixup_dpc_mac_addr(void *blob, int dpmac_id,
353 #ifdef CONFIG_DM_ETH
354                                  struct udevice *eth_dev)
355 #else
356                                  struct eth_device *eth_dev)
357 #endif
358 {
359         int nodeoffset = fdt_path_offset(blob, "/board_info/ports"), noff;
360         int err = 0;
361         char mac_name[10];
362         const char link_type_mode[] = "MAC_LINK_TYPE_FIXED";
363
364         sprintf(mac_name, "mac@%d", dpmac_id);
365
366         /* node not found - create it */
367         noff = fdt_subnode_offset(blob, nodeoffset, (const char *)mac_name);
368         if (noff < 0) {
369                 err = fdt_increase_size(blob, 200);
370                 if (err) {
371                         printf("fdt_increase_size: err=%s\n",
372                                 fdt_strerror(err));
373                         return err;
374                 }
375
376                 noff = fdt_add_subnode(blob, nodeoffset, mac_name);
377                 if (noff < 0) {
378                         printf("fdt_add_subnode: err=%s\n",
379                                fdt_strerror(err));
380                         return err;
381                 }
382
383                 /* add default property of fixed link */
384                 err = fdt_appendprop_string(blob, noff,
385                                             "link_type", link_type_mode);
386                 if (err) {
387                         printf("fdt_appendprop_string: err=%s\n",
388                                 fdt_strerror(err));
389                         return err;
390                 }
391         }
392
393         return mc_fixup_mac_addr(blob, noff, "port_mac_address", eth_dev,
394                                  MC_FIXUP_DPC);
395 }
396
397 static int mc_fixup_mac_addrs(void *blob, enum mc_fixup_type type)
398 {
399         int i, err = 0, ret = 0;
400 #ifdef CONFIG_DM_ETH
401 #define ETH_NAME_LEN 20
402         struct udevice *eth_dev;
403 #else
404         struct eth_device *eth_dev;
405 #endif
406         char ethname[ETH_NAME_LEN];
407
408         for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
409                 /* port not enabled */
410                 if (wriop_is_enabled_dpmac(i) != 1)
411                         continue;
412
413                 snprintf(ethname, ETH_NAME_LEN, "DPMAC%d@%s", i,
414                          phy_interface_strings[wriop_get_enet_if(i)]);
415
416                 eth_dev = eth_get_dev_by_name(ethname);
417                 if (eth_dev == NULL)
418                         continue;
419
420                 switch (type) {
421                 case MC_FIXUP_DPL:
422                         err = mc_fixup_dpl_mac_addr(blob, i, eth_dev);
423                         break;
424                 case MC_FIXUP_DPC:
425                         err = mc_fixup_dpc_mac_addr(blob, i, eth_dev);
426                         break;
427                 default:
428                         break;
429                 }
430
431                 if (err)
432                         printf("fsl-mc: ERROR fixing mac address for %s\n",
433                                ethname);
434                 ret |= err;
435         }
436
437         return ret;
438 }
439
440 static int mc_fixup_dpc(u64 dpc_addr)
441 {
442         void *blob = (void *)dpc_addr;
443         int nodeoffset, err = 0;
444
445         /* delete any existing ICID pools */
446         nodeoffset = fdt_path_offset(blob, "/resources/icid_pools");
447         if (fdt_del_node(blob, nodeoffset) < 0)
448                 printf("\nfsl-mc: WARNING: could not delete ICID pool\n");
449
450         /* add a new pool */
451         nodeoffset = fdt_path_offset(blob, "/resources");
452         if (nodeoffset < 0) {
453                 printf("\nfsl-mc: ERROR: DPC is missing /resources\n");
454                 return -EINVAL;
455         }
456         nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pools");
457         nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pool@0");
458         do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
459                              "base_icid", FSL_DPAA2_STREAM_ID_START, 1);
460         do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
461                              "num",
462                              FSL_DPAA2_STREAM_ID_END -
463                              FSL_DPAA2_STREAM_ID_START + 1, 1);
464
465         /* fixup MAC addresses for dpmac ports */
466         nodeoffset = fdt_path_offset(blob, "/board_info/ports");
467         if (nodeoffset < 0)
468                 goto out;
469
470         err = mc_fixup_mac_addrs(blob, MC_FIXUP_DPC);
471
472 out:
473         flush_dcache_range(dpc_addr, dpc_addr + fdt_totalsize(blob));
474
475         return err;
476 }
477
478 static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpc_addr)
479 {
480         u64 mc_dpc_offset;
481 #ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
482         int error;
483         void *dpc_fdt_hdr;
484         int dpc_size;
485 #endif
486
487 #ifdef CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET
488         BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET & 0x3) != 0 ||
489                      CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET > 0xffffffff);
490
491         mc_dpc_offset = CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET;
492 #else
493 #error "CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET not defined"
494 #endif
495
496         /*
497          * Load the MC DPC blob in the MC private DRAM block:
498          */
499 #ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
500         printf("MC DPC is preloaded to %#llx\n", mc_ram_addr + mc_dpc_offset);
501 #else
502         /*
503          * Get address and size of the DPC blob stored in flash:
504          */
505         dpc_fdt_hdr = (void *)mc_dpc_addr;
506
507         error = fdt_check_header(dpc_fdt_hdr);
508         if (error != 0) {
509                 /*
510                  * Don't return with error here, since the MC firmware can
511                  * still boot without a DPC
512                  */
513                 printf("\nfsl-mc: WARNING: No DPC image found");
514                 return 0;
515         }
516
517         dpc_size = fdt_totalsize(dpc_fdt_hdr);
518         if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) {
519                 printf("\nfsl-mc: ERROR: Bad DPC image (too large: %d)\n",
520                        dpc_size);
521                 return -EINVAL;
522         }
523
524         mc_copy_image("MC DPC blob",
525                       (u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset);
526 #endif /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */
527
528         if (mc_fixup_dpc(mc_ram_addr + mc_dpc_offset))
529                 return -EINVAL;
530
531         dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset));
532         return 0;
533 }
534
535
536 static int mc_fixup_dpl(u64 dpl_addr)
537 {
538         void *blob = (void *)dpl_addr;
539         u32 ver = fdt_getprop_u32_default(blob, "/", "dpl-version", 0);
540         int err = 0;
541
542         /* The DPL fixup for mac addresses is only relevant
543          * for old-style DPLs
544          */
545         if (ver >= 10)
546                 return 0;
547
548         err = mc_fixup_mac_addrs(blob, MC_FIXUP_DPL);
549         flush_dcache_range(dpl_addr, dpl_addr + fdt_totalsize(blob));
550
551         return err;
552 }
553
554 static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpl_addr)
555 {
556         u64 mc_dpl_offset;
557 #ifndef CONFIG_SYS_LS_MC_DPL_IN_DDR
558         int error;
559         void *dpl_fdt_hdr;
560         int dpl_size;
561 #endif
562
563 #ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
564         BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
565                      CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
566
567         mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
568 #else
569 #error "CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET not defined"
570 #endif
571
572         /*
573          * Load the MC DPL blob in the MC private DRAM block:
574          */
575 #ifdef CONFIG_SYS_LS_MC_DPL_IN_DDR
576         printf("MC DPL is preloaded to %#llx\n", mc_ram_addr + mc_dpl_offset);
577 #else
578         /*
579          * Get address and size of the DPL blob stored in flash:
580          */
581         dpl_fdt_hdr = (void *)mc_dpl_addr;
582
583         error = fdt_check_header(dpl_fdt_hdr);
584         if (error != 0) {
585                 printf("\nfsl-mc: ERROR: Bad DPL image (bad header)\n");
586                 return error;
587         }
588
589         dpl_size = fdt_totalsize(dpl_fdt_hdr);
590         if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
591                 printf("\nfsl-mc: ERROR: Bad DPL image (too large: %d)\n",
592                        dpl_size);
593                 return -EINVAL;
594         }
595
596         mc_copy_image("MC DPL blob",
597                       (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
598 #endif /* not defined CONFIG_SYS_LS_MC_DPL_IN_DDR */
599
600         if (mc_fixup_dpl(mc_ram_addr + mc_dpl_offset))
601                 return -EINVAL;
602         dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset));
603         return 0;
604 }
605
606 /**
607  * Return the MC boot timeout value in milliseconds
608  */
609 static unsigned long get_mc_boot_timeout_ms(void)
610 {
611         unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
612
613         char *timeout_ms_env_var = env_get(MC_BOOT_TIMEOUT_ENV_VAR);
614
615         if (timeout_ms_env_var) {
616                 timeout_ms = simple_strtoul(timeout_ms_env_var, NULL, 10);
617                 if (timeout_ms == 0) {
618                         printf("fsl-mc: WARNING: Invalid value for \'"
619                                MC_BOOT_TIMEOUT_ENV_VAR
620                                "\' environment variable: %lu\n",
621                                timeout_ms);
622
623                         timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
624                 }
625         }
626
627         return timeout_ms;
628 }
629
630 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
631
632 __weak bool soc_has_aiop(void)
633 {
634         return false;
635 }
636
637 static int load_mc_aiop_img(u64 aiop_fw_addr)
638 {
639         u64 mc_ram_addr = mc_get_dram_addr();
640 #ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
641         void *aiop_img;
642 #endif
643
644         /* Check if AIOP is available */
645         if (!soc_has_aiop())
646                 return -ENODEV;
647         /*
648          * Load the MC AIOP image in the MC private DRAM block:
649          */
650
651 #ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
652         printf("MC AIOP is preloaded to %#llx\n", mc_ram_addr +
653                CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
654 #else
655         aiop_img = (void *)aiop_fw_addr;
656         mc_copy_image("MC AIOP image",
657                       (u64)aiop_img, CONFIG_SYS_LS_MC_AIOP_IMG_MAX_LENGTH,
658                       mc_ram_addr + CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
659 #endif
660         mc_aiop_applied = 0;
661
662         return 0;
663 }
664 #endif
665
666 static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr)
667 {
668         u32 reg_gsr;
669         u32 mc_fw_boot_status;
670         unsigned long timeout_ms = get_mc_boot_timeout_ms();
671         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
672
673         dmb();
674         assert(timeout_ms > 0);
675         for (;;) {
676                 udelay(1000);   /* throttle polling */
677                 reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
678                 mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
679                 if (mc_fw_boot_status & 0x1)
680                         break;
681
682                 timeout_ms--;
683                 if (timeout_ms == 0)
684                         break;
685         }
686
687         if (timeout_ms == 0) {
688                 printf("ERROR: timeout\n");
689
690                 /* TODO: Get an error status from an MC CCSR register */
691                 return -ETIMEDOUT;
692         }
693
694         if (mc_fw_boot_status != 0x1) {
695                 /*
696                  * TODO: Identify critical errors from the GSR register's FS
697                  * field and for those errors, set error to -ENODEV or other
698                  * appropriate errno, so that the status property is set to
699                  * failure in the fsl,dprc device tree node.
700                  */
701                 printf("WARNING: Firmware returned an error (GSR: %#x)\n",
702                        reg_gsr);
703         } else {
704                 printf("SUCCESS\n");
705         }
706
707
708         *final_reg_gsr = reg_gsr;
709         return 0;
710 }
711
712 int mc_init(u64 mc_fw_addr, u64 mc_dpc_addr)
713 {
714         int error = 0;
715         int portal_id = 0;
716         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
717         u64 mc_ram_addr = mc_get_dram_addr();
718         u32 reg_gsr;
719         u32 reg_mcfbalr;
720 #ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
721         const void *raw_image_addr;
722         size_t raw_image_size = 0;
723 #endif
724         u8 mc_ram_num_256mb_blocks;
725         size_t mc_ram_size = mc_get_dram_block_size();
726
727         mc_ram_num_256mb_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT;
728
729         if (mc_ram_num_256mb_blocks >= 0xff) {
730                 error = -EINVAL;
731                 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
732                        mc_ram_size);
733                 goto out;
734         }
735
736         /*
737          * To support 128 MB DDR Size for MC
738          */
739         if (mc_ram_num_256mb_blocks == 0)
740                 mc_ram_num_256mb_blocks = 0xFF;
741
742         /*
743          * Management Complex cores should be held at reset out of POR.
744          * U-Boot should be the first software to touch MC. To be safe,
745          * we reset all cores again by setting GCR1 to 0. It doesn't do
746          * anything if they are held at reset. After we setup the firmware
747          * we kick off MC by deasserting the reset bit for core 0, and
748          * deasserting the reset bits for Command Portal Managers.
749          * The stop bits are not touched here. They are used to stop the
750          * cores when they are active. Setting stop bits doesn't stop the
751          * cores from fetching instructions when they are released from
752          * reset.
753          */
754         out_le32(&mc_ccsr_regs->reg_gcr1, 0);
755         dmb();
756
757 #ifdef CONFIG_SYS_LS_MC_FW_IN_DDR
758         printf("MC firmware is preloaded to %#llx\n", mc_ram_addr);
759 #else
760         error = parse_mc_firmware_fit_image(mc_fw_addr, &raw_image_addr,
761                                             &raw_image_size);
762         if (error != 0)
763                 goto out;
764         /*
765          * Load the MC FW at the beginning of the MC private DRAM block:
766          */
767         mc_copy_image("MC Firmware",
768                       (u64)raw_image_addr, raw_image_size, mc_ram_addr);
769 #endif
770         dump_ram_words("firmware", (void *)mc_ram_addr);
771
772         error = load_mc_dpc(mc_ram_addr, mc_ram_size, mc_dpc_addr);
773         if (error != 0)
774                 goto out;
775
776         debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
777         dump_mc_ccsr_regs(mc_ccsr_regs);
778
779         /*
780          * Tell MC what is the address range of the DRAM block assigned to it:
781          */
782         if (mc_ram_num_256mb_blocks < 0xFF) {
783                 reg_mcfbalr = (u32)mc_ram_addr |
784                                 (mc_ram_num_256mb_blocks - 1);
785         } else {
786                 reg_mcfbalr = (u32)mc_ram_addr |
787                                 (mc_ram_num_256mb_blocks);
788         }
789
790         out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr);
791         out_le32(&mc_ccsr_regs->reg_mcfbahr,
792                  (u32)(mc_ram_addr >> 32));
793         out_le32(&mc_ccsr_regs->reg_mcfapr, FSL_BYPASS_AMQ);
794
795         /*
796          * Tell the MC that we want delayed DPL deployment.
797          */
798         out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00);
799
800         printf("\nfsl-mc: Booting Management Complex ... ");
801
802         /*
803          * Deassert reset and release MC core 0 to run
804          */
805         out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
806         error = wait_for_mc(true, &reg_gsr);
807         if (error != 0)
808                 goto out;
809
810         /*
811          * TODO: need to obtain the portal_id for the root container from the
812          * DPL
813          */
814         portal_id = 0;
815
816         /*
817          * Initialize the global default MC portal
818          * And check that the MC firmware is responding portal commands:
819          */
820         root_mc_io = (struct fsl_mc_io *)calloc(sizeof(struct fsl_mc_io), 1);
821         if (!root_mc_io) {
822                 printf(" No memory: calloc() failed\n");
823                 return -ENOMEM;
824         }
825
826         root_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
827         debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
828               portal_id, root_mc_io->mmio_regs);
829
830         error = mc_get_version(root_mc_io, MC_CMD_NO_FLAGS, &mc_ver_info);
831         if (error != 0) {
832                 printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n",
833                        error);
834                 goto out;
835         }
836
837         printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n",
838                mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision,
839                reg_gsr & GSR_FS_MASK);
840
841 out:
842         if (error != 0)
843                 mc_boot_status = error;
844         else
845                 mc_boot_status = 0;
846
847         return error;
848 }
849
850 int mc_apply_dpl(u64 mc_dpl_addr)
851 {
852         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
853         int error = 0;
854         u32 reg_gsr;
855         u64 mc_ram_addr = mc_get_dram_addr();
856         size_t mc_ram_size = mc_get_dram_block_size();
857
858         if (!mc_dpl_addr)
859                 return -1;
860
861         error = load_mc_dpl(mc_ram_addr, mc_ram_size, mc_dpl_addr);
862         if (error != 0)
863                 return error;
864
865         /*
866          * Tell the MC to deploy the DPL:
867          */
868         out_le32(&mc_ccsr_regs->reg_gsr, 0x0);
869         printf("fsl-mc: Deploying data path layout ... ");
870         error = wait_for_mc(false, &reg_gsr);
871
872         if (!error)
873                 mc_dpl_applied = 0;
874
875         return error;
876 }
877
878 int get_mc_boot_status(void)
879 {
880         return mc_boot_status;
881 }
882
883 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
884 int get_aiop_apply_status(void)
885 {
886         return mc_aiop_applied;
887 }
888 #endif
889
890 int get_dpl_apply_status(void)
891 {
892         return mc_dpl_applied;
893 }
894
895 int is_lazy_dpl_addr_valid(void)
896 {
897         return !!mc_lazy_dpl_addr;
898 }
899
900 /*
901  * Return the MC address of private DRAM block.
902  * As per MC design document, MC initial base address
903  * should be least significant 512MB address of MC private
904  * memory, i.e. address should point to end address masked
905  * with 512MB offset in private DRAM block.
906  */
907 u64 mc_get_dram_addr(void)
908 {
909         size_t mc_ram_size = mc_get_dram_block_size();
910
911         if (!mc_memset_resv_ram || (get_mc_boot_status() < 0)) {
912                 mc_memset_resv_ram = 1;
913                 memset((void *)gd->arch.resv_ram, 0, mc_ram_size);
914         }
915
916         return (gd->arch.resv_ram + mc_ram_size - 1) &
917                 MC_RAM_BASE_ADDR_ALIGNMENT_MASK;
918 }
919
920 /**
921  * Return the actual size of the MC private DRAM block.
922  */
923 unsigned long mc_get_dram_block_size(void)
924 {
925         unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
926
927         char *dram_block_size_env_var = env_get(MC_MEM_SIZE_ENV_VAR);
928
929         if (dram_block_size_env_var) {
930                 dram_block_size = simple_strtoul(dram_block_size_env_var, NULL,
931                                                  16);
932
933                 if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
934                         printf("fsl-mc: WARNING: Invalid value for \'"
935                                MC_MEM_SIZE_ENV_VAR
936                                "\' environment variable: %lu\n",
937                                dram_block_size);
938
939                         dram_block_size = MC_DRAM_BLOCK_DEFAULT_SIZE;
940                 }
941         }
942
943         return dram_block_size;
944 }
945
946 int fsl_mc_ldpaa_init(bd_t *bis)
947 {
948         int i;
949
950         for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++)
951                 if (wriop_is_enabled_dpmac(i) == 1)
952                         ldpaa_eth_init(i, wriop_get_enet_if(i));
953         return 0;
954 }
955
956 static int dprc_version_check(struct fsl_mc_io *mc_io, uint16_t handle)
957 {
958         int error;
959         uint16_t major_ver, minor_ver;
960
961         error = dprc_get_api_version(mc_io, 0,
962                                      &major_ver,
963                                      &minor_ver);
964         if (error < 0) {
965                 printf("dprc_get_api_version() failed: %d\n", error);
966                 return error;
967         }
968
969         if (major_ver < DPRC_VER_MAJOR || (major_ver == DPRC_VER_MAJOR &&
970                                            minor_ver < DPRC_VER_MINOR)) {
971                 printf("DPRC version mismatch found %u.%u,",
972                        major_ver, minor_ver);
973                 printf("supported version is %u.%u\n",
974                        DPRC_VER_MAJOR, DPRC_VER_MINOR);
975         }
976
977         return error;
978 }
979
980 static int dpio_init(void)
981 {
982         struct qbman_swp_desc p_des;
983         struct dpio_attr attr;
984         struct dpio_cfg dpio_cfg;
985         int err = 0;
986         uint16_t major_ver, minor_ver;
987
988         dflt_dpio = (struct fsl_dpio_obj *)calloc(
989                                         sizeof(struct fsl_dpio_obj), 1);
990         if (!dflt_dpio) {
991                 printf("No memory: calloc() failed\n");
992                 err = -ENOMEM;
993                 goto err_calloc;
994         }
995         dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL;
996         dpio_cfg.num_priorities = 8;
997
998         err = dpio_create(dflt_mc_io,
999                           dflt_dprc_handle,
1000                           MC_CMD_NO_FLAGS,
1001                           &dpio_cfg,
1002                           &dflt_dpio->dpio_id);
1003         if (err < 0) {
1004                 printf("dpio_create() failed: %d\n", err);
1005                 err = -ENODEV;
1006                 goto err_create;
1007         }
1008
1009         err = dpio_get_api_version(dflt_mc_io, 0,
1010                                    &major_ver,
1011                                    &minor_ver);
1012         if (err < 0) {
1013                 printf("dpio_get_api_version() failed: %d\n", err);
1014                 goto err_get_api_ver;
1015         }
1016
1017         if (major_ver < DPIO_VER_MAJOR || (major_ver == DPIO_VER_MAJOR &&
1018                                            minor_ver < DPIO_VER_MINOR)) {
1019                 printf("DPRC version mismatch found %u.%u,",
1020                        major_ver,
1021                        minor_ver);
1022         }
1023
1024         err = dpio_open(dflt_mc_io,
1025                         MC_CMD_NO_FLAGS,
1026                         dflt_dpio->dpio_id,
1027                         &dflt_dpio->dpio_handle);
1028         if (err) {
1029                 printf("dpio_open() failed\n");
1030                 goto err_open;
1031         }
1032
1033         memset(&attr, 0, sizeof(struct dpio_attr));
1034         err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1035                                   dflt_dpio->dpio_handle, &attr);
1036         if (err < 0) {
1037                 printf("dpio_get_attributes() failed: %d\n", err);
1038                 goto err_get_attr;
1039         }
1040
1041         if (dflt_dpio->dpio_id != attr.id) {
1042                 printf("dnpi object id and attribute id are not same\n");
1043                 goto err_attr_not_same;
1044         }
1045
1046 #ifdef DEBUG
1047         printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id);
1048 #endif
1049         err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1050         if (err < 0) {
1051                 printf("dpio_enable() failed %d\n", err);
1052                 goto err_get_enable;
1053         }
1054         debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n",
1055               attr.qbman_portal_ce_offset,
1056               attr.qbman_portal_ci_offset,
1057               attr.qbman_portal_id,
1058               attr.num_priorities);
1059
1060         p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
1061                                         + attr.qbman_portal_ce_offset);
1062         p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
1063                                         + attr.qbman_portal_ci_offset);
1064
1065         dflt_dpio->sw_portal = qbman_swp_init(&p_des);
1066         if (dflt_dpio->sw_portal == NULL) {
1067                 printf("qbman_swp_init() failed\n");
1068                 goto err_get_swp_init;
1069         }
1070         return 0;
1071
1072 err_get_swp_init:
1073         dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1074 err_get_enable:
1075 err_get_attr:
1076 err_attr_not_same:
1077         dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1078 err_open:
1079 err_get_api_ver:
1080         dpio_destroy(dflt_mc_io,
1081                      dflt_dprc_handle,
1082                      MC_CMD_NO_FLAGS,
1083                      dflt_dpio->dpio_id);
1084 err_create:
1085         free(dflt_dpio);
1086 err_calloc:
1087         return err;
1088 }
1089
1090 static int dpio_exit(void)
1091 {
1092         int err;
1093
1094         err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1095         if (err < 0) {
1096                 printf("dpio_disable() failed: %d\n", err);
1097                 goto err;
1098         }
1099
1100         dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1101         if (err < 0) {
1102                 printf("dpio_close() failed: %d\n", err);
1103                 goto err;
1104         }
1105
1106         err = dpio_destroy(dflt_mc_io,
1107                            dflt_dprc_handle,
1108                            MC_CMD_NO_FLAGS,
1109                            dflt_dpio->dpio_id);
1110         if (err < 0) {
1111                 printf("dpio_destroy() failed: %d\n", err);
1112                 goto err;
1113         }
1114
1115 #ifdef DEBUG
1116         printf("Exit: DPIO id=0x%d\n", dflt_dpio->dpio_id);
1117 #endif
1118
1119         if (dflt_dpio)
1120                 free(dflt_dpio);
1121
1122         return 0;
1123 err:
1124         return err;
1125 }
1126
1127 static int dprc_init(void)
1128 {
1129         int err, child_portal_id, container_id;
1130         struct dprc_cfg cfg;
1131         uint64_t mc_portal_offset;
1132
1133         /* Open root container */
1134         err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id);
1135         if (err < 0) {
1136                 printf("dprc_get_container_id(): Root failed: %d\n", err);
1137                 goto err_root_container_id;
1138         }
1139
1140 #ifdef DEBUG
1141         printf("Root container id = %d\n", container_id);
1142 #endif
1143         err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id,
1144                         &root_dprc_handle);
1145         if (err < 0) {
1146                 printf("dprc_open(): Root Container failed: %d\n", err);
1147                 goto err_root_open;
1148         }
1149
1150         if (!root_dprc_handle) {
1151                 printf("dprc_open(): Root Container Handle is not valid\n");
1152                 goto err_root_open;
1153         }
1154
1155         err = dprc_version_check(root_mc_io, root_dprc_handle);
1156         if (err < 0) {
1157                 printf("dprc_version_check() failed: %d\n", err);
1158                 goto err_root_open;
1159         }
1160
1161         memset(&cfg, 0, sizeof(struct dprc_cfg));
1162         cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED |
1163                       DPRC_CFG_OPT_OBJ_CREATE_ALLOWED |
1164                       DPRC_CFG_OPT_ALLOC_ALLOWED;
1165         cfg.icid = DPRC_GET_ICID_FROM_POOL;
1166         cfg.portal_id = DPRC_GET_PORTAL_ID_FROM_POOL;
1167         err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS,
1168                         root_dprc_handle,
1169                         &cfg,
1170                         &child_dprc_id,
1171                         &mc_portal_offset);
1172         if (err < 0) {
1173                 printf("dprc_create_container() failed: %d\n", err);
1174                 goto err_create;
1175         }
1176
1177         dflt_mc_io = (struct fsl_mc_io *)calloc(sizeof(struct fsl_mc_io), 1);
1178         if (!dflt_mc_io) {
1179                 err  = -ENOMEM;
1180                 printf(" No memory: calloc() failed\n");
1181                 goto err_calloc;
1182         }
1183
1184         child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset);
1185         dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id);
1186
1187 #ifdef DEBUG
1188         printf("MC portal of child DPRC container: %d, physical addr %p)\n",
1189                child_dprc_id, dflt_mc_io->mmio_regs);
1190 #endif
1191
1192         err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id,
1193                         &dflt_dprc_handle);
1194         if (err < 0) {
1195                 printf("dprc_open(): Child container failed: %d\n", err);
1196                 goto err_child_open;
1197         }
1198
1199         if (!dflt_dprc_handle) {
1200                 printf("dprc_open(): Child container Handle is not valid\n");
1201                 goto err_child_open;
1202         }
1203
1204         return 0;
1205 err_child_open:
1206         free(dflt_mc_io);
1207 err_calloc:
1208         dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
1209                                root_dprc_handle, child_dprc_id);
1210 err_create:
1211         dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
1212 err_root_open:
1213 err_root_container_id:
1214         return err;
1215 }
1216
1217 static int dprc_exit(void)
1218 {
1219         int err;
1220
1221         err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle);
1222         if (err < 0) {
1223                 printf("dprc_close(): Child failed: %d\n", err);
1224                 goto err;
1225         }
1226
1227         err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
1228                                      root_dprc_handle, child_dprc_id);
1229         if (err < 0) {
1230                 printf("dprc_destroy_container() failed: %d\n", err);
1231                 goto err;
1232         }
1233
1234         err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
1235         if (err < 0) {
1236                 printf("dprc_close(): Root failed: %d\n", err);
1237                 goto err;
1238         }
1239
1240         if (dflt_mc_io)
1241                 free(dflt_mc_io);
1242
1243         if (root_mc_io)
1244                 free(root_mc_io);
1245
1246         return 0;
1247
1248 err:
1249         return err;
1250 }
1251
1252 static int dpbp_init(void)
1253 {
1254         int err;
1255         struct dpbp_attr dpbp_attr;
1256         struct dpbp_cfg dpbp_cfg;
1257         uint16_t major_ver, minor_ver;
1258
1259         dflt_dpbp = (struct fsl_dpbp_obj *)calloc(
1260                                         sizeof(struct fsl_dpbp_obj), 1);
1261         if (!dflt_dpbp) {
1262                 printf("No memory: calloc() failed\n");
1263                 err = -ENOMEM;
1264                 goto err_calloc;
1265         }
1266
1267         dpbp_cfg.options = 512;
1268
1269         err = dpbp_create(dflt_mc_io,
1270                           dflt_dprc_handle,
1271                           MC_CMD_NO_FLAGS,
1272                           &dpbp_cfg,
1273                           &dflt_dpbp->dpbp_id);
1274
1275         if (err < 0) {
1276                 err = -ENODEV;
1277                 printf("dpbp_create() failed: %d\n", err);
1278                 goto err_create;
1279         }
1280
1281         err = dpbp_get_api_version(dflt_mc_io, 0,
1282                                    &major_ver,
1283                                    &minor_ver);
1284         if (err < 0) {
1285                 printf("dpbp_get_api_version() failed: %d\n", err);
1286                 goto err_get_api_ver;
1287         }
1288
1289         if (major_ver < DPBP_VER_MAJOR || (major_ver == DPBP_VER_MAJOR &&
1290                                            minor_ver < DPBP_VER_MINOR)) {
1291                 printf("DPBP version mismatch found %u.%u,",
1292                        major_ver, minor_ver);
1293                 printf("supported version is %u.%u\n",
1294                        DPBP_VER_MAJOR, DPBP_VER_MINOR);
1295         }
1296
1297         err = dpbp_open(dflt_mc_io,
1298                         MC_CMD_NO_FLAGS,
1299                         dflt_dpbp->dpbp_id,
1300                         &dflt_dpbp->dpbp_handle);
1301         if (err) {
1302                 printf("dpbp_open() failed\n");
1303                 goto err_open;
1304         }
1305
1306         memset(&dpbp_attr, 0, sizeof(struct dpbp_attr));
1307         err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1308                                   dflt_dpbp->dpbp_handle,
1309                                   &dpbp_attr);
1310         if (err < 0) {
1311                 printf("dpbp_get_attributes() failed: %d\n", err);
1312                 goto err_get_attr;
1313         }
1314
1315         if (dflt_dpbp->dpbp_id != dpbp_attr.id) {
1316                 printf("dpbp object id and attribute id are not same\n");
1317                 goto err_attr_not_same;
1318         }
1319
1320 #ifdef DEBUG
1321         printf("Init: DPBP id=0x%x\n", dflt_dpbp->dpbp_attr.id);
1322 #endif
1323
1324         err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1325         if (err < 0) {
1326                 printf("dpbp_close() failed: %d\n", err);
1327                 goto err_close;
1328         }
1329
1330         return 0;
1331
1332 err_get_attr:
1333 err_attr_not_same:
1334         dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1335         dpbp_destroy(dflt_mc_io,
1336                      dflt_dprc_handle,
1337                      MC_CMD_NO_FLAGS,
1338                      dflt_dpbp->dpbp_id);
1339 err_get_api_ver:
1340 err_close:
1341 err_open:
1342 err_create:
1343         free(dflt_dpbp);
1344 err_calloc:
1345         return err;
1346 }
1347
1348 static int dpbp_exit(void)
1349 {
1350         int err;
1351
1352         err = dpbp_destroy(dflt_mc_io, dflt_dprc_handle, MC_CMD_NO_FLAGS,
1353                            dflt_dpbp->dpbp_id);
1354         if (err < 0) {
1355                 printf("dpbp_destroy() failed: %d\n", err);
1356                 goto err;
1357         }
1358
1359 #ifdef DEBUG
1360         printf("Exit: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
1361 #endif
1362
1363         if (dflt_dpbp)
1364                 free(dflt_dpbp);
1365         return 0;
1366
1367 err:
1368         return err;
1369 }
1370
1371 static int dpni_init(void)
1372 {
1373         int err;
1374         uint8_t cfg_buf[256] = {0};
1375         struct dpni_cfg dpni_cfg;
1376         uint16_t major_ver, minor_ver;
1377
1378         dflt_dpni = (struct fsl_dpni_obj *)calloc(
1379                                         sizeof(struct fsl_dpni_obj), 1);
1380         if (!dflt_dpni) {
1381                 printf("No memory: calloc() failed\n");
1382                 err = -ENOMEM;
1383                 goto err_calloc;
1384         }
1385
1386         memset(&dpni_cfg, 0, sizeof(dpni_cfg));
1387         err = dpni_prepare_cfg(&dpni_cfg, &cfg_buf[0]);
1388         if (err < 0) {
1389                 err = -ENODEV;
1390                 printf("dpni_prepare_cfg() failed: %d\n", err);
1391                 goto err_prepare_cfg;
1392         }
1393
1394         err = dpni_create(dflt_mc_io,
1395                           dflt_dprc_handle,
1396                           MC_CMD_NO_FLAGS,
1397                           &dpni_cfg,
1398                           &dflt_dpni->dpni_id);
1399         if (err < 0) {
1400                 err = -ENODEV;
1401                 printf("dpni create() failed: %d\n", err);
1402                 goto err_create;
1403         }
1404
1405         err = dpni_get_api_version(dflt_mc_io, 0,
1406                                    &major_ver,
1407                                    &minor_ver);
1408         if (err < 0) {
1409                 printf("dpni_get_api_version() failed: %d\n", err);
1410                 goto err_get_version;
1411         }
1412
1413         if (major_ver < DPNI_VER_MAJOR || (major_ver == DPNI_VER_MAJOR &&
1414                                            minor_ver < DPNI_VER_MINOR)) {
1415                 printf("DPNI version mismatch found %u.%u,",
1416                        major_ver, minor_ver);
1417                 printf("supported version is %u.%u\n",
1418                        DPNI_VER_MAJOR, DPNI_VER_MINOR);
1419         }
1420
1421         err = dpni_open(dflt_mc_io,
1422                         MC_CMD_NO_FLAGS,
1423                         dflt_dpni->dpni_id,
1424                         &dflt_dpni->dpni_handle);
1425         if (err) {
1426                 printf("dpni_open() failed\n");
1427                 goto err_open;
1428         }
1429
1430 #ifdef DEBUG
1431         printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1432 #endif
1433         err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1434         if (err < 0) {
1435                 printf("dpni_close() failed: %d\n", err);
1436                 goto err_close;
1437         }
1438
1439         return 0;
1440
1441 err_close:
1442         dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1443 err_open:
1444 err_get_version:
1445         dpni_destroy(dflt_mc_io,
1446                      dflt_dprc_handle,
1447                      MC_CMD_NO_FLAGS,
1448                      dflt_dpni->dpni_id);
1449 err_create:
1450 err_prepare_cfg:
1451         free(dflt_dpni);
1452 err_calloc:
1453         return err;
1454 }
1455
1456 static int dpni_exit(void)
1457 {
1458         int err;
1459
1460         err = dpni_destroy(dflt_mc_io, dflt_dprc_handle, MC_CMD_NO_FLAGS,
1461                            dflt_dpni->dpni_id);
1462         if (err < 0) {
1463                 printf("dpni_destroy() failed: %d\n", err);
1464                 goto err;
1465         }
1466
1467 #ifdef DEBUG
1468         printf("Exit: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1469 #endif
1470
1471         if (dflt_dpni)
1472                 free(dflt_dpni);
1473         return 0;
1474
1475 err:
1476         return err;
1477 }
1478
1479 static bool is_dpsparser_supported(void)
1480 {
1481         /* dpsparser support was first introduced in MC version: 10.12.0 */
1482         if (mc_ver_info.major < 10)
1483                 return false;
1484         if (mc_ver_info.major == 10)
1485                 return (mc_ver_info.minor >= 12);
1486         return true;
1487 }
1488
1489 static int dpsparser_version_check(struct fsl_mc_io *mc_io)
1490 {
1491         int error;
1492         u16 major_ver, minor_ver;
1493
1494         if (!is_dpsparser_supported())
1495                 return 0;
1496
1497         error = dpsparser_get_api_version(mc_io, 0,
1498                                           &major_ver,
1499                                           &minor_ver);
1500         if (error < 0) {
1501                 printf("dpsparser_get_api_version() failed: %d\n", error);
1502                 return error;
1503         }
1504
1505         if (major_ver < DPSPARSER_VER_MAJOR || (major_ver ==
1506             DPSPARSER_VER_MAJOR && minor_ver < DPSPARSER_VER_MINOR)) {
1507                 printf("DPSPARSER version mismatch found %u.%u,",
1508                        major_ver, minor_ver);
1509                 printf("supported version is %u.%u\n",
1510                        DPSPARSER_VER_MAJOR, DPSPARSER_VER_MINOR);
1511         }
1512
1513         return error;
1514 }
1515
1516 static int dpsparser_init(void)
1517 {
1518         int err = 0;
1519
1520         if (!is_dpsparser_supported())
1521                 return 0;
1522
1523         err = dpsparser_create(dflt_mc_io,
1524                                dflt_dprc_handle,
1525                                MC_CMD_NO_FLAGS,
1526                                &dpsparser_obj_id);
1527         if (err)
1528                 printf("dpsparser_create() failed\n");
1529
1530         err = dpsparser_version_check(dflt_mc_io);
1531         if (err < 0) {
1532                 printf("dpsparser_version_check() failed: %d\n", err);
1533                 goto err_version_check;
1534         }
1535
1536         err = dpsparser_open(dflt_mc_io,
1537                              MC_CMD_NO_FLAGS,
1538                              &dpsparser_handle);
1539         if (err < 0) {
1540                 printf("dpsparser_open() failed: %d\n", err);
1541                 goto err_open;
1542         }
1543
1544         return err;
1545
1546 err_open:
1547 err_version_check:
1548         dpsparser_destroy(dflt_mc_io,
1549                           dflt_dprc_handle,
1550                           MC_CMD_NO_FLAGS, dpsparser_obj_id);
1551
1552         return err;
1553 }
1554
1555 #ifdef DPSPARSER_DESTROY
1556 /* TODO: refactoring needed in the future to allow DPSPARSER object destroy
1557  * Workaround: DO NOT destroy DPSPARSER object because it needs to be available
1558  * on Apply DPL
1559  */
1560 static int dpsparser_exit(void)
1561 {
1562         int err;
1563
1564         if (!is_dpsparser_supported())
1565                 return 0;
1566
1567         dpsparser_close(dflt_mc_io, MC_CMD_NO_FLAGS, dpsparser_handle);
1568         if (err < 0) {
1569                 printf("dpsparser_close() failed: %d\n", err);
1570                 goto err;
1571         }
1572
1573         err = dpsparser_destroy(dflt_mc_io, dflt_dprc_handle,
1574                                 MC_CMD_NO_FLAGS, dpsparser_obj_id);
1575         if (err < 0) {
1576                 printf("dpsparser_destroy() failed: %d\n", err);
1577                 goto err;
1578         }
1579         return 0;
1580
1581 err:
1582         return err;
1583 }
1584 #endif
1585
1586 int mc_apply_spb(u64 mc_spb_addr)
1587 {
1588         int err = 0;
1589         u16 error, err_arr_size;
1590         u64 mc_spb_offset;
1591         u32 spb_size;
1592         struct sp_blob_header *sp_blob;
1593         u64 mc_ram_addr = mc_get_dram_addr();
1594
1595         if (!is_dpsparser_supported())
1596                 return 0;
1597
1598         if (!mc_spb_addr) {
1599                 printf("fsl-mc: Invalid Blob address\n");
1600                 return -1;
1601         }
1602
1603 #ifdef CONFIG_MC_DRAM_SPB_OFFSET
1604         mc_spb_offset = CONFIG_MC_DRAM_SPB_OFFSET;
1605 #else
1606 #error "CONFIG_MC_DRAM_SPB_OFFSET not defined"
1607 #endif
1608
1609         // Read blob header and get size of SPB blob
1610         sp_blob = (struct sp_blob_header *)mc_spb_addr;
1611         spb_size = le32_to_cpu(sp_blob->length);
1612         if (spb_size > CONFIG_MC_SPB_MAX_SIZE) {
1613                 printf("\nfsl-mc: ERROR: Bad SPB image (too large: %d)\n",
1614                        spb_size);
1615                 return -EINVAL;
1616         }
1617
1618         mc_copy_image("MC SP Blob", mc_spb_addr, spb_size,
1619                       mc_ram_addr + mc_spb_offset);
1620
1621         //Invoke MC command to apply SPB blob
1622         printf("fsl-mc: Applying soft parser blob... ");
1623         err = dpsparser_apply_spb(dflt_mc_io, MC_CMD_NO_FLAGS, dpsparser_handle,
1624                                   mc_spb_offset, &error);
1625         if (err)
1626                 return err;
1627
1628         if (error == 0) {
1629                 printf("SUCCESS\n");
1630         } else {
1631                 printf("FAILED with error code = %d:\n", error);
1632                 err_arr_size = (u16)ARRAY_SIZE(mc_err_msg_apply_spb);
1633
1634                 if (error > 0 && error < err_arr_size)
1635                         printf(mc_err_msg_apply_spb[error]);
1636                 else
1637                         printf(MC_ERROR_MSG_SPB_UNKNOWN);
1638         }
1639
1640         return err;
1641 }
1642
1643 static int mc_init_object(void)
1644 {
1645         int err = 0;
1646
1647         err = dprc_init();
1648         if (err < 0) {
1649                 printf("dprc_init() failed: %d\n", err);
1650                 goto err;
1651         }
1652
1653         err = dpbp_init();
1654         if (err < 0) {
1655                 printf("dpbp_init() failed: %d\n", err);
1656                 goto err;
1657         }
1658
1659         err = dpio_init();
1660         if (err < 0) {
1661                 printf("dpio_init() failed: %d\n", err);
1662                 goto err;
1663         }
1664
1665         err = dpni_init();
1666         if (err < 0) {
1667                 printf("dpni_init() failed: %d\n", err);
1668                 goto err;
1669         }
1670
1671         err = dpsparser_init();
1672         if (err < 0) {
1673                 printf("dpsparser_init() failed: %d\n", err);
1674                 goto err;
1675         }
1676
1677         return 0;
1678 err:
1679         return err;
1680 }
1681
1682 int fsl_mc_ldpaa_exit(bd_t *bd)
1683 {
1684         int err = 0;
1685         bool is_dpl_apply_status = false;
1686         bool mc_boot_status = false;
1687
1688         if (bd && mc_lazy_dpl_addr && !fsl_mc_ldpaa_exit(NULL)) {
1689                 err = mc_apply_dpl(mc_lazy_dpl_addr);
1690                 if (!err)
1691                         fdt_fixup_board_enet(working_fdt);
1692                 mc_lazy_dpl_addr = 0;
1693         }
1694
1695         if (!get_mc_boot_status())
1696                 mc_boot_status = true;
1697
1698         /* MC is not loaded intentionally, So return success. */
1699         if (bd && !mc_boot_status)
1700                 return 0;
1701
1702         /* If DPL is deployed, set is_dpl_apply_status as TRUE. */
1703         if (!get_dpl_apply_status())
1704                 is_dpl_apply_status = true;
1705
1706         /*
1707          * For case MC is loaded but DPL is not deployed, return success and
1708          * print message on console. Else FDT fix-up code execution hanged.
1709          */
1710         if (bd && mc_boot_status && !is_dpl_apply_status) {
1711                 printf("fsl-mc: DPL not deployed, DPAA2 ethernet not work\n");
1712                 goto mc_obj_cleanup;
1713         }
1714
1715         if (bd && mc_boot_status && is_dpl_apply_status)
1716                 return 0;
1717
1718 mc_obj_cleanup:
1719         err = dpbp_exit();
1720         if (err < 0) {
1721                 printf("dpbp_exit() failed: %d\n", err);
1722                 goto err;
1723         }
1724
1725         err = dpio_exit();
1726         if (err < 0) {
1727                 printf("dpio_exit() failed: %d\n", err);
1728                 goto err;
1729         }
1730
1731         err = dpni_exit();
1732         if (err < 0) {
1733                 printf("dpni_exit() failed: %d\n", err);
1734                 goto err;
1735         }
1736
1737         err = dprc_exit();
1738         if (err < 0) {
1739                 printf("dprc_exit() failed: %d\n", err);
1740                 goto err;
1741         }
1742
1743         return 0;
1744 err:
1745         return err;
1746 }
1747
1748 static int do_fsl_mc(struct cmd_tbl *cmdtp, int flag, int argc,
1749                      char *const argv[])
1750 {
1751         int err = 0;
1752         if (argc < 3)
1753                 goto usage;
1754
1755         switch (argv[1][0]) {
1756         case 's': {
1757                         char sub_cmd;
1758                         u64 mc_fw_addr, mc_dpc_addr;
1759 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1760                         u64 aiop_fw_addr;
1761 #endif
1762
1763                         sub_cmd = argv[2][0];
1764
1765                         switch (sub_cmd) {
1766                         case 'm':
1767                                 if (argc < 5)
1768                                         goto usage;
1769
1770                                 if (get_mc_boot_status() == 0) {
1771                                         printf("fsl-mc: MC is already booted");
1772                                         printf("\n");
1773                                         return err;
1774                                 }
1775                                 mc_fw_addr = simple_strtoull(argv[3], NULL, 16);
1776                                 mc_dpc_addr = simple_strtoull(argv[4], NULL,
1777                                                               16);
1778
1779                                 if (!mc_init(mc_fw_addr, mc_dpc_addr))
1780                                         err = mc_init_object();
1781                                 break;
1782
1783 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1784                         case 'a':
1785                                 if (argc < 4)
1786                                         goto usage;
1787                                 if (get_aiop_apply_status() == 0) {
1788                                         printf("fsl-mc: AIOP FW is already");
1789                                         printf(" applied\n");
1790                                         return err;
1791                                 }
1792
1793                                 aiop_fw_addr = simple_strtoull(argv[3], NULL,
1794                                                                16);
1795
1796                                 /* if SoC doesn't have AIOP, err = -ENODEV */
1797                                 err = load_mc_aiop_img(aiop_fw_addr);
1798                                 if (!err)
1799                                         printf("fsl-mc: AIOP FW applied\n");
1800                                 break;
1801 #endif
1802                         default:
1803                                 printf("Invalid option: %s\n", argv[2]);
1804                                 goto usage;
1805
1806                                 break;
1807                         }
1808                 }
1809                 break;
1810
1811         case 'l': {
1812                 /* lazyapply */
1813                 u64 mc_dpl_addr;
1814
1815                 if (argc < 4)
1816                         goto usage;
1817
1818                 if (get_dpl_apply_status() == 0) {
1819                         printf("fsl-mc: DPL already applied\n");
1820                         return err;
1821                 }
1822
1823                 mc_dpl_addr = simple_strtoull(argv[3], NULL, 16);
1824
1825                 if (get_mc_boot_status() != 0) {
1826                         printf("fsl-mc: Deploying data path layout ..");
1827                         printf("ERROR (MC is not booted)\n");
1828                         return -ENODEV;
1829                 }
1830
1831                 /*
1832                  * We will do the actual dpaa exit and dpl apply
1833                  * later from announce_and_cleanup().
1834                  */
1835                 mc_lazy_dpl_addr = mc_dpl_addr;
1836                 break;
1837                 }
1838
1839         case 'a': {
1840                 /* apply */
1841                 char sub_cmd;
1842                 u64 mc_apply_addr;
1843
1844                 if (argc < 4)
1845                         goto usage;
1846
1847                 sub_cmd = argv[2][0];
1848
1849                 switch (sub_cmd) {
1850                 case 'd':
1851                 case 'D':
1852                         if (get_dpl_apply_status() == 0) {
1853                                 printf("fsl-mc: DPL already applied\n");
1854                                 return err;
1855                         }
1856                         if (get_mc_boot_status() != 0) {
1857                                 printf("fsl-mc: Deploying data path layout ..");
1858                                 printf("ERROR (MC is not booted)\n");
1859                                 return -ENODEV;
1860                         }
1861
1862                         mc_apply_addr = simple_strtoull(argv[3], NULL, 16);
1863
1864                         /* The user wants DPL applied now */
1865                         if (!fsl_mc_ldpaa_exit(NULL))
1866                                 err = mc_apply_dpl(mc_apply_addr);
1867                         break;
1868
1869                 case 's':
1870                         if (!is_dpsparser_supported()) {
1871                                 printf("fsl-mc: apply spb command .. ");
1872                                 printf("ERROR: requires at least MC 10.12.0\n");
1873                                 return err;
1874                         }
1875                         if (get_mc_boot_status() != 0) {
1876                                 printf("fsl-mc: Deploying Soft Parser Blob...");
1877                                 printf("ERROR (MC is not booted)\n");
1878                                 return err;
1879                         }
1880
1881                         mc_apply_addr = simple_strtoull(argv[3], NULL, 16);
1882
1883                         /* Apply spb (Soft Parser Blob) */
1884                         err = mc_apply_spb(mc_apply_addr);
1885                         break;
1886
1887                 default:
1888                         printf("Invalid option: %s\n", argv[2]);
1889                         goto usage;
1890                 }
1891                 break;
1892                 }
1893         default:
1894                 printf("Invalid option: %s\n", argv[1]);
1895                 goto usage;
1896                 break;
1897         }
1898         return err;
1899  usage:
1900         return CMD_RET_USAGE;
1901 }
1902
1903 U_BOOT_CMD(
1904         fsl_mc,  CONFIG_SYS_MAXARGS,  1,   do_fsl_mc,
1905         "DPAA2 command to manage Management Complex (MC)",
1906         "start mc [FW_addr] [DPC_addr] - Start Management Complex\n"
1907         "fsl_mc apply DPL [DPL_addr] - Apply DPL file\n"
1908         "fsl_mc lazyapply DPL [DPL_addr] - Apply DPL file on exit\n"
1909         "fsl_mc apply spb [spb_addr] - Apply SPB Soft Parser Blob\n"
1910         "fsl_mc start aiop [FW_addr] - Start AIOP\n"
1911 );
1912
1913 void mc_env_boot(void)
1914 {
1915 #if defined(CONFIG_FSL_MC_ENET)
1916         char *mc_boot_env_var;
1917         /* The MC may only be initialized in the reset PHY function
1918          * because otherwise U-Boot has not yet set up all the MAC
1919          * address info properly. Without MAC addresses, the MC code
1920          * can not properly initialize the DPC.
1921          */
1922         mc_boot_env_var = env_get(MC_BOOT_ENV_VAR);
1923         if (mc_boot_env_var)
1924                 run_command_list(mc_boot_env_var, -1, 0);
1925 #endif /* CONFIG_FSL_MC_ENET */
1926 }