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