uboot/drivers/net/fsl-mc/mc.c
<<
>>
Prefs
   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_dpni.h>
  18#include <fsl-mc/fsl_qbman_portal.h>
  19#include <fsl-mc/ldpaa_wriop.h>
  20
  21#define MC_RAM_BASE_ADDR_ALIGNMENT  (512UL * 1024 * 1024)
  22#define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1))
  23#define MC_RAM_SIZE_ALIGNMENT       (256UL * 1024 * 1024)
  24
  25#define MC_MEM_SIZE_ENV_VAR     "mcmemsize"
  26#define MC_BOOT_TIMEOUT_ENV_VAR "mcboottimeout"
  27
  28DECLARE_GLOBAL_DATA_PTR;
  29static int mc_boot_status = -1;
  30static int mc_dpl_applied = -1;
  31#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
  32static int mc_aiop_applied = -1;
  33#endif
  34struct fsl_mc_io *root_mc_io = NULL;
  35struct fsl_mc_io *dflt_mc_io = NULL; /* child container */
  36uint16_t root_dprc_handle = 0;
  37uint16_t dflt_dprc_handle = 0;
  38int child_dprc_id;
  39struct fsl_dpbp_obj *dflt_dpbp = NULL;
  40struct fsl_dpio_obj *dflt_dpio = NULL;
  41struct fsl_dpni_obj *dflt_dpni = NULL;
  42
  43#ifdef DEBUG
  44void dump_ram_words(const char *title, void *addr)
  45{
  46        int i;
  47        uint32_t *words = addr;
  48
  49        printf("Dumping beginning of %s (%p):\n", title, addr);
  50        for (i = 0; i < 16; i++)
  51                printf("%#x ", words[i]);
  52
  53        printf("\n");
  54}
  55
  56void dump_mc_ccsr_regs(struct mc_ccsr_registers __iomem *mc_ccsr_regs)
  57{
  58        printf("MC CCSR registers:\n"
  59                "reg_gcr1 %#x\n"
  60                "reg_gsr %#x\n"
  61                "reg_sicbalr %#x\n"
  62                "reg_sicbahr %#x\n"
  63                "reg_sicapr %#x\n"
  64                "reg_mcfbalr %#x\n"
  65                "reg_mcfbahr %#x\n"
  66                "reg_mcfapr %#x\n"
  67                "reg_psr %#x\n",
  68                mc_ccsr_regs->reg_gcr1,
  69                mc_ccsr_regs->reg_gsr,
  70                mc_ccsr_regs->reg_sicbalr,
  71                mc_ccsr_regs->reg_sicbahr,
  72                mc_ccsr_regs->reg_sicapr,
  73                mc_ccsr_regs->reg_mcfbalr,
  74                mc_ccsr_regs->reg_mcfbahr,
  75                mc_ccsr_regs->reg_mcfapr,
  76                mc_ccsr_regs->reg_psr);
  77}
  78#else
  79
  80#define dump_ram_words(title, addr)
  81#define dump_mc_ccsr_regs(mc_ccsr_regs)
  82
  83#endif /* DEBUG */
  84
  85#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
  86/**
  87 * Copying MC firmware or DPL image to DDR
  88 */
  89static int mc_copy_image(const char *title,
  90                         u64 image_addr, u32 image_size, u64 mc_ram_addr)
  91{
  92        debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
  93        memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
  94        flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size);
  95        return 0;
  96}
  97
  98/**
  99 * MC firmware FIT image parser checks if the image is in FIT
 100 * format, verifies integrity of the image and calculates
 101 * raw image address and size values.
 102 * Returns 0 on success and a negative errno on error.
 103 * task fail.
 104 **/
 105int parse_mc_firmware_fit_image(u64 mc_fw_addr,
 106                                const void **raw_image_addr,
 107                                size_t *raw_image_size)
 108{
 109        int format;
 110        void *fit_hdr;
 111        int node_offset;
 112        const void *data;
 113        size_t size;
 114        const char *uname = "firmware";
 115
 116        fit_hdr = (void *)mc_fw_addr;
 117
 118        /* Check if Image is in FIT format */
 119        format = genimg_get_format(fit_hdr);
 120
 121        if (format != IMAGE_FORMAT_FIT) {
 122                printf("fsl-mc: ERR: Bad firmware image (not a FIT image)\n");
 123                return -EINVAL;
 124        }
 125
 126        if (!fit_check_format(fit_hdr)) {
 127                printf("fsl-mc: ERR: Bad firmware image (bad FIT header)\n");
 128                return -EINVAL;
 129        }
 130
 131        node_offset = fit_image_get_node(fit_hdr, uname);
 132
 133        if (node_offset < 0) {
 134                printf("fsl-mc: ERR: Bad firmware image (missing subimage)\n");
 135                return -ENOENT;
 136        }
 137
 138        /* Verify MC firmware image */
 139        if (!(fit_image_verify(fit_hdr, node_offset))) {
 140                printf("fsl-mc: ERR: Bad firmware image (bad CRC)\n");
 141                return -EINVAL;
 142        }
 143
 144        /* Get address and size of raw image */
 145        fit_image_get_data(fit_hdr, node_offset, &data, &size);
 146
 147        *raw_image_addr = data;
 148        *raw_image_size = size;
 149
 150        return 0;
 151}
 152#endif
 153
 154/*
 155 * Calculates the values to be used to specify the address range
 156 * for the MC private DRAM block, in the MCFBALR/MCFBAHR registers.
 157 * It returns the highest 512MB-aligned address within the given
 158 * address range, in '*aligned_base_addr', and the number of 256 MiB
 159 * blocks in it, in 'num_256mb_blocks'.
 160 */
 161static int calculate_mc_private_ram_params(u64 mc_private_ram_start_addr,
 162                                           size_t mc_ram_size,
 163                                           u64 *aligned_base_addr,
 164                                           u8 *num_256mb_blocks)
 165{
 166        u64 addr;
 167        u16 num_blocks;
 168
 169        if (mc_ram_size % MC_RAM_SIZE_ALIGNMENT != 0) {
 170                printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
 171                       mc_ram_size);
 172                return -EINVAL;
 173        }
 174
 175        num_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT;
 176        if (num_blocks < 1 || num_blocks > 0xff) {
 177                printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
 178                       mc_ram_size);
 179                return -EINVAL;
 180        }
 181
 182        addr = (mc_private_ram_start_addr + mc_ram_size - 1) &
 183                MC_RAM_BASE_ADDR_ALIGNMENT_MASK;
 184
 185        if (addr < mc_private_ram_start_addr) {
 186                printf("fsl-mc: ERROR: bad start address %#llx\n",
 187                       mc_private_ram_start_addr);
 188                return -EFAULT;
 189        }
 190
 191        *aligned_base_addr = addr;
 192        *num_256mb_blocks = num_blocks;
 193        return 0;
 194}
 195
 196static int mc_fixup_dpc(u64 dpc_addr)
 197{
 198        void *blob = (void *)dpc_addr;
 199        int nodeoffset;
 200
 201        /* delete any existing ICID pools */
 202        nodeoffset = fdt_path_offset(blob, "/resources/icid_pools");
 203        if (fdt_del_node(blob, nodeoffset) < 0)
 204                printf("\nfsl-mc: WARNING: could not delete ICID pool\n");
 205
 206        /* add a new pool */
 207        nodeoffset = fdt_path_offset(blob, "/resources");
 208        if (nodeoffset < 0) {
 209                printf("\nfsl-mc: ERROR: DPC is missing /resources\n");
 210                return -EINVAL;
 211        }
 212        nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pools");
 213        nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pool@0");
 214        do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
 215                             "base_icid", FSL_DPAA2_STREAM_ID_START, 1);
 216        do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
 217                             "num",
 218                             FSL_DPAA2_STREAM_ID_END -
 219                             FSL_DPAA2_STREAM_ID_START + 1, 1);
 220
 221        flush_dcache_range(dpc_addr, dpc_addr + fdt_totalsize(blob));
 222
 223        return 0;
 224}
 225
 226static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpc_addr)
 227{
 228        u64 mc_dpc_offset;
 229#ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
 230        int error;
 231        void *dpc_fdt_hdr;
 232        int dpc_size;
 233#endif
 234
 235#ifdef CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET
 236        BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET & 0x3) != 0 ||
 237                     CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET > 0xffffffff);
 238
 239        mc_dpc_offset = CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET;
 240#else
 241#error "CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET not defined"
 242#endif
 243
 244        /*
 245         * Load the MC DPC blob in the MC private DRAM block:
 246         */
 247#ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
 248        printf("MC DPC is preloaded to %#llx\n", mc_ram_addr + mc_dpc_offset);
 249#else
 250        /*
 251         * Get address and size of the DPC blob stored in flash:
 252         */
 253        dpc_fdt_hdr = (void *)mc_dpc_addr;
 254
 255        error = fdt_check_header(dpc_fdt_hdr);
 256        if (error != 0) {
 257                /*
 258                 * Don't return with error here, since the MC firmware can
 259                 * still boot without a DPC
 260                 */
 261                printf("\nfsl-mc: WARNING: No DPC image found");
 262                return 0;
 263        }
 264
 265        dpc_size = fdt_totalsize(dpc_fdt_hdr);
 266        if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) {
 267                printf("\nfsl-mc: ERROR: Bad DPC image (too large: %d)\n",
 268                       dpc_size);
 269                return -EINVAL;
 270        }
 271
 272        mc_copy_image("MC DPC blob",
 273                      (u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset);
 274#endif /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */
 275
 276        if (mc_fixup_dpc(mc_ram_addr + mc_dpc_offset))
 277                return -EINVAL;
 278
 279        dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset));
 280        return 0;
 281}
 282
 283static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpl_addr)
 284{
 285        u64 mc_dpl_offset;
 286#ifndef CONFIG_SYS_LS_MC_DPL_IN_DDR
 287        int error;
 288        void *dpl_fdt_hdr;
 289        int dpl_size;
 290#endif
 291
 292#ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
 293        BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
 294                     CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
 295
 296        mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
 297#else
 298#error "CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET not defined"
 299#endif
 300
 301        /*
 302         * Load the MC DPL blob in the MC private DRAM block:
 303         */
 304#ifdef CONFIG_SYS_LS_MC_DPL_IN_DDR
 305        printf("MC DPL is preloaded to %#llx\n", mc_ram_addr + mc_dpl_offset);
 306#else
 307        /*
 308         * Get address and size of the DPL blob stored in flash:
 309         */
 310        dpl_fdt_hdr = (void *)mc_dpl_addr;
 311
 312        error = fdt_check_header(dpl_fdt_hdr);
 313        if (error != 0) {
 314                printf("\nfsl-mc: ERROR: Bad DPL image (bad header)\n");
 315                return error;
 316        }
 317
 318        dpl_size = fdt_totalsize(dpl_fdt_hdr);
 319        if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
 320                printf("\nfsl-mc: ERROR: Bad DPL image (too large: %d)\n",
 321                       dpl_size);
 322                return -EINVAL;
 323        }
 324
 325        mc_copy_image("MC DPL blob",
 326                      (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
 327#endif /* not defined CONFIG_SYS_LS_MC_DPL_IN_DDR */
 328
 329        dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset));
 330        return 0;
 331}
 332
 333/**
 334 * Return the MC boot timeout value in milliseconds
 335 */
 336static unsigned long get_mc_boot_timeout_ms(void)
 337{
 338        unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
 339
 340        char *timeout_ms_env_var = getenv(MC_BOOT_TIMEOUT_ENV_VAR);
 341
 342        if (timeout_ms_env_var) {
 343                timeout_ms = simple_strtoul(timeout_ms_env_var, NULL, 10);
 344                if (timeout_ms == 0) {
 345                        printf("fsl-mc: WARNING: Invalid value for \'"
 346                               MC_BOOT_TIMEOUT_ENV_VAR
 347                               "\' environment variable: %lu\n",
 348                               timeout_ms);
 349
 350                        timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
 351                }
 352        }
 353
 354        return timeout_ms;
 355}
 356
 357#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
 358static int load_mc_aiop_img(u64 aiop_fw_addr)
 359{
 360        u64 mc_ram_addr = mc_get_dram_addr();
 361#ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
 362        void *aiop_img;
 363#endif
 364
 365        /*
 366         * Load the MC AIOP image in the MC private DRAM block:
 367         */
 368
 369#ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
 370        printf("MC AIOP is preloaded to %#llx\n", mc_ram_addr +
 371               CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
 372#else
 373        aiop_img = (void *)aiop_fw_addr;
 374        mc_copy_image("MC AIOP image",
 375                      (u64)aiop_img, CONFIG_SYS_LS_MC_AIOP_IMG_MAX_LENGTH,
 376                      mc_ram_addr + CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
 377#endif
 378        mc_aiop_applied = 0;
 379
 380        return 0;
 381}
 382#endif
 383
 384static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr)
 385{
 386        u32 reg_gsr;
 387        u32 mc_fw_boot_status;
 388        unsigned long timeout_ms = get_mc_boot_timeout_ms();
 389        struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
 390
 391        dmb();
 392        assert(timeout_ms > 0);
 393        for (;;) {
 394                udelay(1000);   /* throttle polling */
 395                reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
 396                mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
 397                if (mc_fw_boot_status & 0x1)
 398                        break;
 399
 400                timeout_ms--;
 401                if (timeout_ms == 0)
 402                        break;
 403        }
 404
 405        if (timeout_ms == 0) {
 406                printf("ERROR: timeout\n");
 407
 408                /* TODO: Get an error status from an MC CCSR register */
 409                return -ETIMEDOUT;
 410        }
 411
 412        if (mc_fw_boot_status != 0x1) {
 413                /*
 414                 * TODO: Identify critical errors from the GSR register's FS
 415                 * field and for those errors, set error to -ENODEV or other
 416                 * appropriate errno, so that the status property is set to
 417                 * failure in the fsl,dprc device tree node.
 418                 */
 419                printf("WARNING: Firmware returned an error (GSR: %#x)\n",
 420                       reg_gsr);
 421        } else {
 422                printf("SUCCESS\n");
 423        }
 424
 425
 426        *final_reg_gsr = reg_gsr;
 427        return 0;
 428}
 429
 430int mc_init(u64 mc_fw_addr, u64 mc_dpc_addr)
 431{
 432        int error = 0;
 433        int portal_id = 0;
 434        struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
 435        u64 mc_ram_addr = mc_get_dram_addr();
 436        u32 reg_gsr;
 437        u32 reg_mcfbalr;
 438#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
 439        const void *raw_image_addr;
 440        size_t raw_image_size = 0;
 441#endif
 442        struct mc_version mc_ver_info;
 443        u64 mc_ram_aligned_base_addr;
 444        u8 mc_ram_num_256mb_blocks;
 445        size_t mc_ram_size = mc_get_dram_block_size();
 446
 447
 448        error = calculate_mc_private_ram_params(mc_ram_addr,
 449                                                mc_ram_size,
 450                                                &mc_ram_aligned_base_addr,
 451                                                &mc_ram_num_256mb_blocks);
 452        if (error != 0)
 453                goto out;
 454
 455        /*
 456         * Management Complex cores should be held at reset out of POR.
 457         * U-boot should be the first software to touch MC. To be safe,
 458         * we reset all cores again by setting GCR1 to 0. It doesn't do
 459         * anything if they are held at reset. After we setup the firmware
 460         * we kick off MC by deasserting the reset bit for core 0, and
 461         * deasserting the reset bits for Command Portal Managers.
 462         * The stop bits are not touched here. They are used to stop the
 463         * cores when they are active. Setting stop bits doesn't stop the
 464         * cores from fetching instructions when they are released from
 465         * reset.
 466         */
 467        out_le32(&mc_ccsr_regs->reg_gcr1, 0);
 468        dmb();
 469
 470#ifdef CONFIG_SYS_LS_MC_FW_IN_DDR
 471        printf("MC firmware is preloaded to %#llx\n", mc_ram_addr);
 472#else
 473        error = parse_mc_firmware_fit_image(mc_fw_addr, &raw_image_addr,
 474                                            &raw_image_size);
 475        if (error != 0)
 476                goto out;
 477        /*
 478         * Load the MC FW at the beginning of the MC private DRAM block:
 479         */
 480        mc_copy_image("MC Firmware",
 481                      (u64)raw_image_addr, raw_image_size, mc_ram_addr);
 482#endif
 483        dump_ram_words("firmware", (void *)mc_ram_addr);
 484
 485        error = load_mc_dpc(mc_ram_addr, mc_ram_size, mc_dpc_addr);
 486        if (error != 0)
 487                goto out;
 488
 489        debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
 490        dump_mc_ccsr_regs(mc_ccsr_regs);
 491
 492        /*
 493         * Tell MC what is the address range of the DRAM block assigned to it:
 494         */
 495        reg_mcfbalr = (u32)mc_ram_aligned_base_addr |
 496                      (mc_ram_num_256mb_blocks - 1);
 497        out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr);
 498        out_le32(&mc_ccsr_regs->reg_mcfbahr,
 499                 (u32)(mc_ram_aligned_base_addr >> 32));
 500        out_le32(&mc_ccsr_regs->reg_mcfapr, FSL_BYPASS_AMQ);
 501
 502        /*
 503         * Tell the MC that we want delayed DPL deployment.
 504         */
 505        out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00);
 506
 507        printf("\nfsl-mc: Booting Management Complex ... ");
 508
 509        /*
 510         * Deassert reset and release MC core 0 to run
 511         */
 512        out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
 513        error = wait_for_mc(true, &reg_gsr);
 514        if (error != 0)
 515                goto out;
 516
 517        /*
 518         * TODO: need to obtain the portal_id for the root container from the
 519         * DPL
 520         */
 521        portal_id = 0;
 522
 523        /*
 524         * Initialize the global default MC portal
 525         * And check that the MC firmware is responding portal commands:
 526         */
 527        root_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
 528        if (!root_mc_io) {
 529                printf(" No memory: malloc() failed\n");
 530                return -ENOMEM;
 531        }
 532
 533        root_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
 534        debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
 535              portal_id, root_mc_io->mmio_regs);
 536
 537        error = mc_get_version(root_mc_io, MC_CMD_NO_FLAGS, &mc_ver_info);
 538        if (error != 0) {
 539                printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n",
 540                       error);
 541                goto out;
 542        }
 543
 544        printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n",
 545               mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision,
 546               reg_gsr & GSR_FS_MASK);
 547
 548out:
 549        if (error != 0)
 550                mc_boot_status = error;
 551        else
 552                mc_boot_status = 0;
 553
 554        return error;
 555}
 556
 557int mc_apply_dpl(u64 mc_dpl_addr)
 558{
 559        struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
 560        int error = 0;
 561        u32 reg_gsr;
 562        u64 mc_ram_addr = mc_get_dram_addr();
 563        size_t mc_ram_size = mc_get_dram_block_size();
 564
 565        error = load_mc_dpl(mc_ram_addr, mc_ram_size, mc_dpl_addr);
 566        if (error != 0)
 567                return error;
 568
 569        /*
 570         * Tell the MC to deploy the DPL:
 571         */
 572        out_le32(&mc_ccsr_regs->reg_gsr, 0x0);
 573        printf("fsl-mc: Deploying data path layout ... ");
 574        error = wait_for_mc(false, &reg_gsr);
 575
 576        if (!error)
 577                mc_dpl_applied = 0;
 578
 579        return error;
 580}
 581
 582int get_mc_boot_status(void)
 583{
 584        return mc_boot_status;
 585}
 586
 587#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
 588int get_aiop_apply_status(void)
 589{
 590        return mc_aiop_applied;
 591}
 592#endif
 593
 594int get_dpl_apply_status(void)
 595{
 596        return mc_dpl_applied;
 597}
 598
 599/**
 600 * Return the MC address of private DRAM block.
 601 */
 602u64 mc_get_dram_addr(void)
 603{
 604        u64 mc_ram_addr;
 605
 606        /*
 607         * The MC private DRAM block was already carved at the end of DRAM
 608         * by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE:
 609         */
 610        if (gd->bd->bi_dram[1].start) {
 611                mc_ram_addr =
 612                        gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size;
 613        } else {
 614                mc_ram_addr =
 615                        gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
 616        }
 617
 618        return mc_ram_addr;
 619}
 620
 621/**
 622 * Return the actual size of the MC private DRAM block.
 623 */
 624unsigned long mc_get_dram_block_size(void)
 625{
 626        unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
 627
 628        char *dram_block_size_env_var = getenv(MC_MEM_SIZE_ENV_VAR);
 629
 630        if (dram_block_size_env_var) {
 631                dram_block_size = simple_strtoul(dram_block_size_env_var, NULL,
 632                                                 10);
 633
 634                if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
 635                        printf("fsl-mc: WARNING: Invalid value for \'"
 636                               MC_MEM_SIZE_ENV_VAR
 637                               "\' environment variable: %lu\n",
 638                               dram_block_size);
 639
 640                        dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
 641                }
 642        }
 643
 644        return dram_block_size;
 645}
 646
 647int fsl_mc_ldpaa_init(bd_t *bis)
 648{
 649        int i;
 650
 651        for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++)
 652                if ((wriop_is_enabled_dpmac(i) == 1) &&
 653                    (wriop_get_phy_address(i) != -1))
 654                        ldpaa_eth_init(i, wriop_get_enet_if(i));
 655        return 0;
 656}
 657
 658static int dpio_init(void)
 659{
 660        struct qbman_swp_desc p_des;
 661        struct dpio_attr attr;
 662        struct dpio_cfg dpio_cfg;
 663        int err = 0;
 664
 665        dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj));
 666        if (!dflt_dpio) {
 667                printf("No memory: malloc() failed\n");
 668                err = -ENOMEM;
 669                goto err_malloc;
 670        }
 671
 672        dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL;
 673        dpio_cfg.num_priorities = 8;
 674
 675        err = dpio_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpio_cfg,
 676                          &dflt_dpio->dpio_handle);
 677        if (err < 0) {
 678                printf("dpio_create() failed: %d\n", err);
 679                err = -ENODEV;
 680                goto err_create;
 681        }
 682
 683        memset(&attr, 0, sizeof(struct dpio_attr));
 684        err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
 685                                  dflt_dpio->dpio_handle, &attr);
 686        if (err < 0) {
 687                printf("dpio_get_attributes() failed: %d\n", err);
 688                goto err_get_attr;
 689        }
 690
 691        dflt_dpio->dpio_id = attr.id;
 692#ifdef DEBUG
 693        printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id);
 694#endif
 695
 696        err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
 697        if (err < 0) {
 698                printf("dpio_enable() failed %d\n", err);
 699                goto err_get_enable;
 700        }
 701        debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n",
 702              attr.qbman_portal_ce_offset,
 703              attr.qbman_portal_ci_offset,
 704              attr.qbman_portal_id,
 705              attr.num_priorities);
 706
 707        p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
 708                                        + attr.qbman_portal_ce_offset);
 709        p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
 710                                        + attr.qbman_portal_ci_offset);
 711
 712        dflt_dpio->sw_portal = qbman_swp_init(&p_des);
 713        if (dflt_dpio->sw_portal == NULL) {
 714                printf("qbman_swp_init() failed\n");
 715                goto err_get_swp_init;
 716        }
 717        return 0;
 718
 719err_get_swp_init:
 720        dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
 721err_get_enable:
 722        free(dflt_dpio);
 723err_get_attr:
 724        dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
 725        dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
 726err_create:
 727err_malloc:
 728        return err;
 729}
 730
 731static int dpio_exit(void)
 732{
 733        int err;
 734
 735        err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
 736        if (err < 0) {
 737                printf("dpio_disable() failed: %d\n", err);
 738                goto err;
 739        }
 740
 741        err = dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
 742        if (err < 0) {
 743                printf("dpio_destroy() failed: %d\n", err);
 744                goto err;
 745        }
 746
 747#ifdef DEBUG
 748        printf("Exit: DPIO id=0x%d\n", dflt_dpio->dpio_id);
 749#endif
 750
 751        if (dflt_dpio)
 752                free(dflt_dpio);
 753
 754        return 0;
 755err:
 756        return err;
 757}
 758
 759static int dprc_init(void)
 760{
 761        int err, child_portal_id, container_id;
 762        struct dprc_cfg cfg;
 763        uint64_t mc_portal_offset;
 764
 765        /* Open root container */
 766        err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id);
 767        if (err < 0) {
 768                printf("dprc_get_container_id(): Root failed: %d\n", err);
 769                goto err_root_container_id;
 770        }
 771
 772#ifdef DEBUG
 773        printf("Root container id = %d\n", container_id);
 774#endif
 775        err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id,
 776                        &root_dprc_handle);
 777        if (err < 0) {
 778                printf("dprc_open(): Root Container failed: %d\n", err);
 779                goto err_root_open;
 780        }
 781
 782        if (!root_dprc_handle) {
 783                printf("dprc_open(): Root Container Handle is not valid\n");
 784                goto err_root_open;
 785        }
 786
 787        cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED |
 788                      DPRC_CFG_OPT_OBJ_CREATE_ALLOWED |
 789                      DPRC_CFG_OPT_ALLOC_ALLOWED;
 790        cfg.icid = DPRC_GET_ICID_FROM_POOL;
 791        cfg.portal_id = 250;
 792        err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS,
 793                        root_dprc_handle,
 794                        &cfg,
 795                        &child_dprc_id,
 796                        &mc_portal_offset);
 797        if (err < 0) {
 798                printf("dprc_create_container() failed: %d\n", err);
 799                goto err_create;
 800        }
 801
 802        dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
 803        if (!dflt_mc_io) {
 804                err  = -ENOMEM;
 805                printf(" No memory: malloc() failed\n");
 806                goto err_malloc;
 807        }
 808
 809        child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset);
 810        dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id);
 811#ifdef DEBUG
 812        printf("MC portal of child DPRC container: %d, physical addr %p)\n",
 813               child_dprc_id, dflt_mc_io->mmio_regs);
 814#endif
 815
 816        err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id,
 817                        &dflt_dprc_handle);
 818        if (err < 0) {
 819                printf("dprc_open(): Child container failed: %d\n", err);
 820                goto err_child_open;
 821        }
 822
 823        if (!dflt_dprc_handle) {
 824                printf("dprc_open(): Child container Handle is not valid\n");
 825                goto err_child_open;
 826        }
 827
 828        return 0;
 829err_child_open:
 830        free(dflt_mc_io);
 831err_malloc:
 832        dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
 833                               root_dprc_handle, child_dprc_id);
 834err_create:
 835        dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
 836err_root_open:
 837err_root_container_id:
 838        return err;
 839}
 840
 841static int dprc_exit(void)
 842{
 843        int err;
 844
 845        err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle);
 846        if (err < 0) {
 847                printf("dprc_close(): Child failed: %d\n", err);
 848                goto err;
 849        }
 850
 851        err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
 852                                     root_dprc_handle, child_dprc_id);
 853        if (err < 0) {
 854                printf("dprc_destroy_container() failed: %d\n", err);
 855                goto err;
 856        }
 857
 858        err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
 859        if (err < 0) {
 860                printf("dprc_close(): Root failed: %d\n", err);
 861                goto err;
 862        }
 863
 864        if (dflt_mc_io)
 865                free(dflt_mc_io);
 866
 867        if (root_mc_io)
 868                free(root_mc_io);
 869
 870        return 0;
 871
 872err:
 873        return err;
 874}
 875
 876static int dpbp_init(void)
 877{
 878        int err;
 879        struct dpbp_attr dpbp_attr;
 880        struct dpbp_cfg dpbp_cfg;
 881
 882        dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj));
 883        if (!dflt_dpbp) {
 884                printf("No memory: malloc() failed\n");
 885                err = -ENOMEM;
 886                goto err_malloc;
 887        }
 888
 889        dpbp_cfg.options = 512;
 890
 891        err = dpbp_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpbp_cfg,
 892                          &dflt_dpbp->dpbp_handle);
 893
 894        if (err < 0) {
 895                err = -ENODEV;
 896                printf("dpbp_create() failed: %d\n", err);
 897                goto err_create;
 898        }
 899
 900        memset(&dpbp_attr, 0, sizeof(struct dpbp_attr));
 901        err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
 902                                  dflt_dpbp->dpbp_handle,
 903                                  &dpbp_attr);
 904        if (err < 0) {
 905                printf("dpbp_get_attributes() failed: %d\n", err);
 906                goto err_get_attr;
 907        }
 908
 909        dflt_dpbp->dpbp_attr.id = dpbp_attr.id;
 910#ifdef DEBUG
 911        printf("Init: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
 912#endif
 913
 914        err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
 915        if (err < 0) {
 916                printf("dpbp_close() failed: %d\n", err);
 917                goto err_close;
 918        }
 919
 920        return 0;
 921
 922err_close:
 923        free(dflt_dpbp);
 924err_get_attr:
 925        dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
 926        dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
 927err_create:
 928err_malloc:
 929        return err;
 930}
 931
 932static int dpbp_exit(void)
 933{
 934        int err;
 935
 936        err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
 937                        &dflt_dpbp->dpbp_handle);
 938        if (err < 0) {
 939                printf("dpbp_open() failed: %d\n", err);
 940                goto err;
 941        }
 942
 943        err = dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
 944                           dflt_dpbp->dpbp_handle);
 945        if (err < 0) {
 946                printf("dpbp_destroy() failed: %d\n", err);
 947                goto err;
 948        }
 949
 950#ifdef DEBUG
 951        printf("Exit: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
 952#endif
 953
 954        if (dflt_dpbp)
 955                free(dflt_dpbp);
 956        return 0;
 957
 958err:
 959        return err;
 960}
 961
 962static int dpni_init(void)
 963{
 964        int err;
 965        struct dpni_attr dpni_attr;
 966        struct dpni_cfg dpni_cfg;
 967
 968        dflt_dpni = (struct fsl_dpni_obj *)malloc(sizeof(struct fsl_dpni_obj));
 969        if (!dflt_dpni) {
 970                printf("No memory: malloc() failed\n");
 971                err = -ENOMEM;
 972                goto err_malloc;
 973        }
 974
 975        memset(&dpni_cfg, 0, sizeof(dpni_cfg));
 976        dpni_cfg.adv.options = DPNI_OPT_UNICAST_FILTER |
 977                               DPNI_OPT_MULTICAST_FILTER;
 978
 979        err = dpni_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpni_cfg,
 980                          &dflt_dpni->dpni_handle);
 981
 982        if (err < 0) {
 983                err = -ENODEV;
 984                printf("dpni_create() failed: %d\n", err);
 985                goto err_create;
 986        }
 987
 988        memset(&dpni_attr, 0, sizeof(struct dpni_attr));
 989        err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
 990                                  dflt_dpni->dpni_handle,
 991                                  &dpni_attr);
 992        if (err < 0) {
 993                printf("dpni_get_attributes() failed: %d\n", err);
 994                goto err_get_attr;
 995        }
 996
 997        dflt_dpni->dpni_id = dpni_attr.id;
 998#ifdef DEBUG
 999        printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1000#endif
