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, ®_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, ®_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