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