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