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