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