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