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