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