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 int is_lazy_dpl_addr_valid(void) 838 { 839 return !!mc_lazy_dpl_addr; 840 } 841 842 /* 843 * Return the MC address of private DRAM block. 844 * As per MC design document, MC initial base address 845 * should be least significant 512MB address of MC private 846 * memory, i.e. address should point to end address masked 847 * with 512MB offset in private DRAM block. 848 */ 849 u64 mc_get_dram_addr(void) 850 { 851 size_t mc_ram_size = mc_get_dram_block_size(); 852 853 if (!mc_memset_resv_ram || (get_mc_boot_status() < 0)) { 854 mc_memset_resv_ram = 1; 855 memset((void *)gd->arch.resv_ram, 0, mc_ram_size); 856 } 857 858 return (gd->arch.resv_ram + mc_ram_size - 1) & 859 MC_RAM_BASE_ADDR_ALIGNMENT_MASK; 860 } 861 862 /** 863 * Return the actual size of the MC private DRAM block. 864 */ 865 unsigned long mc_get_dram_block_size(void) 866 { 867 unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE; 868 869 char *dram_block_size_env_var = env_get(MC_MEM_SIZE_ENV_VAR); 870 871 if (dram_block_size_env_var) { 872 dram_block_size = simple_strtoul(dram_block_size_env_var, NULL, 873 16); 874 875 if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) { 876 printf("fsl-mc: WARNING: Invalid value for \'" 877 MC_MEM_SIZE_ENV_VAR 878 "\' environment variable: %lu\n", 879 dram_block_size); 880 881 dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE; 882 } 883 } 884 885 return dram_block_size; 886 } 887 888 int fsl_mc_ldpaa_init(bd_t *bis) 889 { 890 int i; 891 892 for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) 893 if (wriop_is_enabled_dpmac(i) == 1) 894 ldpaa_eth_init(i, wriop_get_enet_if(i)); 895 return 0; 896 } 897 898 static int dprc_version_check(struct fsl_mc_io *mc_io, uint16_t handle) 899 { 900 int error; 901 uint16_t major_ver, minor_ver; 902 903 error = dprc_get_api_version(mc_io, 0, 904 &major_ver, 905 &minor_ver); 906 if (error < 0) { 907 printf("dprc_get_api_version() failed: %d\n", error); 908 return error; 909 } 910 911 if (major_ver < DPRC_VER_MAJOR || (major_ver == DPRC_VER_MAJOR && 912 minor_ver < DPRC_VER_MINOR)) { 913 printf("DPRC version mismatch found %u.%u,", 914 major_ver, minor_ver); 915 printf("supported version is %u.%u\n", 916 DPRC_VER_MAJOR, DPRC_VER_MINOR); 917 } 918 919 return error; 920 } 921 922 static int dpio_init(void) 923 { 924 struct qbman_swp_desc p_des; 925 struct dpio_attr attr; 926 struct dpio_cfg dpio_cfg; 927 int err = 0; 928 uint16_t major_ver, minor_ver; 929 930 dflt_dpio = (struct fsl_dpio_obj *)calloc( 931 sizeof(struct fsl_dpio_obj), 1); 932 if (!dflt_dpio) { 933 printf("No memory: calloc() failed\n"); 934 err = -ENOMEM; 935 goto err_calloc; 936 } 937 dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL; 938 dpio_cfg.num_priorities = 8; 939 940 err = dpio_create(dflt_mc_io, 941 dflt_dprc_handle, 942 MC_CMD_NO_FLAGS, 943 &dpio_cfg, 944 &dflt_dpio->dpio_id); 945 if (err < 0) { 946 printf("dpio_create() failed: %d\n", err); 947 err = -ENODEV; 948 goto err_create; 949 } 950 951 err = dpio_get_api_version(dflt_mc_io, 0, 952 &major_ver, 953 &minor_ver); 954 if (err < 0) { 955 printf("dpio_get_api_version() failed: %d\n", err); 956 goto err_get_api_ver; 957 } 958 959 if (major_ver < DPIO_VER_MAJOR || (major_ver == DPIO_VER_MAJOR && 960 minor_ver < DPIO_VER_MINOR)) { 961 printf("DPRC version mismatch found %u.%u,", 962 major_ver, 963 minor_ver); 964 } 965 966 err = dpio_open(dflt_mc_io, 967 MC_CMD_NO_FLAGS, 968 dflt_dpio->dpio_id, 969 &dflt_dpio->dpio_handle); 970 if (err) { 971 printf("dpio_open() failed\n"); 972 goto err_open; 973 } 974 975 memset(&attr, 0, sizeof(struct dpio_attr)); 976 err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS, 977 dflt_dpio->dpio_handle, &attr); 978 if (err < 0) { 979 printf("dpio_get_attributes() failed: %d\n", err); 980 goto err_get_attr; 981 } 982 983 if (dflt_dpio->dpio_id != attr.id) { 984 printf("dnpi object id and attribute id are not same\n"); 985 goto err_attr_not_same; 986 } 987 988 #ifdef DEBUG 989 printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id); 990 #endif 991 err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle); 992 if (err < 0) { 993 printf("dpio_enable() failed %d\n", err); 994 goto err_get_enable; 995 } 996 debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n", 997 attr.qbman_portal_ce_offset, 998 attr.qbman_portal_ci_offset, 999 attr.qbman_portal_id, 1000 attr.num_priorities); 1001 1002 p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR 1003 + attr.qbman_portal_ce_offset); 1004 p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR 1005 + attr.qbman_portal_ci_offset); 1006 1007 dflt_dpio->sw_portal = qbman_swp_init(&p_des); 1008 if (dflt_dpio->sw_portal == NULL) { 1009 printf("qbman_swp_init() failed\n"); 1010 goto err_get_swp_init; 1011 } 1012 return 0; 1013 1014 err_get_swp_init: 1015 dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle); 1016 err_get_enable: 1017 err_get_attr: 1018 err_attr_not_same: 1019 dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle); 1020 err_open: 1021 err_get_api_ver: 1022 dpio_destroy(dflt_mc_io, 1023 dflt_dprc_handle, 1024 MC_CMD_NO_FLAGS, 1025 dflt_dpio->dpio_id); 1026 err_create: 1027 free(dflt_dpio); 1028 err_calloc: 1029 return err; 1030 } 1031 1032 static int dpio_exit(void) 1033 { 1034 int err; 1035 1036 err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle); 1037 if (err < 0) { 1038 printf("dpio_disable() failed: %d\n", err); 1039 goto err; 1040 } 1041 1042 dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle); 1043 if (err < 0) { 1044 printf("dpio_close() failed: %d\n", err); 1045 goto err; 1046 } 1047 1048 err = dpio_destroy(dflt_mc_io, 1049 dflt_dprc_handle, 1050 MC_CMD_NO_FLAGS, 1051 dflt_dpio->dpio_id); 1052 if (err < 0) { 1053 printf("dpio_destroy() failed: %d\n", err); 1054 goto err; 1055 } 1056 1057 #ifdef DEBUG 1058 printf("Exit: DPIO id=0x%d\n", dflt_dpio->dpio_id); 1059 #endif 1060 1061 if (dflt_dpio) 1062 free(dflt_dpio); 1063 1064 return 0; 1065 err: 1066 return err; 1067 } 1068 1069 static int dprc_init(void) 1070 { 1071 int err, child_portal_id, container_id; 1072 struct dprc_cfg cfg; 1073 uint64_t mc_portal_offset; 1074 1075 /* Open root container */ 1076 err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id); 1077 if (err < 0) { 1078 printf("dprc_get_container_id(): Root failed: %d\n", err); 1079 goto err_root_container_id; 1080 } 1081 1082 #ifdef DEBUG 1083 printf("Root container id = %d\n", container_id); 1084 #endif 1085 err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id, 1086 &root_dprc_handle); 1087 if (err < 0) { 1088 printf("dprc_open(): Root Container failed: %d\n", err); 1089 goto err_root_open; 1090 } 1091 1092 if (!root_dprc_handle) { 1093 printf("dprc_open(): Root Container Handle is not valid\n"); 1094 goto err_root_open; 1095 } 1096 1097 err = dprc_version_check(root_mc_io, root_dprc_handle); 1098 if (err < 0) { 1099 printf("dprc_version_check() failed: %d\n", err); 1100 goto err_root_open; 1101 } 1102 1103 memset(&cfg, 0, sizeof(struct dprc_cfg)); 1104 cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED | 1105 DPRC_CFG_OPT_OBJ_CREATE_ALLOWED | 1106 DPRC_CFG_OPT_ALLOC_ALLOWED; 1107 cfg.icid = DPRC_GET_ICID_FROM_POOL; 1108 cfg.portal_id = DPRC_GET_PORTAL_ID_FROM_POOL; 1109 err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS, 1110 root_dprc_handle, 1111 &cfg, 1112 &child_dprc_id, 1113 &mc_portal_offset); 1114 if (err < 0) { 1115 printf("dprc_create_container() failed: %d\n", err); 1116 goto err_create; 1117 } 1118 1119 dflt_mc_io = (struct fsl_mc_io *)calloc(sizeof(struct fsl_mc_io), 1); 1120 if (!dflt_mc_io) { 1121 err = -ENOMEM; 1122 printf(" No memory: calloc() failed\n"); 1123 goto err_calloc; 1124 } 1125 1126 child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset); 1127 dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id); 1128 1129 #ifdef DEBUG 1130 printf("MC portal of child DPRC container: %d, physical addr %p)\n", 1131 child_dprc_id, dflt_mc_io->mmio_regs); 1132 #endif 1133 1134 err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id, 1135 &dflt_dprc_handle); 1136 if (err < 0) { 1137 printf("dprc_open(): Child container failed: %d\n", err); 1138 goto err_child_open; 1139 } 1140 1141 if (!dflt_dprc_handle) { 1142 printf("dprc_open(): Child container Handle is not valid\n"); 1143 goto err_child_open; 1144 } 1145 1146 return 0; 1147 err_child_open: 1148 free(dflt_mc_io); 1149 err_calloc: 1150 dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS, 1151 root_dprc_handle, child_dprc_id); 1152 err_create: 1153 dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle); 1154 err_root_open: 1155 err_root_container_id: 1156 return err; 1157 } 1158 1159 static int dprc_exit(void) 1160 { 1161 int err; 1162 1163 err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle); 1164 if (err < 0) { 1165 printf("dprc_close(): Child failed: %d\n", err); 1166 goto err; 1167 } 1168 1169 err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS, 1170 root_dprc_handle, child_dprc_id); 1171 if (err < 0) { 1172 printf("dprc_destroy_container() failed: %d\n", err); 1173 goto err; 1174 } 1175 1176 err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle); 1177 if (err < 0) { 1178 printf("dprc_close(): Root failed: %d\n", err); 1179 goto err; 1180 } 1181 1182 if (dflt_mc_io) 1183 free(dflt_mc_io); 1184 1185 if (root_mc_io) 1186 free(root_mc_io); 1187 1188 return 0; 1189 1190 err: 1191 return err; 1192 } 1193 1194 static int dpbp_init(void) 1195 { 1196 int err; 1197 struct dpbp_attr dpbp_attr; 1198 struct dpbp_cfg dpbp_cfg; 1199 uint16_t major_ver, minor_ver; 1200 1201 dflt_dpbp = (struct fsl_dpbp_obj *)calloc( 1202 sizeof(struct fsl_dpbp_obj), 1); 1203 if (!dflt_dpbp) { 1204 printf("No memory: calloc() failed\n"); 1205 err = -ENOMEM; 1206 goto err_calloc; 1207 } 1208 1209 dpbp_cfg.options = 512; 1210 1211 err = dpbp_create(dflt_mc_io, 1212 dflt_dprc_handle, 1213 MC_CMD_NO_FLAGS, 1214 &dpbp_cfg, 1215 &dflt_dpbp->dpbp_id); 1216 1217 if (err < 0) { 1218 err = -ENODEV; 1219 printf("dpbp_create() failed: %d\n", err); 1220 goto err_create; 1221 } 1222 1223 err = dpbp_get_api_version(dflt_mc_io, 0, 1224 &major_ver, 1225 &minor_ver); 1226 if (err < 0) { 1227 printf("dpbp_get_api_version() failed: %d\n", err); 1228 goto err_get_api_ver; 1229 } 1230 1231 if (major_ver < DPBP_VER_MAJOR || (major_ver == DPBP_VER_MAJOR && 1232 minor_ver < DPBP_VER_MINOR)) { 1233 printf("DPBP version mismatch found %u.%u,", 1234 major_ver, minor_ver); 1235 printf("supported version is %u.%u\n", 1236 DPBP_VER_MAJOR, DPBP_VER_MINOR); 1237 } 1238 1239 err = dpbp_open(dflt_mc_io, 1240 MC_CMD_NO_FLAGS, 1241 dflt_dpbp->dpbp_id, 1242 &dflt_dpbp->dpbp_handle); 1243 if (err) { 1244 printf("dpbp_open() failed\n"); 1245 goto err_open; 1246 } 1247 1248 memset(&dpbp_attr, 0, sizeof(struct dpbp_attr)); 1249 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS, 1250 dflt_dpbp->dpbp_handle, 1251 &dpbp_attr); 1252 if (err < 0) { 1253 printf("dpbp_get_attributes() failed: %d\n", err); 1254 goto err_get_attr; 1255 } 1256 1257 if (dflt_dpbp->dpbp_id != dpbp_attr.id) { 1258 printf("dpbp object id and attribute id are not same\n"); 1259 goto err_attr_not_same; 1260 } 1261 1262 #ifdef DEBUG 1263 printf("Init: DPBP id=0x%x\n", dflt_dpbp->dpbp_attr.id); 1264 #endif 1265 1266 err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 1267 if (err < 0) { 1268 printf("dpbp_close() failed: %d\n", err); 1269 goto err_close; 1270 } 1271 1272 return 0; 1273 1274 err_get_attr: 1275 err_attr_not_same: 1276 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 1277 dpbp_destroy(dflt_mc_io, 1278 dflt_dprc_handle, 1279 MC_CMD_NO_FLAGS, 1280 dflt_dpbp->dpbp_id); 1281 err_get_api_ver: 1282 err_close: 1283 err_open: 1284 err_create: 1285 free(dflt_dpbp); 1286 err_calloc: 1287 return err; 1288 } 1289 1290 static int dpbp_exit(void) 1291 { 1292 int err; 1293 1294 err = dpbp_destroy(dflt_mc_io, dflt_dprc_handle, MC_CMD_NO_FLAGS, 1295 dflt_dpbp->dpbp_id); 1296 if (err < 0) { 1297 printf("dpbp_destroy() failed: %d\n", err); 1298 goto err; 1299 } 1300 1301 #ifdef DEBUG 1302 printf("Exit: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id); 1303 #endif 1304 1305 if (dflt_dpbp) 1306 free(dflt_dpbp); 1307 return 0; 1308 1309 err: 1310 return err; 1311 } 1312 1313 static int dpni_init(void) 1314 { 1315 int err; 1316 uint8_t cfg_buf[256] = {0}; 1317 struct dpni_cfg dpni_cfg; 1318 uint16_t major_ver, minor_ver; 1319 1320 dflt_dpni = (struct fsl_dpni_obj *)calloc( 1321 sizeof(struct fsl_dpni_obj), 1); 1322 if (!dflt_dpni) { 1323 printf("No memory: calloc() failed\n"); 1324 err = -ENOMEM; 1325 goto err_calloc; 1326 } 1327 1328 memset(&dpni_cfg, 0, sizeof(dpni_cfg)); 1329 err = dpni_prepare_cfg(&dpni_cfg, &cfg_buf[0]); 1330 if (err < 0) { 1331 err = -ENODEV; 1332 printf("dpni_prepare_cfg() failed: %d\n", err); 1333 goto err_prepare_cfg; 1334 } 1335 1336 err = dpni_create(dflt_mc_io, 1337 dflt_dprc_handle, 1338 MC_CMD_NO_FLAGS, 1339 &dpni_cfg, 1340 &dflt_dpni->dpni_id); 1341 if (err < 0) { 1342 err = -ENODEV; 1343 printf("dpni create() failed: %d\n", err); 1344 goto err_create; 1345 } 1346 1347 err = dpni_get_api_version(dflt_mc_io, 0, 1348 &major_ver, 1349 &minor_ver); 1350 if (err < 0) { 1351 printf("dpni_get_api_version() failed: %d\n", err); 1352 goto err_get_version; 1353 } 1354 1355 if (major_ver < DPNI_VER_MAJOR || (major_ver == DPNI_VER_MAJOR && 1356 minor_ver < DPNI_VER_MINOR)) { 1357 printf("DPNI version mismatch found %u.%u,", 1358 major_ver, minor_ver); 1359 printf("supported version is %u.%u\n", 1360 DPNI_VER_MAJOR, DPNI_VER_MINOR); 1361 } 1362 1363 err = dpni_open(dflt_mc_io, 1364 MC_CMD_NO_FLAGS, 1365 dflt_dpni->dpni_id, 1366 &dflt_dpni->dpni_handle); 1367 if (err) { 1368 printf("dpni_open() failed\n"); 1369 goto err_open; 1370 } 1371 1372 #ifdef DEBUG 1373 printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id); 1374 #endif 1375 err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 1376 if (err < 0) { 1377 printf("dpni_close() failed: %d\n", err); 1378 goto err_close; 1379 } 1380 1381 return 0; 1382 1383 err_close: 1384 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 1385 err_open: 1386 err_get_version: 1387 dpni_destroy(dflt_mc_io, 1388 dflt_dprc_handle, 1389 MC_CMD_NO_FLAGS, 1390 dflt_dpni->dpni_id); 1391 err_create: 1392 err_prepare_cfg: 1393 free(dflt_dpni); 1394 err_calloc: 1395 return err; 1396 } 1397 1398 static int dpni_exit(void) 1399 { 1400 int err; 1401 1402 err = dpni_destroy(dflt_mc_io, dflt_dprc_handle, MC_CMD_NO_FLAGS, 1403 dflt_dpni->dpni_id); 1404 if (err < 0) { 1405 printf("dpni_destroy() failed: %d\n", err); 1406 goto err; 1407 } 1408 1409 #ifdef DEBUG 1410 printf("Exit: DPNI id=0x%d\n", dflt_dpni->dpni_id); 1411 #endif 1412 1413 if (dflt_dpni) 1414 free(dflt_dpni); 1415 return 0; 1416 1417 err: 1418 return err; 1419 } 1420 1421 static int mc_init_object(void) 1422 { 1423 int err = 0; 1424 1425 err = dprc_init(); 1426 if (err < 0) { 1427 printf("dprc_init() failed: %d\n", err); 1428 goto err; 1429 } 1430 1431 err = dpbp_init(); 1432 if (err < 0) { 1433 printf("dpbp_init() failed: %d\n", err); 1434 goto err; 1435 } 1436 1437 err = dpio_init(); 1438 if (err < 0) { 1439 printf("dpio_init() failed: %d\n", err); 1440 goto err; 1441 } 1442 1443 err = dpni_init(); 1444 if (err < 0) { 1445 printf("dpni_init() failed: %d\n", err); 1446 goto err; 1447 } 1448 1449 return 0; 1450 err: 1451 return err; 1452 } 1453 1454 int fsl_mc_ldpaa_exit(bd_t *bd) 1455 { 1456 int err = 0; 1457 bool is_dpl_apply_status = false; 1458 bool mc_boot_status = false; 1459 1460 if (bd && mc_lazy_dpl_addr && !fsl_mc_ldpaa_exit(NULL)) { 1461 err = mc_apply_dpl(mc_lazy_dpl_addr); 1462 if (!err) 1463 fdt_fixup_board_enet(working_fdt); 1464 mc_lazy_dpl_addr = 0; 1465 } 1466 1467 if (!get_mc_boot_status()) 1468 mc_boot_status = true; 1469 1470 /* MC is not loaded intentionally, So return success. */ 1471 if (bd && !mc_boot_status) 1472 return 0; 1473 1474 /* If DPL is deployed, set is_dpl_apply_status as TRUE. */ 1475 if (!get_dpl_apply_status()) 1476 is_dpl_apply_status = true; 1477 1478 /* 1479 * For case MC is loaded but DPL is not deployed, return success and 1480 * print message on console. Else FDT fix-up code execution hanged. 1481 */ 1482 if (bd && mc_boot_status && !is_dpl_apply_status) { 1483 printf("fsl-mc: DPL not deployed, DPAA2 ethernet not work\n"); 1484 goto mc_obj_cleanup; 1485 } 1486 1487 if (bd && mc_boot_status && is_dpl_apply_status) 1488 return 0; 1489 1490 mc_obj_cleanup: 1491 err = dpbp_exit(); 1492 if (err < 0) { 1493 printf("dpbp_exit() failed: %d\n", err); 1494 goto err; 1495 } 1496 1497 err = dpio_exit(); 1498 if (err < 0) { 1499 printf("dpio_exit() failed: %d\n", err); 1500 goto err; 1501 } 1502 1503 err = dpni_exit(); 1504 if (err < 0) { 1505 printf("dpni_exit() failed: %d\n", err); 1506 goto err; 1507 } 1508 1509 err = dprc_exit(); 1510 if (err < 0) { 1511 printf("dprc_exit() failed: %d\n", err); 1512 goto err; 1513 } 1514 1515 return 0; 1516 err: 1517 return err; 1518 } 1519 1520 static int do_fsl_mc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 1521 { 1522 int err = 0; 1523 if (argc < 3) 1524 goto usage; 1525 1526 switch (argv[1][0]) { 1527 case 's': { 1528 char sub_cmd; 1529 u64 mc_fw_addr, mc_dpc_addr; 1530 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET 1531 u64 aiop_fw_addr; 1532 #endif 1533 1534 sub_cmd = argv[2][0]; 1535 1536 switch (sub_cmd) { 1537 case 'm': 1538 if (argc < 5) 1539 goto usage; 1540 1541 if (get_mc_boot_status() == 0) { 1542 printf("fsl-mc: MC is already booted"); 1543 printf("\n"); 1544 return err; 1545 } 1546 mc_fw_addr = simple_strtoull(argv[3], NULL, 16); 1547 mc_dpc_addr = simple_strtoull(argv[4], NULL, 1548 16); 1549 1550 if (!mc_init(mc_fw_addr, mc_dpc_addr)) 1551 err = mc_init_object(); 1552 break; 1553 1554 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET 1555 case 'a': 1556 if (argc < 4) 1557 goto usage; 1558 if (get_aiop_apply_status() == 0) { 1559 printf("fsl-mc: AIOP FW is already"); 1560 printf(" applied\n"); 1561 return err; 1562 } 1563 1564 aiop_fw_addr = simple_strtoull(argv[3], NULL, 1565 16); 1566 1567 /* if SoC doesn't have AIOP, err = -ENODEV */ 1568 err = load_mc_aiop_img(aiop_fw_addr); 1569 if (!err) 1570 printf("fsl-mc: AIOP FW applied\n"); 1571 break; 1572 #endif 1573 default: 1574 printf("Invalid option: %s\n", argv[2]); 1575 goto usage; 1576 1577 break; 1578 } 1579 } 1580 break; 1581 1582 case 'l': 1583 case 'a': { 1584 u64 mc_dpl_addr; 1585 1586 if (argc < 4) 1587 goto usage; 1588 1589 if (get_dpl_apply_status() == 0) { 1590 printf("fsl-mc: DPL already applied\n"); 1591 return err; 1592 } 1593 1594 mc_dpl_addr = simple_strtoull(argv[3], NULL, 1595 16); 1596 1597 if (get_mc_boot_status() != 0) { 1598 printf("fsl-mc: Deploying data path layout .."); 1599 printf("ERROR (MC is not booted)\n"); 1600 return -ENODEV; 1601 } 1602 1603 if (argv[1][0] == 'l') { 1604 /* 1605 * We will do the actual dpaa exit and dpl apply 1606 * later from announce_and_cleanup(). 1607 */ 1608 mc_lazy_dpl_addr = mc_dpl_addr; 1609 } else { 1610 /* The user wants it applied now */ 1611 if (!fsl_mc_ldpaa_exit(NULL)) 1612 err = mc_apply_dpl(mc_dpl_addr); 1613 } 1614 break; 1615 } 1616 default: 1617 printf("Invalid option: %s\n", argv[1]); 1618 goto usage; 1619 break; 1620 } 1621 return err; 1622 usage: 1623 return CMD_RET_USAGE; 1624 } 1625 1626 U_BOOT_CMD( 1627 fsl_mc, CONFIG_SYS_MAXARGS, 1, do_fsl_mc, 1628 "DPAA2 command to manage Management Complex (MC)", 1629 "start mc [FW_addr] [DPC_addr] - Start Management Complex\n" 1630 "fsl_mc apply DPL [DPL_addr] - Apply DPL file\n" 1631 "fsl_mc lazyapply DPL [DPL_addr] - Apply DPL file on exit\n" 1632 "fsl_mc start aiop [FW_addr] - Start AIOP\n" 1633 ); 1634 1635 void mc_env_boot(void) 1636 { 1637 #if defined(CONFIG_FSL_MC_ENET) 1638 char *mc_boot_env_var; 1639 /* The MC may only be initialized in the reset PHY function 1640 * because otherwise U-Boot has not yet set up all the MAC 1641 * address info properly. Without MAC addresses, the MC code 1642 * can not properly initialize the DPC. 1643 */ 1644 mc_boot_env_var = env_get(MC_BOOT_ENV_VAR); 1645 if (mc_boot_env_var) 1646 run_command_list(mc_boot_env_var, -1, 0); 1647 #endif /* CONFIG_FSL_MC_ENET */ 1648 } 1649