079082a26fda747d0563b57f66ba5e78d635b256
[oweals/u-boot.git] / drivers / net / fsl-mc / mc.c
1 /*
2  * Copyright (C) 2014 Freescale Semiconductor
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6 #include <common.h>
7 #include <errno.h>
8 #include <linux/bug.h>
9 #include <asm/io.h>
10 #include <libfdt.h>
11 #include <net.h>
12 #include <fdt_support.h>
13 #include <fsl-mc/fsl_mc.h>
14 #include <fsl-mc/fsl_mc_sys.h>
15 #include <fsl-mc/fsl_mc_private.h>
16 #include <fsl-mc/fsl_dpmng.h>
17 #include <fsl-mc/fsl_dprc.h>
18 #include <fsl-mc/fsl_dpio.h>
19 #include <fsl-mc/fsl_dpni.h>
20 #include <fsl-mc/fsl_qbman_portal.h>
21 #include <fsl-mc/ldpaa_wriop.h>
22
23 #define MC_RAM_BASE_ADDR_ALIGNMENT  (512UL * 1024 * 1024)
24 #define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1))
25 #define MC_RAM_SIZE_ALIGNMENT       (256UL * 1024 * 1024)
26
27 #define MC_MEM_SIZE_ENV_VAR     "mcmemsize"
28 #define MC_BOOT_TIMEOUT_ENV_VAR "mcboottimeout"
29
30 DECLARE_GLOBAL_DATA_PTR;
31 static int mc_boot_status = -1;
32 static int mc_dpl_applied = -1;
33 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
34 static int mc_aiop_applied = -1;
35 #endif
36 struct fsl_mc_io *root_mc_io = NULL;
37 struct fsl_mc_io *dflt_mc_io = NULL; /* child container */
38 uint16_t root_dprc_handle = 0;
39 uint16_t dflt_dprc_handle = 0;
40 int child_dprc_id;
41 struct fsl_dpbp_obj *dflt_dpbp = NULL;
42 struct fsl_dpio_obj *dflt_dpio = NULL;
43 struct fsl_dpni_obj *dflt_dpni = NULL;
44 static u64 mc_lazy_dpl_addr;
45
46 #ifdef DEBUG
47 void dump_ram_words(const char *title, void *addr)
48 {
49         int i;
50         uint32_t *words = addr;
51
52         printf("Dumping beginning of %s (%p):\n", title, addr);
53         for (i = 0; i < 16; i++)
54                 printf("%#x ", words[i]);
55
56         printf("\n");
57 }
58
59 void dump_mc_ccsr_regs(struct mc_ccsr_registers __iomem *mc_ccsr_regs)
60 {
61         printf("MC CCSR registers:\n"
62                 "reg_gcr1 %#x\n"
63                 "reg_gsr %#x\n"
64                 "reg_sicbalr %#x\n"
65                 "reg_sicbahr %#x\n"
66                 "reg_sicapr %#x\n"
67                 "reg_mcfbalr %#x\n"
68                 "reg_mcfbahr %#x\n"
69                 "reg_mcfapr %#x\n"
70                 "reg_psr %#x\n",
71                 mc_ccsr_regs->reg_gcr1,
72                 mc_ccsr_regs->reg_gsr,
73                 mc_ccsr_regs->reg_sicbalr,
74                 mc_ccsr_regs->reg_sicbahr,
75                 mc_ccsr_regs->reg_sicapr,
76                 mc_ccsr_regs->reg_mcfbalr,
77                 mc_ccsr_regs->reg_mcfbahr,
78                 mc_ccsr_regs->reg_mcfapr,
79                 mc_ccsr_regs->reg_psr);
80 }
81 #else
82
83 #define dump_ram_words(title, addr)
84 #define dump_mc_ccsr_regs(mc_ccsr_regs)
85
86 #endif /* DEBUG */
87
88 #ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
89 /**
90  * Copying MC firmware or DPL image to DDR
91  */
92 static int mc_copy_image(const char *title,
93                          u64 image_addr, u32 image_size, u64 mc_ram_addr)
94 {
95         debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
96         memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
97         flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size);
98         return 0;
99 }
100
101 /**
102  * MC firmware FIT image parser checks if the image is in FIT
103  * format, verifies integrity of the image and calculates
104  * raw image address and size values.
105  * Returns 0 on success and a negative errno on error.
106  * task fail.
107  **/
108 int parse_mc_firmware_fit_image(u64 mc_fw_addr,
109                                 const void **raw_image_addr,
110                                 size_t *raw_image_size)
111 {
112         int format;
113         void *fit_hdr;
114         int node_offset;
115         const void *data;
116         size_t size;
117         const char *uname = "firmware";
118
119         fit_hdr = (void *)mc_fw_addr;
120
121         /* Check if Image is in FIT format */
122         format = genimg_get_format(fit_hdr);
123
124         if (format != IMAGE_FORMAT_FIT) {
125                 printf("fsl-mc: ERR: Bad firmware image (not a FIT image)\n");
126                 return -EINVAL;
127         }
128
129         if (!fit_check_format(fit_hdr)) {
130                 printf("fsl-mc: ERR: Bad firmware image (bad FIT header)\n");
131                 return -EINVAL;
132         }
133
134         node_offset = fit_image_get_node(fit_hdr, uname);
135
136         if (node_offset < 0) {
137                 printf("fsl-mc: ERR: Bad firmware image (missing subimage)\n");
138                 return -ENOENT;
139         }
140
141         /* Verify MC firmware image */
142         if (!(fit_image_verify(fit_hdr, node_offset))) {
143                 printf("fsl-mc: ERR: Bad firmware image (bad CRC)\n");
144                 return -EINVAL;
145         }
146
147         /* Get address and size of raw image */
148         fit_image_get_data(fit_hdr, node_offset, &data, &size);
149
150         *raw_image_addr = data;
151         *raw_image_size = size;
152
153         return 0;
154 }
155 #endif
156
157 /*
158  * Calculates the values to be used to specify the address range
159  * for the MC private DRAM block, in the MCFBALR/MCFBAHR registers.
160  * It returns the highest 512MB-aligned address within the given
161  * address range, in '*aligned_base_addr', and the number of 256 MiB
162  * blocks in it, in 'num_256mb_blocks'.
163  */
164 static int calculate_mc_private_ram_params(u64 mc_private_ram_start_addr,
165                                            size_t mc_ram_size,
166                                            u64 *aligned_base_addr,
167                                            u8 *num_256mb_blocks)
168 {
169         u64 addr;
170         u16 num_blocks;
171
172         if (mc_ram_size % MC_RAM_SIZE_ALIGNMENT != 0) {
173                 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
174                        mc_ram_size);
175                 return -EINVAL;
176         }
177
178         num_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT;
179         if (num_blocks < 1 || num_blocks > 0xff) {
180                 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
181                        mc_ram_size);
182                 return -EINVAL;
183         }
184
185         addr = (mc_private_ram_start_addr + mc_ram_size - 1) &
186                 MC_RAM_BASE_ADDR_ALIGNMENT_MASK;
187
188         if (addr < mc_private_ram_start_addr) {
189                 printf("fsl-mc: ERROR: bad start address %#llx\n",
190                        mc_private_ram_start_addr);
191                 return -EFAULT;
192         }
193
194         *aligned_base_addr = addr;
195         *num_256mb_blocks = num_blocks;
196         return 0;
197 }
198
199 static int mc_fixup_dpc_mac_addr(void *blob, int noff, int dpmac_id,
200                 struct eth_device *eth_dev)
201 {
202         int nodeoffset, err = 0;
203         char mac_name[10];
204         const char link_type_mode[] = "FIXED_LINK";
205         unsigned char env_enetaddr[6];
206
207         sprintf(mac_name, "mac@%d", dpmac_id);
208
209         /* node not found - create it */
210         nodeoffset = fdt_subnode_offset(blob, noff, (const char *) mac_name);
211         if (nodeoffset < 0) {
212                 err = fdt_increase_size(blob, 200);
213                 if (err) {
214                         printf("fdt_increase_size: err=%s\n",
215                                 fdt_strerror(err));
216                         return err;
217                 }
218
219                 nodeoffset = fdt_add_subnode(blob, noff, mac_name);
220
221                 /* add default property of fixed link */
222                 err = fdt_appendprop_string(blob, nodeoffset,
223                                             "link_type", link_type_mode);
224                 if (err) {
225                         printf("fdt_appendprop_string: err=%s\n",
226                                 fdt_strerror(err));
227                         return err;
228                 }
229         }
230
231         /* port_mac_address property present in DPC */
232         if (fdt_get_property(blob, nodeoffset, "port_mac_address", NULL)) {
233                 /* MAC addr randomly assigned - leave the one in DPC */
234                 eth_getenv_enetaddr_by_index("eth", eth_dev->index,
235                                                 env_enetaddr);
236                 if (is_zero_ethaddr(env_enetaddr))
237                         return err;
238
239                 /* replace DPC MAC address with u-boot env one */
240                 err = fdt_setprop(blob, nodeoffset, "port_mac_address",
241                                   eth_dev->enetaddr, 6);
242                 if (err) {
243                         printf("fdt_setprop mac: err=%s\n", fdt_strerror(err));
244                         return err;
245                 }
246
247                 return 0;
248         }
249
250         /* append port_mac_address property to mac node in DPC */
251         err = fdt_increase_size(blob, 80);
252         if (err) {
253                 printf("fdt_increase_size: err=%s\n", fdt_strerror(err));
254                 return err;
255         }
256
257         err = fdt_appendprop(blob, nodeoffset,
258                              "port_mac_address", eth_dev->enetaddr, 6);
259         if (err) {
260                 printf("fdt_appendprop: err=%s\n", fdt_strerror(err));
261                 return err;
262         }
263
264         return err;
265 }
266
267 static int mc_fixup_dpc(u64 dpc_addr)
268 {
269         void *blob = (void *)dpc_addr;
270         int nodeoffset, err = 0;
271         char ethname[10];
272         struct eth_device *eth_dev;
273         int i;
274
275         /* delete any existing ICID pools */
276         nodeoffset = fdt_path_offset(blob, "/resources/icid_pools");
277         if (fdt_del_node(blob, nodeoffset) < 0)
278                 printf("\nfsl-mc: WARNING: could not delete ICID pool\n");
279
280         /* add a new pool */
281         nodeoffset = fdt_path_offset(blob, "/resources");
282         if (nodeoffset < 0) {
283                 printf("\nfsl-mc: ERROR: DPC is missing /resources\n");
284                 return -EINVAL;
285         }
286         nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pools");
287         nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pool@0");
288         do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
289                              "base_icid", FSL_DPAA2_STREAM_ID_START, 1);
290         do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
291                              "num",
292                              FSL_DPAA2_STREAM_ID_END -
293                              FSL_DPAA2_STREAM_ID_START + 1, 1);
294
295         /* fixup MAC addresses for dpmac ports */
296         nodeoffset = fdt_path_offset(blob, "/board_info/ports");
297         if (nodeoffset < 0)
298                 goto out;
299
300         for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
301                 /* port not enabled */
302                 if ((wriop_is_enabled_dpmac(i) != 1) ||
303                     (wriop_get_phy_address(i) == -1))
304                         continue;
305
306                 sprintf(ethname, "DPMAC%d@%s", i,
307                         phy_interface_strings[wriop_get_enet_if(i)]);
308
309                 eth_dev = eth_get_dev_by_name(ethname);
310                 if (eth_dev == NULL)
311                         continue;
312
313                 err = mc_fixup_dpc_mac_addr(blob, nodeoffset, i, eth_dev);
314                 if (err) {
315                         printf("mc_fixup_dpc_mac_addr failed: err=%s\n",
316                         fdt_strerror(err));
317                         goto out;
318                 }
319         }
320
321 out:
322         flush_dcache_range(dpc_addr, dpc_addr + fdt_totalsize(blob));
323
324         return err;
325 }
326
327 static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpc_addr)
328 {
329         u64 mc_dpc_offset;
330 #ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
331         int error;
332         void *dpc_fdt_hdr;
333         int dpc_size;
334 #endif
335
336 #ifdef CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET
337         BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET & 0x3) != 0 ||
338                      CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET > 0xffffffff);
339
340         mc_dpc_offset = CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET;
341 #else
342 #error "CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET not defined"
343 #endif
344
345         /*
346          * Load the MC DPC blob in the MC private DRAM block:
347          */
348 #ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
349         printf("MC DPC is preloaded to %#llx\n", mc_ram_addr + mc_dpc_offset);
350 #else
351         /*
352          * Get address and size of the DPC blob stored in flash:
353          */
354         dpc_fdt_hdr = (void *)mc_dpc_addr;
355
356         error = fdt_check_header(dpc_fdt_hdr);
357         if (error != 0) {
358                 /*
359                  * Don't return with error here, since the MC firmware can
360                  * still boot without a DPC
361                  */
362                 printf("\nfsl-mc: WARNING: No DPC image found");
363                 return 0;
364         }
365
366         dpc_size = fdt_totalsize(dpc_fdt_hdr);
367         if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) {
368                 printf("\nfsl-mc: ERROR: Bad DPC image (too large: %d)\n",
369                        dpc_size);
370                 return -EINVAL;
371         }
372
373         mc_copy_image("MC DPC blob",
374                       (u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset);
375 #endif /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */
376
377         if (mc_fixup_dpc(mc_ram_addr + mc_dpc_offset))
378                 return -EINVAL;
379
380         dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset));
381         return 0;
382 }
383
384 static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpl_addr)
385 {
386         u64 mc_dpl_offset;
387 #ifndef CONFIG_SYS_LS_MC_DPL_IN_DDR
388         int error;
389         void *dpl_fdt_hdr;
390         int dpl_size;
391 #endif
392
393 #ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
394         BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
395                      CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
396
397         mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
398 #else
399 #error "CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET not defined"
400 #endif
401
402         /*
403          * Load the MC DPL blob in the MC private DRAM block:
404          */
405 #ifdef CONFIG_SYS_LS_MC_DPL_IN_DDR
406         printf("MC DPL is preloaded to %#llx\n", mc_ram_addr + mc_dpl_offset);
407 #else
408         /*
409          * Get address and size of the DPL blob stored in flash:
410          */
411         dpl_fdt_hdr = (void *)mc_dpl_addr;
412
413         error = fdt_check_header(dpl_fdt_hdr);
414         if (error != 0) {
415                 printf("\nfsl-mc: ERROR: Bad DPL image (bad header)\n");
416                 return error;
417         }
418
419         dpl_size = fdt_totalsize(dpl_fdt_hdr);
420         if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
421                 printf("\nfsl-mc: ERROR: Bad DPL image (too large: %d)\n",
422                        dpl_size);
423                 return -EINVAL;
424         }
425
426         mc_copy_image("MC DPL blob",
427                       (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
428 #endif /* not defined CONFIG_SYS_LS_MC_DPL_IN_DDR */
429
430         dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset));
431         return 0;
432 }
433
434 /**
435  * Return the MC boot timeout value in milliseconds
436  */
437 static unsigned long get_mc_boot_timeout_ms(void)
438 {
439         unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
440
441         char *timeout_ms_env_var = getenv(MC_BOOT_TIMEOUT_ENV_VAR);
442
443         if (timeout_ms_env_var) {
444                 timeout_ms = simple_strtoul(timeout_ms_env_var, NULL, 10);
445                 if (timeout_ms == 0) {
446                         printf("fsl-mc: WARNING: Invalid value for \'"
447                                MC_BOOT_TIMEOUT_ENV_VAR
448                                "\' environment variable: %lu\n",
449                                timeout_ms);
450
451                         timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
452                 }
453         }
454
455         return timeout_ms;
456 }
457
458 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
459
460 __weak bool soc_has_aiop(void)
461 {
462         return false;
463 }
464
465 static int load_mc_aiop_img(u64 aiop_fw_addr)
466 {
467         u64 mc_ram_addr = mc_get_dram_addr();
468 #ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
469         void *aiop_img;
470 #endif
471
472         /* Check if AIOP is available */
473         if (!soc_has_aiop())
474                 return -ENODEV;
475         /*
476          * Load the MC AIOP image in the MC private DRAM block:
477          */
478
479 #ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
480         printf("MC AIOP is preloaded to %#llx\n", mc_ram_addr +
481                CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
482 #else
483         aiop_img = (void *)aiop_fw_addr;
484         mc_copy_image("MC AIOP image",
485                       (u64)aiop_img, CONFIG_SYS_LS_MC_AIOP_IMG_MAX_LENGTH,
486                       mc_ram_addr + CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
487 #endif
488         mc_aiop_applied = 0;
489
490         return 0;
491 }
492 #endif
493
494 static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr)
495 {
496         u32 reg_gsr;
497         u32 mc_fw_boot_status;
498         unsigned long timeout_ms = get_mc_boot_timeout_ms();
499         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
500
501         dmb();
502         assert(timeout_ms > 0);
503         for (;;) {
504                 udelay(1000);   /* throttle polling */
505                 reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
506                 mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
507                 if (mc_fw_boot_status & 0x1)
508                         break;
509
510                 timeout_ms--;
511                 if (timeout_ms == 0)
512                         break;
513         }
514
515         if (timeout_ms == 0) {
516                 printf("ERROR: timeout\n");
517
518                 /* TODO: Get an error status from an MC CCSR register */
519                 return -ETIMEDOUT;
520         }
521
522         if (mc_fw_boot_status != 0x1) {
523                 /*
524                  * TODO: Identify critical errors from the GSR register's FS
525                  * field and for those errors, set error to -ENODEV or other
526                  * appropriate errno, so that the status property is set to
527                  * failure in the fsl,dprc device tree node.
528                  */
529                 printf("WARNING: Firmware returned an error (GSR: %#x)\n",
530                        reg_gsr);
531         } else {
532                 printf("SUCCESS\n");
533         }
534
535
536         *final_reg_gsr = reg_gsr;
537         return 0;
538 }
539
540 int mc_init(u64 mc_fw_addr, u64 mc_dpc_addr)
541 {
542         int error = 0;
543         int portal_id = 0;
544         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
545         u64 mc_ram_addr = mc_get_dram_addr();
546         u32 reg_gsr;
547         u32 reg_mcfbalr;
548 #ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
549         const void *raw_image_addr;
550         size_t raw_image_size = 0;
551 #endif
552         struct mc_version mc_ver_info;
553         u64 mc_ram_aligned_base_addr;
554         u8 mc_ram_num_256mb_blocks;
555         size_t mc_ram_size = mc_get_dram_block_size();
556
557
558         error = calculate_mc_private_ram_params(mc_ram_addr,
559                                                 mc_ram_size,
560                                                 &mc_ram_aligned_base_addr,
561                                                 &mc_ram_num_256mb_blocks);
562         if (error != 0)
563                 goto out;
564
565         /*
566          * Management Complex cores should be held at reset out of POR.
567          * U-Boot should be the first software to touch MC. To be safe,
568          * we reset all cores again by setting GCR1 to 0. It doesn't do
569          * anything if they are held at reset. After we setup the firmware
570          * we kick off MC by deasserting the reset bit for core 0, and
571          * deasserting the reset bits for Command Portal Managers.
572          * The stop bits are not touched here. They are used to stop the
573          * cores when they are active. Setting stop bits doesn't stop the
574          * cores from fetching instructions when they are released from
575          * reset.
576          */
577         out_le32(&mc_ccsr_regs->reg_gcr1, 0);
578         dmb();
579
580 #ifdef CONFIG_SYS_LS_MC_FW_IN_DDR
581         printf("MC firmware is preloaded to %#llx\n", mc_ram_addr);
582 #else
583         error = parse_mc_firmware_fit_image(mc_fw_addr, &raw_image_addr,
584                                             &raw_image_size);
585         if (error != 0)
586                 goto out;
587         /*
588          * Load the MC FW at the beginning of the MC private DRAM block:
589          */
590         mc_copy_image("MC Firmware",
591                       (u64)raw_image_addr, raw_image_size, mc_ram_addr);
592 #endif
593         dump_ram_words("firmware", (void *)mc_ram_addr);
594
595         error = load_mc_dpc(mc_ram_addr, mc_ram_size, mc_dpc_addr);
596         if (error != 0)
597                 goto out;
598
599         debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
600         dump_mc_ccsr_regs(mc_ccsr_regs);
601
602         /*
603          * Tell MC what is the address range of the DRAM block assigned to it:
604          */
605         reg_mcfbalr = (u32)mc_ram_aligned_base_addr |
606                       (mc_ram_num_256mb_blocks - 1);
607         out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr);
608         out_le32(&mc_ccsr_regs->reg_mcfbahr,
609                  (u32)(mc_ram_aligned_base_addr >> 32));
610         out_le32(&mc_ccsr_regs->reg_mcfapr, FSL_BYPASS_AMQ);
611
612         /*
613          * Tell the MC that we want delayed DPL deployment.
614          */
615         out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00);
616
617         printf("\nfsl-mc: Booting Management Complex ... ");
618
619         /*
620          * Deassert reset and release MC core 0 to run
621          */
622         out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
623         error = wait_for_mc(true, &reg_gsr);
624         if (error != 0)
625                 goto out;
626
627         /*
628          * TODO: need to obtain the portal_id for the root container from the
629          * DPL
630          */
631         portal_id = 0;
632
633         /*
634          * Initialize the global default MC portal
635          * And check that the MC firmware is responding portal commands:
636          */
637         root_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
638         if (!root_mc_io) {
639                 printf(" No memory: malloc() failed\n");
640                 return -ENOMEM;
641         }
642
643         root_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
644         debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
645               portal_id, root_mc_io->mmio_regs);
646
647         error = mc_get_version(root_mc_io, MC_CMD_NO_FLAGS, &mc_ver_info);
648         if (error != 0) {
649                 printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n",
650                        error);
651                 goto out;
652         }
653
654         printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n",
655                mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision,
656                reg_gsr & GSR_FS_MASK);
657
658 out:
659         if (error != 0)
660                 mc_boot_status = error;
661         else
662                 mc_boot_status = 0;
663
664         return error;
665 }
666
667 int mc_apply_dpl(u64 mc_dpl_addr)
668 {
669         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
670         int error = 0;
671         u32 reg_gsr;
672         u64 mc_ram_addr = mc_get_dram_addr();
673         size_t mc_ram_size = mc_get_dram_block_size();
674
675         if (!mc_dpl_addr)
676                 return -1;
677
678         error = load_mc_dpl(mc_ram_addr, mc_ram_size, mc_dpl_addr);
679         if (error != 0)
680                 return error;
681
682         /*
683          * Tell the MC to deploy the DPL:
684          */
685         out_le32(&mc_ccsr_regs->reg_gsr, 0x0);
686         printf("fsl-mc: Deploying data path layout ... ");
687         error = wait_for_mc(false, &reg_gsr);
688
689         if (!error)
690                 mc_dpl_applied = 0;
691
692         return error;
693 }
694
695 int get_mc_boot_status(void)
696 {
697         return mc_boot_status;
698 }
699
700 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
701 int get_aiop_apply_status(void)
702 {
703         return mc_aiop_applied;
704 }
705 #endif
706
707 int get_dpl_apply_status(void)
708 {
709         return mc_dpl_applied;
710 }
711
712 /**
713  * Return the MC address of private DRAM block.
714  */
715 u64 mc_get_dram_addr(void)
716 {
717         u64 mc_ram_addr;
718
719         /*
720          * The MC private DRAM block was already carved at the end of DRAM
721          * by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE:
722          */
723         if (gd->bd->bi_dram[1].start) {
724                 mc_ram_addr =
725                         gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size;
726         } else {
727                 mc_ram_addr =
728                         gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
729         }
730
731         return mc_ram_addr;
732 }
733
734 /**
735  * Return the actual size of the MC private DRAM block.
736  */
737 unsigned long mc_get_dram_block_size(void)
738 {
739         unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
740
741         char *dram_block_size_env_var = getenv(MC_MEM_SIZE_ENV_VAR);
742
743         if (dram_block_size_env_var) {
744                 dram_block_size = simple_strtoul(dram_block_size_env_var, NULL,
745                                                  10);
746
747                 if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
748                         printf("fsl-mc: WARNING: Invalid value for \'"
749                                MC_MEM_SIZE_ENV_VAR
750                                "\' environment variable: %lu\n",
751                                dram_block_size);
752
753                         dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
754                 }
755         }
756
757         return dram_block_size;
758 }
759
760 int fsl_mc_ldpaa_init(bd_t *bis)
761 {
762         int i;
763
764         for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++)
765                 if ((wriop_is_enabled_dpmac(i) == 1) &&
766                     (wriop_get_phy_address(i) != -1))
767                         ldpaa_eth_init(i, wriop_get_enet_if(i));
768         return 0;
769 }
770
771 static int dprc_version_check(struct fsl_mc_io *mc_io, uint16_t handle)
772 {
773         struct dprc_attributes attr;
774         int error;
775
776         memset(&attr, 0, sizeof(struct dprc_attributes));
777         error = dprc_get_attributes(mc_io, MC_CMD_NO_FLAGS, handle, &attr);
778         if (error == 0) {
779                 if ((attr.version.major != DPRC_VER_MAJOR) ||
780                     (attr.version.minor != DPRC_VER_MINOR)) {
781                         printf("DPRC version mismatch found %u.%u,",
782                                attr.version.major,
783                                attr.version.minor);
784                         printf("supported version is %u.%u\n",
785                                DPRC_VER_MAJOR, DPRC_VER_MINOR);
786                 }
787         }
788         return error;
789 }
790
791 static int dpio_init(void)
792 {
793         struct qbman_swp_desc p_des;
794         struct dpio_attr attr;
795         struct dpio_cfg dpio_cfg;
796         int err = 0;
797
798         dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj));
799         if (!dflt_dpio) {
800                 printf("No memory: malloc() failed\n");
801                 err = -ENOMEM;
802                 goto err_malloc;
803         }
804
805         dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL;
806         dpio_cfg.num_priorities = 8;
807
808         err = dpio_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpio_cfg,
809                           &dflt_dpio->dpio_handle);
810         if (err < 0) {
811                 printf("dpio_create() failed: %d\n", err);
812                 err = -ENODEV;
813                 goto err_create;
814         }
815
816         memset(&attr, 0, sizeof(struct dpio_attr));
817         err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
818                                   dflt_dpio->dpio_handle, &attr);
819         if (err < 0) {
820                 printf("dpio_get_attributes() failed: %d\n", err);
821                 goto err_get_attr;
822         }
823
824         if ((attr.version.major != DPIO_VER_MAJOR) ||
825             (attr.version.minor != DPIO_VER_MINOR)) {
826                 printf("DPIO version mismatch found %u.%u,",
827                        attr.version.major, attr.version.minor);
828                 printf("supported version is %u.%u\n",
829                        DPIO_VER_MAJOR, DPIO_VER_MINOR);
830         }
831
832         dflt_dpio->dpio_id = attr.id;
833 #ifdef DEBUG
834         printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id);
835 #endif
836         err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
837         if (err < 0) {
838                 printf("dpio_enable() failed %d\n", err);
839                 goto err_get_enable;
840         }
841         debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n",
842               attr.qbman_portal_ce_offset,
843               attr.qbman_portal_ci_offset,
844               attr.qbman_portal_id,
845               attr.num_priorities);
846
847         p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
848                                         + attr.qbman_portal_ce_offset);
849         p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
850                                         + attr.qbman_portal_ci_offset);
851
852         dflt_dpio->sw_portal = qbman_swp_init(&p_des);
853         if (dflt_dpio->sw_portal == NULL) {
854                 printf("qbman_swp_init() failed\n");
855                 goto err_get_swp_init;
856         }
857         return 0;
858
859 err_get_swp_init:
860         dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
861 err_get_enable:
862 err_get_attr:
863         dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
864         dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
865 err_create:
866         free(dflt_dpio);
867 err_malloc:
868         return err;
869 }
870
871 static int dpio_exit(void)
872 {
873         int err;
874
875         err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
876         if (err < 0) {
877                 printf("dpio_disable() failed: %d\n", err);
878                 goto err;
879         }
880
881         err = dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
882         if (err < 0) {
883                 printf("dpio_destroy() failed: %d\n", err);
884                 goto err;
885         }
886
887 #ifdef DEBUG
888         printf("Exit: DPIO id=0x%d\n", dflt_dpio->dpio_id);
889 #endif
890
891         if (dflt_dpio)
892                 free(dflt_dpio);
893
894         return 0;
895 err:
896         return err;
897 }
898
899 static int dprc_init(void)
900 {
901         int err, child_portal_id, container_id;
902         struct dprc_cfg cfg;
903         uint64_t mc_portal_offset;
904
905         /* Open root container */
906         err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id);
907         if (err < 0) {
908                 printf("dprc_get_container_id(): Root failed: %d\n", err);
909                 goto err_root_container_id;
910         }
911
912 #ifdef DEBUG
913         printf("Root container id = %d\n", container_id);
914 #endif
915         err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id,
916                         &root_dprc_handle);
917         if (err < 0) {
918                 printf("dprc_open(): Root Container failed: %d\n", err);
919                 goto err_root_open;
920         }
921
922         if (!root_dprc_handle) {
923                 printf("dprc_open(): Root Container Handle is not valid\n");
924                 goto err_root_open;
925         }
926
927         err = dprc_version_check(root_mc_io, root_dprc_handle);
928         if (err < 0) {
929                 printf("dprc_version_check() failed: %d\n", err);
930                 goto err_root_open;
931         }
932
933         memset(&cfg, 0, sizeof(struct dprc_cfg));
934         cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED |
935                       DPRC_CFG_OPT_OBJ_CREATE_ALLOWED |
936                       DPRC_CFG_OPT_ALLOC_ALLOWED;
937         cfg.icid = DPRC_GET_ICID_FROM_POOL;
938         cfg.portal_id = DPRC_GET_PORTAL_ID_FROM_POOL;
939         err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS,
940                         root_dprc_handle,
941                         &cfg,
942                         &child_dprc_id,
943                         &mc_portal_offset);
944         if (err < 0) {
945                 printf("dprc_create_container() failed: %d\n", err);
946                 goto err_create;
947         }
948
949         dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
950         if (!dflt_mc_io) {
951                 err  = -ENOMEM;
952                 printf(" No memory: malloc() failed\n");
953                 goto err_malloc;
954         }
955
956         child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset);
957         dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id);
958 #ifdef DEBUG
959         printf("MC portal of child DPRC container: %d, physical addr %p)\n",
960                child_dprc_id, dflt_mc_io->mmio_regs);
961 #endif
962
963         err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id,
964                         &dflt_dprc_handle);
965         if (err < 0) {
966                 printf("dprc_open(): Child container failed: %d\n", err);
967                 goto err_child_open;
968         }
969
970         if (!dflt_dprc_handle) {
971                 printf("dprc_open(): Child container Handle is not valid\n");
972                 goto err_child_open;
973         }
974
975         return 0;
976 err_child_open:
977         free(dflt_mc_io);
978 err_malloc:
979         dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
980                                root_dprc_handle, child_dprc_id);
981 err_create:
982         dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
983 err_root_open:
984 err_root_container_id:
985         return err;
986 }
987
988 static int dprc_exit(void)
989 {
990         int err;
991
992         err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle);
993         if (err < 0) {
994                 printf("dprc_close(): Child failed: %d\n", err);
995                 goto err;
996         }
997
998         err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
999                                      root_dprc_handle, child_dprc_id);
1000         if (err < 0) {
1001                 printf("dprc_destroy_container() failed: %d\n", err);
1002                 goto err;
1003         }
1004
1005         err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
1006         if (err < 0) {
1007                 printf("dprc_close(): Root failed: %d\n", err);
1008                 goto err;
1009         }
1010
1011         if (dflt_mc_io)
1012                 free(dflt_mc_io);
1013
1014         if (root_mc_io)
1015                 free(root_mc_io);
1016
1017         return 0;
1018
1019 err:
1020         return err;
1021 }
1022
1023 static int dpbp_init(void)
1024 {
1025         int err;
1026         struct dpbp_attr dpbp_attr;
1027         struct dpbp_cfg dpbp_cfg;
1028
1029         dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj));
1030         if (!dflt_dpbp) {
1031                 printf("No memory: malloc() failed\n");
1032                 err = -ENOMEM;
1033                 goto err_malloc;
1034         }
1035
1036         dpbp_cfg.options = 512;
1037
1038         err = dpbp_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpbp_cfg,
1039                           &dflt_dpbp->dpbp_handle);
1040
1041         if (err < 0) {
1042                 err = -ENODEV;
1043                 printf("dpbp_create() failed: %d\n", err);
1044                 goto err_create;
1045         }
1046
1047         memset(&dpbp_attr, 0, sizeof(struct dpbp_attr));
1048         err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1049                                   dflt_dpbp->dpbp_handle,
1050                                   &dpbp_attr);
1051         if (err < 0) {
1052                 printf("dpbp_get_attributes() failed: %d\n", err);
1053                 goto err_get_attr;
1054         }
1055
1056         if ((dpbp_attr.version.major != DPBP_VER_MAJOR) ||
1057             (dpbp_attr.version.minor != DPBP_VER_MINOR)) {
1058                 printf("DPBP version mismatch found %u.%u,",
1059                        dpbp_attr.version.major, dpbp_attr.version.minor);
1060                 printf("supported version is %u.%u\n",
1061                        DPBP_VER_MAJOR, DPBP_VER_MINOR);
1062         }
1063
1064         dflt_dpbp->dpbp_attr.id = dpbp_attr.id;
1065 #ifdef DEBUG
1066         printf("Init: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
1067 #endif
1068
1069         err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1070         if (err < 0) {
1071                 printf("dpbp_close() failed: %d\n", err);
1072                 goto err_close;
1073         }
1074
1075         return 0;
1076
1077 err_close:
1078         free(dflt_dpbp);
1079 err_get_attr:
1080         dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1081         dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1082 err_create:
1083 err_malloc:
1084         return err;
1085 }
1086
1087 static int dpbp_exit(void)
1088 {
1089         int err;
1090
1091         err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
1092                         &dflt_dpbp->dpbp_handle);
1093         if (err < 0) {
1094                 printf("dpbp_open() failed: %d\n", err);
1095                 goto err;
1096         }
1097
1098         err = dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
1099                            dflt_dpbp->dpbp_handle);
1100         if (err < 0) {
1101                 printf("dpbp_destroy() failed: %d\n", err);
1102                 goto err;
1103         }
1104
1105 #ifdef DEBUG
1106         printf("Exit: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
1107 #endif
1108
1109         if (dflt_dpbp)
1110                 free(dflt_dpbp);
1111         return 0;
1112
1113 err:
1114         return err;
1115 }
1116
1117 static int dpni_init(void)
1118 {
1119         int err;
1120         struct dpni_attr dpni_attr;
1121         uint8_t ext_cfg_buf[256] = {0};
1122         struct dpni_extended_cfg dpni_extended_cfg;
1123         struct dpni_cfg dpni_cfg;
1124
1125         dflt_dpni = (struct fsl_dpni_obj *)malloc(sizeof(struct fsl_dpni_obj));
1126         if (!dflt_dpni) {
1127                 printf("No memory: malloc() failed\n");
1128                 err = -ENOMEM;
1129                 goto err_malloc;
1130         }
1131
1132         memset(&dpni_extended_cfg, 0, sizeof(dpni_extended_cfg));
1133         err = dpni_prepare_extended_cfg(&dpni_extended_cfg, &ext_cfg_buf[0]);
1134         if (err < 0) {
1135                 err = -ENODEV;
1136                 printf("dpni_prepare_extended_cfg() failed: %d\n", err);
1137                 goto err_prepare_extended_cfg;
1138         }
1139
1140         memset(&dpni_cfg, 0, sizeof(dpni_cfg));
1141         dpni_cfg.adv.options = DPNI_OPT_UNICAST_FILTER |
1142                                DPNI_OPT_MULTICAST_FILTER;
1143
1144         dpni_cfg.adv.ext_cfg_iova = (uint64_t)&ext_cfg_buf[0];
1145         err = dpni_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpni_cfg,
1146                           &dflt_dpni->dpni_handle);
1147
1148         if (err < 0) {
1149                 err = -ENODEV;
1150                 printf("dpni_create() failed: %d\n", err);
1151                 goto err_create;
1152         }
1153
1154         memset(&dpni_attr, 0, sizeof(struct dpni_attr));
1155         err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1156                                   dflt_dpni->dpni_handle,
1157                                   &dpni_attr);
1158         if (err < 0) {
1159                 printf("dpni_get_attributes() failed: %d\n", err);
1160                 goto err_get_attr;
1161         }
1162
1163         if ((dpni_attr.version.major != DPNI_VER_MAJOR) ||
1164             (dpni_attr.version.minor != DPNI_VER_MINOR)) {
1165                 printf("DPNI version mismatch found %u.%u,",
1166                        dpni_attr.version.major, dpni_attr.version.minor);
1167                 printf("supported version is %u.%u\n",
1168                        DPNI_VER_MAJOR, DPNI_VER_MINOR);
1169         }
1170
1171         dflt_dpni->dpni_id = dpni_attr.id;
1172 #ifdef DEBUG
1173         printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1174 #endif
1175
1176         err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1177         if (err < 0) {
1178                 printf("dpni_close() failed: %d\n", err);
1179                 goto err_close;
1180         }
1181
1182         return 0;
1183
1184 err_close:
1185 err_get_attr:
1186         dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1187         dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1188 err_create:
1189 err_prepare_extended_cfg:
1190         free(dflt_dpni);
1191 err_malloc:
1192         return err;
1193 }
1194
1195 static int dpni_exit(void)
1196 {
1197         int err;
1198
1199         err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
1200                         &dflt_dpni->dpni_handle);
1201         if (err < 0) {
1202                 printf("dpni_open() failed: %d\n", err);
1203                 goto err;
1204         }
1205
1206         err = dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
1207                            dflt_dpni->dpni_handle);
1208         if (err < 0) {
1209                 printf("dpni_destroy() failed: %d\n", err);
1210                 goto err;
1211         }
1212
1213 #ifdef DEBUG
1214         printf("Exit: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1215 #endif
1216
1217         if (dflt_dpni)
1218                 free(dflt_dpni);
1219         return 0;
1220
1221 err:
1222         return err;
1223 }
1224
1225 static int mc_init_object(void)
1226 {
1227         int err = 0;
1228
1229         err = dprc_init();
1230         if (err < 0) {
1231                 printf("dprc_init() failed: %d\n", err);
1232                 goto err;
1233         }
1234
1235         err = dpbp_init();
1236         if (err < 0) {
1237                 printf("dpbp_init() failed: %d\n", err);
1238                 goto err;
1239         }
1240
1241         err = dpio_init();
1242         if (err < 0) {
1243                 printf("dpio_init() failed: %d\n", err);
1244                 goto err;
1245         }
1246
1247         err = dpni_init();
1248         if (err < 0) {
1249                 printf("dpni_init() failed: %d\n", err);
1250                 goto err;
1251         }
1252
1253         return 0;
1254 err:
1255         return err;
1256 }
1257
1258 int fsl_mc_ldpaa_exit(bd_t *bd)
1259 {
1260         int err = 0;
1261
1262         if (bd && mc_lazy_dpl_addr && !fsl_mc_ldpaa_exit(NULL)) {
1263                 mc_apply_dpl(mc_lazy_dpl_addr);
1264                 mc_lazy_dpl_addr = 0;
1265         }
1266
1267         /* MC is not loaded intentionally, So return success. */
1268         if (bd && get_mc_boot_status() != 0)
1269                 return 0;
1270
1271         if (bd && !get_mc_boot_status() && get_dpl_apply_status() == -1) {
1272                 printf("ERROR: fsl-mc: DPL is not applied\n");
1273                 err = -ENODEV;
1274                 return err;
1275         }
1276
1277         if (bd && !get_mc_boot_status() && !get_dpl_apply_status())
1278                 return err;
1279
1280         err = dpbp_exit();
1281         if (err < 0) {
1282                 printf("dpbp_exit() failed: %d\n", err);
1283                 goto err;
1284         }
1285
1286         err = dpio_exit();
1287         if (err < 0) {
1288                 printf("dpio_exit() failed: %d\n", err);
1289                 goto err;
1290         }
1291
1292         err = dpni_exit();
1293         if (err < 0) {
1294                 printf("dpni_exit() failed: %d\n", err);
1295                 goto err;
1296         }
1297
1298         err = dprc_exit();
1299         if (err < 0) {
1300                 printf("dprc_exit() failed: %d\n", err);
1301                 goto err;
1302         }
1303
1304         return 0;
1305 err:
1306         return err;
1307 }
1308
1309 static int do_fsl_mc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1310 {
1311         int err = 0;
1312         if (argc < 3)
1313                 goto usage;
1314
1315         switch (argv[1][0]) {
1316         case 's': {
1317                         char sub_cmd;
1318                         u64 mc_fw_addr, mc_dpc_addr;
1319 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1320                         u64 aiop_fw_addr;
1321 #endif
1322
1323                         sub_cmd = argv[2][0];
1324                         switch (sub_cmd) {
1325                         case 'm':
1326                                 if (argc < 5)
1327                                         goto usage;
1328
1329                                 if (get_mc_boot_status() == 0) {
1330                                         printf("fsl-mc: MC is already booted");
1331                                         printf("\n");
1332                                         return err;
1333                                 }
1334                                 mc_fw_addr = simple_strtoull(argv[3], NULL, 16);
1335                                 mc_dpc_addr = simple_strtoull(argv[4], NULL,
1336                                                               16);
1337
1338                                 if (!mc_init(mc_fw_addr, mc_dpc_addr))
1339                                         err = mc_init_object();
1340                                 break;
1341
1342 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1343                         case 'a':
1344                                 if (argc < 4)
1345                                         goto usage;
1346                                 if (get_aiop_apply_status() == 0) {
1347                                         printf("fsl-mc: AIOP FW is already");
1348                                         printf(" applied\n");
1349                                         return err;
1350                                 }
1351
1352                                 aiop_fw_addr = simple_strtoull(argv[3], NULL,
1353                                                                16);
1354
1355                                 /* if SoC doesn't have AIOP, err = -ENODEV */
1356                                 err = load_mc_aiop_img(aiop_fw_addr);
1357                                 if (!err)
1358                                         printf("fsl-mc: AIOP FW applied\n");
1359                                 break;
1360 #endif
1361                         default:
1362                                 printf("Invalid option: %s\n", argv[2]);
1363                                 goto usage;
1364
1365                                 break;
1366                         }
1367                 }
1368                 break;
1369
1370         case 'l':
1371         case 'a': {
1372                         u64 mc_dpl_addr;
1373
1374                         if (argc < 4)
1375                                 goto usage;
1376
1377                         if (get_dpl_apply_status() == 0) {
1378                                 printf("fsl-mc: DPL already applied\n");
1379                                 return err;
1380                         }
1381
1382                         mc_dpl_addr = simple_strtoull(argv[3], NULL,
1383                                                               16);
1384
1385                         if (get_mc_boot_status() != 0) {
1386                                 printf("fsl-mc: Deploying data path layout ..");
1387                                 printf("ERROR (MC is not booted)\n");
1388                                 return -ENODEV;
1389                         }
1390
1391                         if (argv[1][0] == 'l') {
1392                                 /*
1393                                  * We will do the actual dpaa exit and dpl apply
1394                                  * later from announce_and_cleanup().
1395                                  */
1396                                 mc_lazy_dpl_addr = mc_dpl_addr;
1397                         } else {
1398                                 /* The user wants it applied now */
1399                                 if (!fsl_mc_ldpaa_exit(NULL))
1400                                         err = mc_apply_dpl(mc_dpl_addr);
1401                         }
1402                         break;
1403                 }
1404         default:
1405                 printf("Invalid option: %s\n", argv[1]);
1406                 goto usage;
1407                 break;
1408         }
1409         return err;
1410  usage:
1411         return CMD_RET_USAGE;
1412 }
1413
1414 U_BOOT_CMD(
1415         fsl_mc,  CONFIG_SYS_MAXARGS,  1,   do_fsl_mc,
1416         "DPAA2 command to manage Management Complex (MC)",
1417         "start mc [FW_addr] [DPC_addr] - Start Management Complex\n"
1418         "fsl_mc apply DPL [DPL_addr] - Apply DPL file\n"
1419         "fsl_mc lazyapply DPL [DPL_addr] - Apply DPL file on exit\n"
1420         "fsl_mc start aiop [FW_addr] - Start AIOP\n"
1421 );