xref: /rk3399_rockchip-uboot/drivers/net/fsl-mc/mc.c (revision 36cc0de0b919c0e185739142742e0a76a7c5c30a)
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 	return gd->arch.resv_ram;
718 }
719 
720 /**
721  * Return the actual size of the MC private DRAM block.
722  */
723 unsigned long mc_get_dram_block_size(void)
724 {
725 	unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
726 
727 	char *dram_block_size_env_var = getenv(MC_MEM_SIZE_ENV_VAR);
728 
729 	if (dram_block_size_env_var) {
730 		dram_block_size = simple_strtoul(dram_block_size_env_var, NULL,
731 						 10);
732 
733 		if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
734 			printf("fsl-mc: WARNING: Invalid value for \'"
735 			       MC_MEM_SIZE_ENV_VAR
736 			       "\' environment variable: %lu\n",
737 			       dram_block_size);
738 
739 			dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
740 		}
741 	}
742 
743 	return dram_block_size;
744 }
745 
746 int fsl_mc_ldpaa_init(bd_t *bis)
747 {
748 	int i;
749 
750 	for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++)
751 		if ((wriop_is_enabled_dpmac(i) == 1) &&
752 		    (wriop_get_phy_address(i) != -1))
753 			ldpaa_eth_init(i, wriop_get_enet_if(i));
754 	return 0;
755 }
756 
757 static int dprc_version_check(struct fsl_mc_io *mc_io, uint16_t handle)
758 {
759 	struct dprc_attributes attr;
760 	int error;
761 
762 	memset(&attr, 0, sizeof(struct dprc_attributes));
763 	error = dprc_get_attributes(mc_io, MC_CMD_NO_FLAGS, handle, &attr);
764 	if (error == 0) {
765 		if ((attr.version.major != DPRC_VER_MAJOR) ||
766 		    (attr.version.minor != DPRC_VER_MINOR)) {
767 			printf("DPRC version mismatch found %u.%u,",
768 			       attr.version.major,
769 			       attr.version.minor);
770 			printf("supported version is %u.%u\n",
771 			       DPRC_VER_MAJOR, DPRC_VER_MINOR);
772 		}
773 	}
774 	return error;
775 }
776 
777 static int dpio_init(void)
778 {
779 	struct qbman_swp_desc p_des;
780 	struct dpio_attr attr;
781 	struct dpio_cfg dpio_cfg;
782 	int err = 0;
783 
784 	dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj));
785 	if (!dflt_dpio) {
786 		printf("No memory: malloc() failed\n");
787 		err = -ENOMEM;
788 		goto err_malloc;
789 	}
790 
791 	dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL;
792 	dpio_cfg.num_priorities = 8;
793 
794 	err = dpio_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpio_cfg,
795 			  &dflt_dpio->dpio_handle);
796 	if (err < 0) {
797 		printf("dpio_create() failed: %d\n", err);
798 		err = -ENODEV;
799 		goto err_create;
800 	}
801 
802 	memset(&attr, 0, sizeof(struct dpio_attr));
803 	err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
804 				  dflt_dpio->dpio_handle, &attr);
805 	if (err < 0) {
806 		printf("dpio_get_attributes() failed: %d\n", err);
807 		goto err_get_attr;
808 	}
809 
810 	if ((attr.version.major != DPIO_VER_MAJOR) ||
811 	    (attr.version.minor != DPIO_VER_MINOR)) {
812 		printf("DPIO version mismatch found %u.%u,",
813 		       attr.version.major, attr.version.minor);
814 		printf("supported version is %u.%u\n",
815 		       DPIO_VER_MAJOR, DPIO_VER_MINOR);
816 	}
817 
818 	dflt_dpio->dpio_id = attr.id;
819 #ifdef DEBUG
820 	printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id);
821 #endif
822 	err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
823 	if (err < 0) {
824 		printf("dpio_enable() failed %d\n", err);
825 		goto err_get_enable;
826 	}
827 	debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n",
828 	      attr.qbman_portal_ce_offset,
829 	      attr.qbman_portal_ci_offset,
830 	      attr.qbman_portal_id,
831 	      attr.num_priorities);
832 
833 	p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
834 					+ attr.qbman_portal_ce_offset);
835 	p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
836 					+ attr.qbman_portal_ci_offset);
837 
838 	dflt_dpio->sw_portal = qbman_swp_init(&p_des);
839 	if (dflt_dpio->sw_portal == NULL) {
840 		printf("qbman_swp_init() failed\n");
841 		goto err_get_swp_init;
842 	}
843 	return 0;
844 
845 err_get_swp_init:
846 	dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
847 err_get_enable:
848 err_get_attr:
849 	dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
850 	dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
851 err_create:
852 	free(dflt_dpio);
853 err_malloc:
854 	return err;
855 }
856 
857 static int dpio_exit(void)
858 {
859 	int err;
860 
861 	err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
862 	if (err < 0) {
863 		printf("dpio_disable() failed: %d\n", err);
864 		goto err;
865 	}
866 
867 	err = dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
868 	if (err < 0) {
869 		printf("dpio_destroy() failed: %d\n", err);
870 		goto err;
871 	}
872 
873 #ifdef DEBUG
874 	printf("Exit: DPIO id=0x%d\n", dflt_dpio->dpio_id);
875 #endif
876 
877 	if (dflt_dpio)
878 		free(dflt_dpio);
879 
880 	return 0;
881 err:
882 	return err;
883 }
884 
885 static int dprc_init(void)
886 {
887 	int err, child_portal_id, container_id;
888 	struct dprc_cfg cfg;
889 	uint64_t mc_portal_offset;
890 
891 	/* Open root container */
892 	err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id);
893 	if (err < 0) {
894 		printf("dprc_get_container_id(): Root failed: %d\n", err);
895 		goto err_root_container_id;
896 	}
897 
898 #ifdef DEBUG
899 	printf("Root container id = %d\n", container_id);
900 #endif
901 	err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id,
902 			&root_dprc_handle);
903 	if (err < 0) {
904 		printf("dprc_open(): Root Container failed: %d\n", err);
905 		goto err_root_open;
906 	}
907 
908 	if (!root_dprc_handle) {
909 		printf("dprc_open(): Root Container Handle is not valid\n");
910 		goto err_root_open;
911 	}
912 
913 	err = dprc_version_check(root_mc_io, root_dprc_handle);
914 	if (err < 0) {
915 		printf("dprc_version_check() failed: %d\n", err);
916 		goto err_root_open;
917 	}
918 
919 	memset(&cfg, 0, sizeof(struct dprc_cfg));
920 	cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED |
921 		      DPRC_CFG_OPT_OBJ_CREATE_ALLOWED |
922 		      DPRC_CFG_OPT_ALLOC_ALLOWED;
923 	cfg.icid = DPRC_GET_ICID_FROM_POOL;
924 	cfg.portal_id = DPRC_GET_PORTAL_ID_FROM_POOL;
925 	err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS,
926 			root_dprc_handle,
927 			&cfg,
928 			&child_dprc_id,
929 			&mc_portal_offset);
930 	if (err < 0) {
931 		printf("dprc_create_container() failed: %d\n", err);
932 		goto err_create;
933 	}
934 
935 	dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
936 	if (!dflt_mc_io) {
937 		err  = -ENOMEM;
938 		printf(" No memory: malloc() failed\n");
939 		goto err_malloc;
940 	}
941 
942 	child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset);
943 	dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id);
944 #ifdef DEBUG
945 	printf("MC portal of child DPRC container: %d, physical addr %p)\n",
946 	       child_dprc_id, dflt_mc_io->mmio_regs);
947 #endif
948 
949 	err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id,
950 			&dflt_dprc_handle);
951 	if (err < 0) {
952 		printf("dprc_open(): Child container failed: %d\n", err);
953 		goto err_child_open;
954 	}
955 
956 	if (!dflt_dprc_handle) {
957 		printf("dprc_open(): Child container Handle is not valid\n");
958 		goto err_child_open;
959 	}
960 
961 	return 0;
962 err_child_open:
963 	free(dflt_mc_io);
964 err_malloc:
965 	dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
966 			       root_dprc_handle, child_dprc_id);
967 err_create:
968 	dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
969 err_root_open:
970 err_root_container_id:
971 	return err;
972 }
973 
974 static int dprc_exit(void)
975 {
976 	int err;
977 
978 	err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle);
979 	if (err < 0) {
980 		printf("dprc_close(): Child failed: %d\n", err);
981 		goto err;
982 	}
983 
984 	err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
985 				     root_dprc_handle, child_dprc_id);
986 	if (err < 0) {
987 		printf("dprc_destroy_container() failed: %d\n", err);
988 		goto err;
989 	}
990 
991 	err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
992 	if (err < 0) {
993 		printf("dprc_close(): Root failed: %d\n", err);
994 		goto err;
995 	}
996 
997 	if (dflt_mc_io)
998 		free(dflt_mc_io);
999 
1000 	if (root_mc_io)
1001 		free(root_mc_io);
1002 
1003 	return 0;
1004 
1005 err:
1006 	return err;
1007 }
1008 
1009 static int dpbp_init(void)
1010 {
1011 	int err;
1012 	struct dpbp_attr dpbp_attr;
1013 	struct dpbp_cfg dpbp_cfg;
1014 
1015 	dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj));
1016 	if (!dflt_dpbp) {
1017 		printf("No memory: malloc() failed\n");
1018 		err = -ENOMEM;
1019 		goto err_malloc;
1020 	}
1021 
1022 	dpbp_cfg.options = 512;
1023 
1024 	err = dpbp_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpbp_cfg,
1025 			  &dflt_dpbp->dpbp_handle);
1026 
1027 	if (err < 0) {
1028 		err = -ENODEV;
1029 		printf("dpbp_create() failed: %d\n", err);
1030 		goto err_create;
1031 	}
1032 
1033 	memset(&dpbp_attr, 0, sizeof(struct dpbp_attr));
1034 	err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1035 				  dflt_dpbp->dpbp_handle,
1036 				  &dpbp_attr);
1037 	if (err < 0) {
1038 		printf("dpbp_get_attributes() failed: %d\n", err);
1039 		goto err_get_attr;
1040 	}
1041 
1042 	if ((dpbp_attr.version.major != DPBP_VER_MAJOR) ||
1043 	    (dpbp_attr.version.minor != DPBP_VER_MINOR)) {
1044 		printf("DPBP version mismatch found %u.%u,",
1045 		       dpbp_attr.version.major, dpbp_attr.version.minor);
1046 		printf("supported version is %u.%u\n",
1047 		       DPBP_VER_MAJOR, DPBP_VER_MINOR);
1048 	}
1049 
1050 	dflt_dpbp->dpbp_attr.id = dpbp_attr.id;
1051 #ifdef DEBUG
1052 	printf("Init: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
1053 #endif
1054 
1055 	err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1056 	if (err < 0) {
1057 		printf("dpbp_close() failed: %d\n", err);
1058 		goto err_close;
1059 	}
1060 
1061 	return 0;
1062 
1063 err_close:
1064 	free(dflt_dpbp);
1065 err_get_attr:
1066 	dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1067 	dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1068 err_create:
1069 err_malloc:
1070 	return err;
1071 }
1072 
1073 static int dpbp_exit(void)
1074 {
1075 	int err;
1076 
1077 	err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
1078 			&dflt_dpbp->dpbp_handle);
1079 	if (err < 0) {
1080 		printf("dpbp_open() failed: %d\n", err);
1081 		goto err;
1082 	}
1083 
1084 	err = dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
1085 			   dflt_dpbp->dpbp_handle);
1086 	if (err < 0) {
1087 		printf("dpbp_destroy() failed: %d\n", err);
1088 		goto err;
1089 	}
1090 
1091 #ifdef DEBUG
1092 	printf("Exit: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
1093 #endif
1094 
1095 	if (dflt_dpbp)
1096 		free(dflt_dpbp);
1097 	return 0;
1098 
1099 err:
1100 	return err;
1101 }
1102 
1103 static int dpni_init(void)
1104 {
1105 	int err;
1106 	struct dpni_attr dpni_attr;
1107 	uint8_t	ext_cfg_buf[256] = {0};
1108 	struct dpni_extended_cfg dpni_extended_cfg;
1109 	struct dpni_cfg dpni_cfg;
1110 
1111 	dflt_dpni = (struct fsl_dpni_obj *)malloc(sizeof(struct fsl_dpni_obj));
1112 	if (!dflt_dpni) {
1113 		printf("No memory: malloc() failed\n");
1114 		err = -ENOMEM;
1115 		goto err_malloc;
1116 	}
1117 
1118 	memset(&dpni_extended_cfg, 0, sizeof(dpni_extended_cfg));
1119 	err = dpni_prepare_extended_cfg(&dpni_extended_cfg, &ext_cfg_buf[0]);
1120 	if (err < 0) {
1121 		err = -ENODEV;
1122 		printf("dpni_prepare_extended_cfg() failed: %d\n", err);
1123 		goto err_prepare_extended_cfg;
1124 	}
1125 
1126 	memset(&dpni_cfg, 0, sizeof(dpni_cfg));
1127 	dpni_cfg.adv.options = DPNI_OPT_UNICAST_FILTER |
1128 			       DPNI_OPT_MULTICAST_FILTER;
1129 
1130 	dpni_cfg.adv.ext_cfg_iova = (uint64_t)&ext_cfg_buf[0];
1131 	err = dpni_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpni_cfg,
1132 			  &dflt_dpni->dpni_handle);
1133 
1134 	if (err < 0) {
1135 		err = -ENODEV;
1136 		printf("dpni_create() failed: %d\n", err);
1137 		goto err_create;
1138 	}
1139 
1140 	memset(&dpni_attr, 0, sizeof(struct dpni_attr));
1141 	err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1142 				  dflt_dpni->dpni_handle,
1143 				  &dpni_attr);
1144 	if (err < 0) {
1145 		printf("dpni_get_attributes() failed: %d\n", err);
1146 		goto err_get_attr;
1147 	}
1148 
1149 	if ((dpni_attr.version.major != DPNI_VER_MAJOR) ||
1150 	    (dpni_attr.version.minor != DPNI_VER_MINOR)) {
1151 		printf("DPNI version mismatch found %u.%u,",
1152 		       dpni_attr.version.major, dpni_attr.version.minor);
1153 		printf("supported version is %u.%u\n",
1154 		       DPNI_VER_MAJOR, DPNI_VER_MINOR);
1155 	}
1156 
1157 	dflt_dpni->dpni_id = dpni_attr.id;
1158 #ifdef DEBUG
1159 	printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1160 #endif
1161 
1162 	err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1163 	if (err < 0) {
1164 		printf("dpni_close() failed: %d\n", err);
1165 		goto err_close;
1166 	}
1167 
1168 	return 0;
1169 
1170 err_close:
1171 err_get_attr:
1172 	dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1173 	dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1174 err_create:
1175 err_prepare_extended_cfg:
1176 	free(dflt_dpni);
1177 err_malloc:
1178 	return err;
1179 }
1180 
1181 static int dpni_exit(void)
1182 {
1183 	int err;
1184 
1185 	err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
1186 			&dflt_dpni->dpni_handle);
1187 	if (err < 0) {
1188 		printf("dpni_open() failed: %d\n", err);
1189 		goto err;
1190 	}
1191 
1192 	err = dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
1193 			   dflt_dpni->dpni_handle);
1194 	if (err < 0) {
1195 		printf("dpni_destroy() failed: %d\n", err);
1196 		goto err;
1197 	}
1198 
1199 #ifdef DEBUG
1200 	printf("Exit: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1201 #endif
1202 
1203 	if (dflt_dpni)
1204 		free(dflt_dpni);
1205 	return 0;
1206 
1207 err:
1208 	return err;
1209 }
1210 
1211 static int mc_init_object(void)
1212 {
1213 	int err = 0;
1214 
1215 	err = dprc_init();
1216 	if (err < 0) {
1217 		printf("dprc_init() failed: %d\n", err);
1218 		goto err;
1219 	}
1220 
1221 	err = dpbp_init();
1222 	if (err < 0) {
1223 		printf("dpbp_init() failed: %d\n", err);
1224 		goto err;
1225 	}
1226 
1227 	err = dpio_init();
1228 	if (err < 0) {
1229 		printf("dpio_init() failed: %d\n", err);
1230 		goto err;
1231 	}
1232 
1233 	err = dpni_init();
1234 	if (err < 0) {
1235 		printf("dpni_init() failed: %d\n", err);
1236 		goto err;
1237 	}
1238 
1239 	return 0;
1240 err:
1241 	return err;
1242 }
1243 
1244 int fsl_mc_ldpaa_exit(bd_t *bd)
1245 {
1246 	int err = 0;
1247 
1248 	if (bd && mc_lazy_dpl_addr && !fsl_mc_ldpaa_exit(NULL)) {
1249 		mc_apply_dpl(mc_lazy_dpl_addr);
1250 		mc_lazy_dpl_addr = 0;
1251 	}
1252 
1253 	/* MC is not loaded intentionally, So return success. */
1254 	if (bd && get_mc_boot_status() != 0)
1255 		return 0;
1256 
1257 	if (bd && !get_mc_boot_status() && get_dpl_apply_status() == -1) {
1258 		printf("ERROR: fsl-mc: DPL is not applied\n");
1259 		err = -ENODEV;
1260 		return err;
1261 	}
1262 
1263 	if (bd && !get_mc_boot_status() && !get_dpl_apply_status())
1264 		return err;
1265 
1266 	err = dpbp_exit();
1267 	if (err < 0) {
1268 		printf("dpbp_exit() failed: %d\n", err);
1269 		goto err;
1270 	}
1271 
1272 	err = dpio_exit();
1273 	if (err < 0) {
1274 		printf("dpio_exit() failed: %d\n", err);
1275 		goto err;
1276 	}
1277 
1278 	err = dpni_exit();
1279 	if (err < 0) {
1280 		printf("dpni_exit() failed: %d\n", err);
1281 		goto err;
1282 	}
1283 
1284 	err = dprc_exit();
1285 	if (err < 0) {
1286 		printf("dprc_exit() failed: %d\n", err);
1287 		goto err;
1288 	}
1289 
1290 	return 0;
1291 err:
1292 	return err;
1293 }
1294 
1295 static int do_fsl_mc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1296 {
1297 	int err = 0;
1298 	if (argc < 3)
1299 		goto usage;
1300 
1301 	switch (argv[1][0]) {
1302 	case 's': {
1303 			char sub_cmd;
1304 			u64 mc_fw_addr, mc_dpc_addr;
1305 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1306 			u64 aiop_fw_addr;
1307 #endif
1308 
1309 			sub_cmd = argv[2][0];
1310 			switch (sub_cmd) {
1311 			case 'm':
1312 				if (argc < 5)
1313 					goto usage;
1314 
1315 				if (get_mc_boot_status() == 0) {
1316 					printf("fsl-mc: MC is already booted");
1317 					printf("\n");
1318 					return err;
1319 				}
1320 				mc_fw_addr = simple_strtoull(argv[3], NULL, 16);
1321 				mc_dpc_addr = simple_strtoull(argv[4], NULL,
1322 							      16);
1323 
1324 				if (!mc_init(mc_fw_addr, mc_dpc_addr))
1325 					err = mc_init_object();
1326 				break;
1327 
1328 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1329 			case 'a':
1330 				if (argc < 4)
1331 					goto usage;
1332 				if (get_aiop_apply_status() == 0) {
1333 					printf("fsl-mc: AIOP FW is already");
1334 					printf(" applied\n");
1335 					return err;
1336 				}
1337 
1338 				aiop_fw_addr = simple_strtoull(argv[3], NULL,
1339 							       16);
1340 
1341 				/* if SoC doesn't have AIOP, err = -ENODEV */
1342 				err = load_mc_aiop_img(aiop_fw_addr);
1343 				if (!err)
1344 					printf("fsl-mc: AIOP FW applied\n");
1345 				break;
1346 #endif
1347 			default:
1348 				printf("Invalid option: %s\n", argv[2]);
1349 				goto usage;
1350 
1351 				break;
1352 			}
1353 		}
1354 		break;
1355 
1356 	case 'l':
1357 	case 'a': {
1358 			u64 mc_dpl_addr;
1359 
1360 			if (argc < 4)
1361 				goto usage;
1362 
1363 			if (get_dpl_apply_status() == 0) {
1364 				printf("fsl-mc: DPL already applied\n");
1365 				return err;
1366 			}
1367 
1368 			mc_dpl_addr = simple_strtoull(argv[3], NULL,
1369 							      16);
1370 
1371 			if (get_mc_boot_status() != 0) {
1372 				printf("fsl-mc: Deploying data path layout ..");
1373 				printf("ERROR (MC is not booted)\n");
1374 				return -ENODEV;
1375 			}
1376 
1377 			if (argv[1][0] == 'l') {
1378 				/*
1379 				 * We will do the actual dpaa exit and dpl apply
1380 				 * later from announce_and_cleanup().
1381 				 */
1382 				mc_lazy_dpl_addr = mc_dpl_addr;
1383 			} else {
1384 				/* The user wants it applied now */
1385 				if (!fsl_mc_ldpaa_exit(NULL))
1386 					err = mc_apply_dpl(mc_dpl_addr);
1387 			}
1388 			break;
1389 		}
1390 	default:
1391 		printf("Invalid option: %s\n", argv[1]);
1392 		goto usage;
1393 		break;
1394 	}
1395 	return err;
1396  usage:
1397 	return CMD_RET_USAGE;
1398 }
1399 
1400 U_BOOT_CMD(
1401 	fsl_mc,  CONFIG_SYS_MAXARGS,  1,   do_fsl_mc,
1402 	"DPAA2 command to manage Management Complex (MC)",
1403 	"start mc [FW_addr] [DPC_addr] - Start Management Complex\n"
1404 	"fsl_mc apply DPL [DPL_addr] - Apply DPL file\n"
1405 	"fsl_mc lazyapply DPL [DPL_addr] - Apply DPL file on exit\n"
1406 	"fsl_mc start aiop [FW_addr] - Start AIOP\n"
1407 );
1408