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