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