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