1001
1002        err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1003        if (err < 0) {
1004                printf("dpni_close() failed: %d\n", err);
1005                goto err_close;
1006        }
1007
1008        return 0;
1009
1010err_close:
1011        free(dflt_dpni);
1012err_get_attr:
1013        dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1014        dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1015err_create:
1016err_malloc:
1017        return err;
1018}
1019
1020static int dpni_exit(void)
1021{
1022        int err;
1023
1024        err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
1025                        &dflt_dpni->dpni_handle);
1026        if (err < 0) {
1027                printf("dpni_open() failed: %d\n", err);
1028                goto err;
1029        }
1030
1031        err = dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
1032                           dflt_dpni->dpni_handle);
1033        if (err < 0) {
1034                printf("dpni_destroy() failed: %d\n", err);
1035                goto err;
1036        }
1037
1038#ifdef DEBUG
1039        printf("Exit: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1040#endif
1041
1042        if (dflt_dpni)
1043                free(dflt_dpni);
1044        return 0;
1045
1046err:
1047        return err;
1048}
1049
1050static int mc_init_object(void)
1051{
1052        int err = 0;
1053
1054        err = dprc_init();
1055        if (err < 0) {
1056                printf("dprc_init() failed: %d\n", err);
1057                goto err;
1058        }
1059
1060        err = dpbp_init();
1061        if (err < 0) {
1062                printf("dpbp_init() failed: %d\n", err);
1063                goto err;
1064        }
1065
1066        err = dpio_init();
1067        if (err < 0) {
1068                printf("dpio_init() failed: %d\n", err);
1069                goto err;
1070        }
1071
1072        err = dpni_init();
1073        if (err < 0) {
1074                printf("dpni_init() failed: %d\n", err);
1075                goto err;
1076        }
1077
1078        return 0;
1079err:
1080        return err;
1081}
1082
1083int fsl_mc_ldpaa_exit(bd_t *bd)
1084{
1085        int err = 0;
1086
1087        if (bd && get_mc_boot_status() == -1)
1088                return 0;
1089
1090        if (bd && !get_mc_boot_status() && get_dpl_apply_status() == -1) {
1091                printf("ERROR: fsl-mc: DPL is not applied\n");
1092                err = -ENODEV;
1093                return err;
1094        }
1095
1096        if (bd && !get_mc_boot_status() && !get_dpl_apply_status())
1097                return err;
1098
1099        err = dpbp_exit();
1100        if (err < 0) {
1101                printf("dpni_exit() failed: %d\n", err);
1102                goto err;
1103        }
1104
1105        err = dpio_exit();
1106        if (err < 0) {
1107                printf("dpio_exit() failed: %d\n", err);
1108                goto err;
1109        }
1110
1111        err = dpni_exit();
1112        if (err < 0) {
1113                printf("dpni_exit() failed: %d\n", err);
1114                goto err;
1115        }
1116
1117        err = dprc_exit();
1118        if (err < 0) {
1119                printf("dprc_exit() failed: %d\n", err);
1120                goto err;
1121        }
1122
1123        return 0;
1124err:
1125        return err;
1126}
1127
1128static int do_fsl_mc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1129{
1130        int err = 0;
1131        if (argc < 3)
1132                goto usage;
1133
1134        switch (argv[1][0]) {
1135        case 's': {
1136                        char sub_cmd;
1137                        u64 mc_fw_addr, mc_dpc_addr;
1138#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1139                        u64 aiop_fw_addr;
1140#endif
1141
1142                        sub_cmd = argv[2][0];
1143                        switch (sub_cmd) {
1144                        case 'm':
1145                                if (argc < 5)
1146                                        goto usage;
1147
1148                                if (get_mc_boot_status() == 0) {
1149                                        printf("fsl-mc: MC is already booted");
1150                                        printf("\n");
1151                                        return err;
1152                                }
1153                                mc_fw_addr = simple_strtoull(argv[3], NULL, 16);
1154                                mc_dpc_addr = simple_strtoull(argv[4], NULL,
1155                                                              16);
1156
1157                                if (!mc_init(mc_fw_addr, mc_dpc_addr))
1158                                        err = mc_init_object();
1159                                break;
1160
1161#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1162                        case 'a':
1163                                if (argc < 4)
1164                                        goto usage;
1165                                if (get_aiop_apply_status() == 0) {
1166                                        printf("fsl-mc: AIOP FW is already");
1167                                        printf(" applied\n");
1168                                        return err;
1169                                }
1170
1171                                aiop_fw_addr = simple_strtoull(argv[3], NULL,
1172                                                               16);
1173
1174                                err = load_mc_aiop_img(aiop_fw_addr);
1175                                if (!err)
1176                                        printf("fsl-mc: AIOP FW applied\n");
1177                                break;
1178#endif
1179                        default:
1180                                printf("Invalid option: %s\n", argv[2]);
1181                                goto usage;
1182
1183                                break;
1184                        }
1185                }
1186                break;
1187
1188        case 'a': {
1189                        u64 mc_dpl_addr;
1190
1191                        if (argc < 4)
1192                                goto usage;
1193
1194                        if (get_dpl_apply_status() == 0) {
1195                                printf("fsl-mc: DPL already applied\n");
1196                                return err;
1197                        }
1198
1199                        mc_dpl_addr = simple_strtoull(argv[3], NULL,
1200                                                              16);
1201
1202                        if (get_mc_boot_status() != 0) {
1203                                printf("fsl-mc: Deploying data path layout ..");
1204                                printf("ERROR (MC is not booted)\n");
1205                                return -ENODEV;
1206                        }
1207
1208                        if (!fsl_mc_ldpaa_exit(NULL))
1209                                err = mc_apply_dpl(mc_dpl_addr);
1210                        break;
1211                }
1212        default:
1213                printf("Invalid option: %s\n", argv[1]);
1214                goto usage;
1215                break;
1216        }
1217        return err;
1218 usage:
1219        return CMD_RET_USAGE;
1220}
1221
1222U_BOOT_CMD(
1223        fsl_mc,  CONFIG_SYS_MAXARGS,  1,   do_fsl_mc,
1224        "DPAA2 command to manage Management Complex (MC)",
1225        "start mc [FW_addr] [DPC_addr] - Start Management Complex\n"
1226        "fsl_mc apply DPL [DPL_addr] - Apply DPL file\n"
1227        "fsl_mc start aiop [FW_addr] - Start AIOP\n"
1228);
1229