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