1 /* 2 * Copyright (C) 2014 Freescale Semiconductor 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 #include <common.h> 7 #include <errno.h> 8 #include <asm/io.h> 9 #include <libfdt.h> 10 #include <fdt_support.h> 11 #include <fsl-mc/fsl_mc.h> 12 #include <fsl-mc/fsl_mc_sys.h> 13 #include <fsl-mc/fsl_mc_private.h> 14 #include <fsl-mc/fsl_dpmng.h> 15 #include <fsl-mc/fsl_dprc.h> 16 #include <fsl-mc/fsl_dpio.h> 17 #include <fsl-mc/fsl_qbman_portal.h> 18 19 #define MC_RAM_BASE_ADDR_ALIGNMENT (512UL * 1024 * 1024) 20 #define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1)) 21 #define MC_RAM_SIZE_ALIGNMENT (256UL * 1024 * 1024) 22 23 #define MC_MEM_SIZE_ENV_VAR "mcmemsize" 24 #define MC_BOOT_TIMEOUT_ENV_VAR "mcboottimeout" 25 26 DECLARE_GLOBAL_DATA_PTR; 27 static int mc_boot_status; 28 struct fsl_mc_io *dflt_mc_io = NULL; 29 uint16_t dflt_dprc_handle = 0; 30 struct fsl_dpbp_obj *dflt_dpbp = NULL; 31 struct fsl_dpio_obj *dflt_dpio = NULL; 32 uint16_t dflt_dpio_handle = 0; 33 34 #ifdef DEBUG 35 void dump_ram_words(const char *title, void *addr) 36 { 37 int i; 38 uint32_t *words = addr; 39 40 printf("Dumping beginning of %s (%p):\n", title, addr); 41 for (i = 0; i < 16; i++) 42 printf("%#x ", words[i]); 43 44 printf("\n"); 45 } 46 47 void dump_mc_ccsr_regs(struct mc_ccsr_registers __iomem *mc_ccsr_regs) 48 { 49 printf("MC CCSR registers:\n" 50 "reg_gcr1 %#x\n" 51 "reg_gsr %#x\n" 52 "reg_sicbalr %#x\n" 53 "reg_sicbahr %#x\n" 54 "reg_sicapr %#x\n" 55 "reg_mcfbalr %#x\n" 56 "reg_mcfbahr %#x\n" 57 "reg_mcfapr %#x\n" 58 "reg_psr %#x\n", 59 mc_ccsr_regs->reg_gcr1, 60 mc_ccsr_regs->reg_gsr, 61 mc_ccsr_regs->reg_sicbalr, 62 mc_ccsr_regs->reg_sicbahr, 63 mc_ccsr_regs->reg_sicapr, 64 mc_ccsr_regs->reg_mcfbalr, 65 mc_ccsr_regs->reg_mcfbahr, 66 mc_ccsr_regs->reg_mcfapr, 67 mc_ccsr_regs->reg_psr); 68 } 69 #else 70 71 #define dump_ram_words(title, addr) 72 #define dump_mc_ccsr_regs(mc_ccsr_regs) 73 74 #endif /* DEBUG */ 75 76 #ifndef CONFIG_SYS_LS_MC_FW_IN_DDR 77 /** 78 * Copying MC firmware or DPL image to DDR 79 */ 80 static int mc_copy_image(const char *title, 81 u64 image_addr, u32 image_size, u64 mc_ram_addr) 82 { 83 debug("%s copied to address %p\n", title, (void *)mc_ram_addr); 84 memcpy((void *)mc_ram_addr, (void *)image_addr, image_size); 85 flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size); 86 return 0; 87 } 88 89 /** 90 * MC firmware FIT image parser checks if the image is in FIT 91 * format, verifies integrity of the image and calculates 92 * raw image address and size values. 93 * Returns 0 on success and a negative errno on error. 94 * task fail. 95 **/ 96 int parse_mc_firmware_fit_image(const void **raw_image_addr, 97 size_t *raw_image_size) 98 { 99 int format; 100 void *fit_hdr; 101 int node_offset; 102 const void *data; 103 size_t size; 104 const char *uname = "firmware"; 105 106 /* Check if the image is in NOR flash */ 107 #ifdef CONFIG_SYS_LS_MC_FW_IN_NOR 108 fit_hdr = (void *)CONFIG_SYS_LS_MC_FW_ADDR; 109 #else 110 #error "No CONFIG_SYS_LS_MC_FW_IN_xxx defined" 111 #endif 112 113 /* Check if Image is in FIT format */ 114 format = genimg_get_format(fit_hdr); 115 116 if (format != IMAGE_FORMAT_FIT) { 117 printf("fsl-mc: ERROR: Bad firmware image (not a FIT image)\n"); 118 return -EINVAL; 119 } 120 121 if (!fit_check_format(fit_hdr)) { 122 printf("fsl-mc: ERROR: Bad firmware image (bad FIT header)\n"); 123 return -EINVAL; 124 } 125 126 node_offset = fit_image_get_node(fit_hdr, uname); 127 128 if (node_offset < 0) { 129 printf("fsl-mc: ERROR: Bad firmware image (missing subimage)\n"); 130 return -ENOENT; 131 } 132 133 /* Verify MC firmware image */ 134 if (!(fit_image_verify(fit_hdr, node_offset))) { 135 printf("fsl-mc: ERROR: Bad firmware image (bad CRC)\n"); 136 return -EINVAL; 137 } 138 139 /* Get address and size of raw image */ 140 fit_image_get_data(fit_hdr, node_offset, &data, &size); 141 142 *raw_image_addr = data; 143 *raw_image_size = size; 144 145 return 0; 146 } 147 #endif 148 149 /* 150 * Calculates the values to be used to specify the address range 151 * for the MC private DRAM block, in the MCFBALR/MCFBAHR registers. 152 * It returns the highest 512MB-aligned address within the given 153 * address range, in '*aligned_base_addr', and the number of 256 MiB 154 * blocks in it, in 'num_256mb_blocks'. 155 */ 156 static int calculate_mc_private_ram_params(u64 mc_private_ram_start_addr, 157 size_t mc_ram_size, 158 u64 *aligned_base_addr, 159 u8 *num_256mb_blocks) 160 { 161 u64 addr; 162 u16 num_blocks; 163 164 if (mc_ram_size % MC_RAM_SIZE_ALIGNMENT != 0) { 165 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n", 166 mc_ram_size); 167 return -EINVAL; 168 } 169 170 num_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT; 171 if (num_blocks < 1 || num_blocks > 0xff) { 172 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n", 173 mc_ram_size); 174 return -EINVAL; 175 } 176 177 addr = (mc_private_ram_start_addr + mc_ram_size - 1) & 178 MC_RAM_BASE_ADDR_ALIGNMENT_MASK; 179 180 if (addr < mc_private_ram_start_addr) { 181 printf("fsl-mc: ERROR: bad start address %#llx\n", 182 mc_private_ram_start_addr); 183 return -EFAULT; 184 } 185 186 *aligned_base_addr = addr; 187 *num_256mb_blocks = num_blocks; 188 return 0; 189 } 190 191 static int mc_fixup_dpc(u64 dpc_addr) 192 { 193 void *blob = (void *)dpc_addr; 194 int nodeoffset; 195 196 /* delete any existing ICID pools */ 197 nodeoffset = fdt_path_offset(blob, "/resources/icid_pools"); 198 if (fdt_del_node(blob, nodeoffset) < 0) 199 printf("\nfsl-mc: WARNING: could not delete ICID pool\n"); 200 201 /* add a new pool */ 202 nodeoffset = fdt_path_offset(blob, "/resources"); 203 if (nodeoffset < 0) { 204 printf("\nfsl-mc: ERROR: DPC is missing /resources\n"); 205 return -EINVAL; 206 } 207 nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pools"); 208 nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pool@0"); 209 do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0", 210 "base_icid", FSL_DPAA2_STREAM_ID_START, 1); 211 do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0", 212 "num", 213 FSL_DPAA2_STREAM_ID_END - 214 FSL_DPAA2_STREAM_ID_START + 1, 1); 215 216 flush_dcache_range(dpc_addr, dpc_addr + fdt_totalsize(blob)); 217 218 return 0; 219 } 220 221 static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size) 222 { 223 u64 mc_dpc_offset; 224 #ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR 225 int error; 226 void *dpc_fdt_hdr; 227 int dpc_size; 228 #endif 229 230 #ifdef CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET 231 BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET & 0x3) != 0 || 232 CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET > 0xffffffff); 233 234 mc_dpc_offset = CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET; 235 #else 236 #error "CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET not defined" 237 #endif 238 239 /* 240 * Load the MC DPC blob in the MC private DRAM block: 241 */ 242 #ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR 243 printf("MC DPC is preloaded to %#llx\n", mc_ram_addr + mc_dpc_offset); 244 #else 245 /* 246 * Get address and size of the DPC blob stored in flash: 247 */ 248 #ifdef CONFIG_SYS_LS_MC_DPC_IN_NOR 249 dpc_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPC_ADDR; 250 #else 251 #error "No CONFIG_SYS_LS_MC_DPC_IN_xxx defined" 252 #endif 253 254 error = fdt_check_header(dpc_fdt_hdr); 255 if (error != 0) { 256 /* 257 * Don't return with error here, since the MC firmware can 258 * still boot without a DPC 259 */ 260 printf("\nfsl-mc: WARNING: No DPC image found"); 261 return 0; 262 } 263 264 dpc_size = fdt_totalsize(dpc_fdt_hdr); 265 if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) { 266 printf("\nfsl-mc: ERROR: Bad DPC image (too large: %d)\n", 267 dpc_size); 268 return -EINVAL; 269 } 270 271 mc_copy_image("MC DPC blob", 272 (u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset); 273 #endif /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */ 274 275 if (mc_fixup_dpc(mc_ram_addr + mc_dpc_offset)) 276 return -EINVAL; 277 278 dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset)); 279 return 0; 280 } 281 282 static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size) 283 { 284 u64 mc_dpl_offset; 285 #ifndef CONFIG_SYS_LS_MC_DPL_IN_DDR 286 int error; 287 void *dpl_fdt_hdr; 288 int dpl_size; 289 #endif 290 291 #ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET 292 BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 || 293 CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff); 294 295 mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET; 296 #else 297 #error "CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET not defined" 298 #endif 299 300 /* 301 * Load the MC DPL blob in the MC private DRAM block: 302 */ 303 #ifdef CONFIG_SYS_LS_MC_DPL_IN_DDR 304 printf("MC DPL is preloaded to %#llx\n", mc_ram_addr + mc_dpl_offset); 305 #else 306 /* 307 * Get address and size of the DPL blob stored in flash: 308 */ 309 #ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR 310 dpl_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR; 311 #else 312 #error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined" 313 #endif 314 315 error = fdt_check_header(dpl_fdt_hdr); 316 if (error != 0) { 317 printf("\nfsl-mc: ERROR: Bad DPL image (bad header)\n"); 318 return error; 319 } 320 321 dpl_size = fdt_totalsize(dpl_fdt_hdr); 322 if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) { 323 printf("\nfsl-mc: ERROR: Bad DPL image (too large: %d)\n", 324 dpl_size); 325 return -EINVAL; 326 } 327 328 mc_copy_image("MC DPL blob", 329 (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset); 330 #endif /* not defined CONFIG_SYS_LS_MC_DPL_IN_DDR */ 331 332 dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset)); 333 return 0; 334 } 335 336 /** 337 * Return the MC boot timeout value in milliseconds 338 */ 339 static unsigned long get_mc_boot_timeout_ms(void) 340 { 341 unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS; 342 343 char *timeout_ms_env_var = getenv(MC_BOOT_TIMEOUT_ENV_VAR); 344 345 if (timeout_ms_env_var) { 346 timeout_ms = simple_strtoul(timeout_ms_env_var, NULL, 10); 347 if (timeout_ms == 0) { 348 printf("fsl-mc: WARNING: Invalid value for \'" 349 MC_BOOT_TIMEOUT_ENV_VAR 350 "\' environment variable: %lu\n", 351 timeout_ms); 352 353 timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS; 354 } 355 } 356 357 return timeout_ms; 358 } 359 360 #ifdef CONFIG_SYS_LS_MC_AIOP_IMG_IN_NOR 361 static int load_mc_aiop_img(u64 mc_ram_addr, size_t mc_ram_size) 362 { 363 void *aiop_img; 364 365 /* 366 * Load the MC AIOP image in the MC private DRAM block: 367 */ 368 369 aiop_img = (void *)CONFIG_SYS_LS_MC_AIOP_IMG_ADDR; 370 mc_copy_image("MC AIOP image", 371 (u64)aiop_img, CONFIG_SYS_LS_MC_AIOP_IMG_MAX_LENGTH, 372 mc_ram_addr + CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET); 373 374 return 0; 375 } 376 #endif 377 static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr) 378 { 379 u32 reg_gsr; 380 u32 mc_fw_boot_status; 381 unsigned long timeout_ms = get_mc_boot_timeout_ms(); 382 struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR; 383 384 dmb(); 385 assert(timeout_ms > 0); 386 for (;;) { 387 udelay(1000); /* throttle polling */ 388 reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr); 389 mc_fw_boot_status = (reg_gsr & GSR_FS_MASK); 390 if (mc_fw_boot_status & 0x1) 391 break; 392 393 timeout_ms--; 394 if (timeout_ms == 0) 395 break; 396 } 397 398 if (timeout_ms == 0) { 399 printf("ERROR: timeout\n"); 400 401 /* TODO: Get an error status from an MC CCSR register */ 402 return -ETIMEDOUT; 403 } 404 405 if (mc_fw_boot_status != 0x1) { 406 /* 407 * TODO: Identify critical errors from the GSR register's FS 408 * field and for those errors, set error to -ENODEV or other 409 * appropriate errno, so that the status property is set to 410 * failure in the fsl,dprc device tree node. 411 */ 412 printf("WARNING: Firmware returned an error (GSR: %#x)\n", 413 reg_gsr); 414 } else { 415 printf("SUCCESS\n"); 416 } 417 418 419 *final_reg_gsr = reg_gsr; 420 return 0; 421 } 422 423 int mc_init(void) 424 { 425 int error = 0; 426 int portal_id = 0; 427 struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR; 428 u64 mc_ram_addr; 429 u32 reg_gsr; 430 u32 reg_mcfbalr; 431 #ifndef CONFIG_SYS_LS_MC_FW_IN_DDR 432 const void *raw_image_addr; 433 size_t raw_image_size = 0; 434 #endif 435 struct mc_version mc_ver_info; 436 u64 mc_ram_aligned_base_addr; 437 u8 mc_ram_num_256mb_blocks; 438 size_t mc_ram_size = mc_get_dram_block_size(); 439 440 /* 441 * The MC private DRAM block was already carved at the end of DRAM 442 * by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE: 443 */ 444 if (gd->bd->bi_dram[1].start) { 445 mc_ram_addr = 446 gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size; 447 } else { 448 mc_ram_addr = 449 gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size; 450 } 451 452 error = calculate_mc_private_ram_params(mc_ram_addr, 453 mc_ram_size, 454 &mc_ram_aligned_base_addr, 455 &mc_ram_num_256mb_blocks); 456 if (error != 0) 457 goto out; 458 459 /* 460 * Management Complex cores should be held at reset out of POR. 461 * U-boot should be the first software to touch MC. To be safe, 462 * we reset all cores again by setting GCR1 to 0. It doesn't do 463 * anything if they are held at reset. After we setup the firmware 464 * we kick off MC by deasserting the reset bit for core 0, and 465 * deasserting the reset bits for Command Portal Managers. 466 * The stop bits are not touched here. They are used to stop the 467 * cores when they are active. Setting stop bits doesn't stop the 468 * cores from fetching instructions when they are released from 469 * reset. 470 */ 471 out_le32(&mc_ccsr_regs->reg_gcr1, 0); 472 dmb(); 473 474 #ifdef CONFIG_SYS_LS_MC_FW_IN_DDR 475 printf("MC firmware is preloaded to %#llx\n", mc_ram_addr); 476 #else 477 error = parse_mc_firmware_fit_image(&raw_image_addr, &raw_image_size); 478 if (error != 0) 479 goto out; 480 /* 481 * Load the MC FW at the beginning of the MC private DRAM block: 482 */ 483 mc_copy_image("MC Firmware", 484 (u64)raw_image_addr, raw_image_size, mc_ram_addr); 485 #endif 486 dump_ram_words("firmware", (void *)mc_ram_addr); 487 488 error = load_mc_dpc(mc_ram_addr, mc_ram_size); 489 if (error != 0) 490 goto out; 491 492 error = load_mc_dpl(mc_ram_addr, mc_ram_size); 493 if (error != 0) 494 goto out; 495 496 #ifdef CONFIG_SYS_LS_MC_AIOP_IMG_IN_NOR 497 error = load_mc_aiop_img(mc_ram_addr, mc_ram_size); 498 if (error != 0) 499 goto out; 500 #endif 501 502 debug("mc_ccsr_regs %p\n", mc_ccsr_regs); 503 dump_mc_ccsr_regs(mc_ccsr_regs); 504 505 /* 506 * Tell MC what is the address range of the DRAM block assigned to it: 507 */ 508 reg_mcfbalr = (u32)mc_ram_aligned_base_addr | 509 (mc_ram_num_256mb_blocks - 1); 510 out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr); 511 out_le32(&mc_ccsr_regs->reg_mcfbahr, 512 (u32)(mc_ram_aligned_base_addr >> 32)); 513 out_le32(&mc_ccsr_regs->reg_mcfapr, FSL_BYPASS_AMQ); 514 515 /* 516 * Tell the MC that we want delayed DPL deployment. 517 */ 518 out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00); 519 520 printf("\nfsl-mc: Booting Management Complex ... "); 521 522 /* 523 * Deassert reset and release MC core 0 to run 524 */ 525 out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST); 526 error = wait_for_mc(true, ®_gsr); 527 if (error != 0) 528 goto out; 529 530 /* 531 * TODO: need to obtain the portal_id for the root container from the 532 * DPL 533 */ 534 portal_id = 0; 535 536 /* 537 * Initialize the global default MC portal 538 * And check that the MC firmware is responding portal commands: 539 */ 540 dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io)); 541 if (!dflt_mc_io) { 542 printf(" No memory: malloc() failed\n"); 543 return -ENOMEM; 544 } 545 546 dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id); 547 debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n", 548 portal_id, dflt_mc_io->mmio_regs); 549 550 error = mc_get_version(dflt_mc_io, MC_CMD_NO_FLAGS, &mc_ver_info); 551 if (error != 0) { 552 printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n", 553 error); 554 goto out; 555 } 556 557 if (MC_VER_MAJOR != mc_ver_info.major) { 558 printf("fsl-mc: ERROR: Firmware major version mismatch (found: %d, expected: %d)\n", 559 mc_ver_info.major, MC_VER_MAJOR); 560 printf("fsl-mc: Update the Management Complex firmware\n"); 561 562 error = -ENODEV; 563 goto out; 564 } 565 566 if (MC_VER_MINOR != mc_ver_info.minor) 567 printf("fsl-mc: WARNING: Firmware minor version mismatch (found: %d, expected: %d)\n", 568 mc_ver_info.minor, MC_VER_MINOR); 569 570 printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n", 571 mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision, 572 reg_gsr & GSR_FS_MASK); 573 574 /* 575 * Tell the MC to deploy the DPL: 576 */ 577 out_le32(&mc_ccsr_regs->reg_gsr, 0x0); 578 printf("fsl-mc: Deploying data path layout ... "); 579 error = wait_for_mc(false, ®_gsr); 580 if (error != 0) 581 goto out; 582 583 out: 584 if (error != 0) 585 mc_boot_status = error; 586 else 587 mc_boot_status = 0; 588 589 return error; 590 } 591 592 int get_mc_boot_status(void) 593 { 594 return mc_boot_status; 595 } 596 597 /** 598 * Return the actual size of the MC private DRAM block. 599 */ 600 unsigned long mc_get_dram_block_size(void) 601 { 602 unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE; 603 604 char *dram_block_size_env_var = getenv(MC_MEM_SIZE_ENV_VAR); 605 606 if (dram_block_size_env_var) { 607 dram_block_size = simple_strtoul(dram_block_size_env_var, NULL, 608 10); 609 610 if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) { 611 printf("fsl-mc: WARNING: Invalid value for \'" 612 MC_MEM_SIZE_ENV_VAR 613 "\' environment variable: %lu\n", 614 dram_block_size); 615 616 dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE; 617 } 618 } 619 620 return dram_block_size; 621 } 622 623 int dpio_init(struct dprc_obj_desc obj_desc) 624 { 625 struct qbman_swp_desc p_des; 626 struct dpio_attr attr; 627 int err = 0; 628 629 dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj)); 630 if (!dflt_dpio) { 631 printf(" No memory: malloc() failed\n"); 632 return -ENOMEM; 633 } 634 635 dflt_dpio->dpio_id = obj_desc.id; 636 637 err = dpio_open(dflt_mc_io, MC_CMD_NO_FLAGS, obj_desc.id, 638 &dflt_dpio_handle); 639 if (err) { 640 printf("dpio_open() failed\n"); 641 goto err_open; 642 } 643 644 err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS, 645 dflt_dpio_handle, &attr); 646 if (err) { 647 printf("dpio_get_attributes() failed %d\n", err); 648 goto err_get_attr; 649 } 650 651 err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio_handle); 652 if (err) { 653 printf("dpio_enable() failed %d\n", err); 654 goto err_get_enable; 655 } 656 debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n", 657 attr.qbman_portal_ce_offset, 658 attr.qbman_portal_ci_offset, 659 attr.qbman_portal_id, 660 attr.num_priorities); 661 662 p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR 663 + attr.qbman_portal_ce_offset); 664 p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR 665 + attr.qbman_portal_ci_offset); 666 667 dflt_dpio->sw_portal = qbman_swp_init(&p_des); 668 if (dflt_dpio->sw_portal == NULL) { 669 printf("qbman_swp_init() failed\n"); 670 goto err_get_swp_init; 671 } 672 return 0; 673 674 err_get_swp_init: 675 err_get_enable: 676 dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio_handle); 677 err_get_attr: 678 dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio_handle); 679 err_open: 680 free(dflt_dpio); 681 return err; 682 } 683 684 int dpbp_init(struct dprc_obj_desc obj_desc) 685 { 686 dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj)); 687 if (!dflt_dpbp) { 688 printf(" No memory: malloc() failed\n"); 689 return -ENOMEM; 690 } 691 dflt_dpbp->dpbp_attr.id = obj_desc.id; 692 693 return 0; 694 } 695 696 int dprc_init_container_obj(struct dprc_obj_desc obj_desc, uint16_t dprc_handle) 697 { 698 int error = 0, state = 0; 699 struct dprc_endpoint dpni_endpoint, dpmac_endpoint; 700 if (!strcmp(obj_desc.type, "dpbp")) { 701 if (!dflt_dpbp) { 702 error = dpbp_init(obj_desc); 703 if (error < 0) 704 printf("dpbp_init failed\n"); 705 } 706 } else if (!strcmp(obj_desc.type, "dpio")) { 707 if (!dflt_dpio) { 708 error = dpio_init(obj_desc); 709 if (error < 0) 710 printf("dpio_init failed\n"); 711 } 712 } else if (!strcmp(obj_desc.type, "dpni")) { 713 strcpy(dpni_endpoint.type, obj_desc.type); 714 dpni_endpoint.id = obj_desc.id; 715 error = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS, 716 dprc_handle, &dpni_endpoint, 717 &dpmac_endpoint, &state); 718 if (!strcmp(dpmac_endpoint.type, "dpmac")) 719 error = ldpaa_eth_init(obj_desc); 720 if (error < 0) 721 printf("ldpaa_eth_init failed\n"); 722 } 723 724 return error; 725 } 726 727 int dprc_scan_container_obj(uint16_t dprc_handle, char *obj_type, int i) 728 { 729 int error = 0; 730 struct dprc_obj_desc obj_desc; 731 732 memset((void *)&obj_desc, 0x00, sizeof(struct dprc_obj_desc)); 733 734 error = dprc_get_obj(dflt_mc_io, MC_CMD_NO_FLAGS, dprc_handle, 735 i, &obj_desc); 736 if (error < 0) { 737 printf("dprc_get_obj(i=%d) failed: %d\n", 738 i, error); 739 return error; 740 } 741 742 if (!strcmp(obj_desc.type, obj_type)) { 743 debug("Discovered object: type %s, id %d, req %s\n", 744 obj_desc.type, obj_desc.id, obj_type); 745 746 error = dprc_init_container_obj(obj_desc, dprc_handle); 747 if (error < 0) { 748 printf("dprc_init_container_obj(i=%d) failed: %d\n", 749 i, error); 750 return error; 751 } 752 } 753 754 return error; 755 } 756 757 int fsl_mc_ldpaa_init(bd_t *bis) 758 { 759 int i, error = 0; 760 int dprc_opened = 0, container_id; 761 int num_child_objects = 0; 762 763 error = mc_init(); 764 if (error < 0) 765 goto error; 766 767 error = dprc_get_container_id(dflt_mc_io, MC_CMD_NO_FLAGS, 768 &container_id); 769 if (error < 0) { 770 printf("dprc_get_container_id() failed: %d\n", error); 771 goto error; 772 } 773 774 debug("fsl-mc: Container id=0x%x\n", container_id); 775 776 error = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, container_id, 777 &dflt_dprc_handle); 778 if (error < 0) { 779 printf("dprc_open() failed: %d\n", error); 780 goto error; 781 } 782 dprc_opened = true; 783 784 error = dprc_get_obj_count(dflt_mc_io, 785 MC_CMD_NO_FLAGS, dflt_dprc_handle, 786 &num_child_objects); 787 if (error < 0) { 788 printf("dprc_get_obj_count() failed: %d\n", error); 789 goto error; 790 } 791 debug("Total child in container %d = %d\n", container_id, 792 num_child_objects); 793 794 if (num_child_objects != 0) { 795 /* 796 * Discover objects currently in the DPRC container in the MC: 797 */ 798 for (i = 0; i < num_child_objects; i++) 799 error = dprc_scan_container_obj(dflt_dprc_handle, 800 "dpbp", i); 801 802 for (i = 0; i < num_child_objects; i++) 803 error = dprc_scan_container_obj(dflt_dprc_handle, 804 "dpio", i); 805 806 for (i = 0; i < num_child_objects; i++) 807 error = dprc_scan_container_obj(dflt_dprc_handle, 808 "dpni", i); 809 } 810 error: 811 if (dprc_opened) 812 dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle); 813 814 return error; 815 } 816 817 void fsl_mc_ldpaa_exit(bd_t *bis) 818 { 819 int err; 820 821 if (get_mc_boot_status() == 0) { 822 err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, 823 dflt_dpio_handle); 824 if (err < 0) { 825 printf("dpio_disable() failed: %d\n", err); 826 return; 827 } 828 err = dpio_reset(dflt_mc_io, MC_CMD_NO_FLAGS, 829 dflt_dpio_handle); 830 if (err < 0) { 831 printf("dpio_reset() failed: %d\n", err); 832 return; 833 } 834 err = dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, 835 dflt_dpio_handle); 836 if (err < 0) { 837 printf("dpio_close() failed: %d\n", err); 838 return; 839 } 840 841 free(dflt_dpio); 842 free(dflt_dpbp); 843 } 844 845 if (dflt_mc_io) 846 free(dflt_mc_io); 847 } 848