]> git.sur5r.net Git - u-boot/blob - drivers/net/fsl-mc/mc.c
Merge git://git.denx.de/u-boot-fsl-qoriq
[u-boot] / drivers / net / fsl-mc / mc.c
1 /*
2  * Copyright (C) 2017 NXP Semiconductors
3  * Copyright (C) 2014 Freescale Semiconductor
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7 #include <common.h>
8 #include <errno.h>
9 #include <linux/bug.h>
10 #include <asm/io.h>
11 #include <libfdt.h>
12 #include <net.h>
13 #include <fdt_support.h>
14 #include <fsl-mc/fsl_mc.h>
15 #include <fsl-mc/fsl_mc_sys.h>
16 #include <fsl-mc/fsl_mc_private.h>
17 #include <fsl-mc/fsl_dpmng.h>
18 #include <fsl-mc/fsl_dprc.h>
19 #include <fsl-mc/fsl_dpio.h>
20 #include <fsl-mc/fsl_dpni.h>
21 #include <fsl-mc/fsl_qbman_portal.h>
22 #include <fsl-mc/ldpaa_wriop.h>
23
24 #define MC_RAM_BASE_ADDR_ALIGNMENT  (512UL * 1024 * 1024)
25 #define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1))
26 #define MC_RAM_SIZE_ALIGNMENT       (256UL * 1024 * 1024)
27
28 #define MC_MEM_SIZE_ENV_VAR     "mcmemsize"
29 #define MC_BOOT_TIMEOUT_ENV_VAR "mcboottimeout"
30 #define MC_BOOT_ENV_VAR         "mcinitcmd"
31
32 DECLARE_GLOBAL_DATA_PTR;
33 static int mc_boot_status = -1;
34 static int mc_dpl_applied = -1;
35 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
36 static int mc_aiop_applied = -1;
37 #endif
38 struct fsl_mc_io *root_mc_io = NULL;
39 struct fsl_mc_io *dflt_mc_io = NULL; /* child container */
40 uint16_t root_dprc_handle = 0;
41 uint16_t dflt_dprc_handle = 0;
42 int child_dprc_id;
43 struct fsl_dpbp_obj *dflt_dpbp = NULL;
44 struct fsl_dpio_obj *dflt_dpio = NULL;
45 struct fsl_dpni_obj *dflt_dpni = NULL;
46 static u64 mc_lazy_dpl_addr;
47
48 #ifdef DEBUG
49 void dump_ram_words(const char *title, void *addr)
50 {
51         int i;
52         uint32_t *words = addr;
53
54         printf("Dumping beginning of %s (%p):\n", title, addr);
55         for (i = 0; i < 16; i++)
56                 printf("%#x ", words[i]);
57
58         printf("\n");
59 }
60
61 void dump_mc_ccsr_regs(struct mc_ccsr_registers __iomem *mc_ccsr_regs)
62 {
63         printf("MC CCSR registers:\n"
64                 "reg_gcr1 %#x\n"
65                 "reg_gsr %#x\n"
66                 "reg_sicbalr %#x\n"
67                 "reg_sicbahr %#x\n"
68                 "reg_sicapr %#x\n"
69                 "reg_mcfbalr %#x\n"
70                 "reg_mcfbahr %#x\n"
71                 "reg_mcfapr %#x\n"
72                 "reg_psr %#x\n",
73                 mc_ccsr_regs->reg_gcr1,
74                 mc_ccsr_regs->reg_gsr,
75                 mc_ccsr_regs->reg_sicbalr,
76                 mc_ccsr_regs->reg_sicbahr,
77                 mc_ccsr_regs->reg_sicapr,
78                 mc_ccsr_regs->reg_mcfbalr,
79                 mc_ccsr_regs->reg_mcfbahr,
80                 mc_ccsr_regs->reg_mcfapr,
81                 mc_ccsr_regs->reg_psr);
82 }
83 #else
84
85 #define dump_ram_words(title, addr)
86 #define dump_mc_ccsr_regs(mc_ccsr_regs)
87
88 #endif /* DEBUG */
89
90 #ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
91 /**
92  * Copying MC firmware or DPL image to DDR
93  */
94 static int mc_copy_image(const char *title,
95                          u64 image_addr, u32 image_size, u64 mc_ram_addr)
96 {
97         debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
98         memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
99         flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size);
100         return 0;
101 }
102
103 /**
104  * MC firmware FIT image parser checks if the image is in FIT
105  * format, verifies integrity of the image and calculates
106  * raw image address and size values.
107  * Returns 0 on success and a negative errno on error.
108  * task fail.
109  **/
110 int parse_mc_firmware_fit_image(u64 mc_fw_addr,
111                                 const void **raw_image_addr,
112                                 size_t *raw_image_size)
113 {
114         int format;
115         void *fit_hdr;
116         int node_offset;
117         const void *data;
118         size_t size;
119         const char *uname = "firmware";
120
121         fit_hdr = (void *)mc_fw_addr;
122
123         /* Check if Image is in FIT format */
124         format = genimg_get_format(fit_hdr);
125
126         if (format != IMAGE_FORMAT_FIT) {
127                 printf("fsl-mc: ERR: Bad firmware image (not a FIT image)\n");
128                 return -EINVAL;
129         }
130
131         if (!fit_check_format(fit_hdr)) {
132                 printf("fsl-mc: ERR: Bad firmware image (bad FIT header)\n");
133                 return -EINVAL;
134         }
135
136         node_offset = fit_image_get_node(fit_hdr, uname);
137
138         if (node_offset < 0) {
139                 printf("fsl-mc: ERR: Bad firmware image (missing subimage)\n");
140                 return -ENOENT;
141         }
142
143         /* Verify MC firmware image */
144         if (!(fit_image_verify(fit_hdr, node_offset))) {
145                 printf("fsl-mc: ERR: Bad firmware image (bad CRC)\n");
146                 return -EINVAL;
147         }
148
149         /* Get address and size of raw image */
150         fit_image_get_data(fit_hdr, node_offset, &data, &size);
151
152         *raw_image_addr = data;
153         *raw_image_size = size;
154
155         return 0;
156 }
157 #endif
158
159 #define MC_DT_INCREASE_SIZE     64
160
161 enum mc_fixup_type {
162         MC_FIXUP_DPL,
163         MC_FIXUP_DPC
164 };
165
166 static int mc_fixup_mac_addr(void *blob, int nodeoffset,
167                              const char *propname, struct eth_device *eth_dev,
168                              enum mc_fixup_type type)
169 {
170         int err = 0, len = 0, size, i;
171         unsigned char env_enetaddr[ARP_HLEN];
172         unsigned int enetaddr_32[ARP_HLEN];
173         void *val = NULL;
174
175         switch (type) {
176         case MC_FIXUP_DPL:
177         /* DPL likes its addresses on 32 * ARP_HLEN bits */
178         for (i = 0; i < ARP_HLEN; i++)
179                 enetaddr_32[i] = cpu_to_fdt32(eth_dev->enetaddr[i]);
180         val = enetaddr_32;
181         len = sizeof(enetaddr_32);
182         break;
183
184         case MC_FIXUP_DPC:
185         val = eth_dev->enetaddr;
186         len = ARP_HLEN;
187         break;
188         }
189
190         /* MAC address property present */
191         if (fdt_get_property(blob, nodeoffset, propname, NULL)) {
192                 /* u-boot MAC addr randomly assigned - leave the present one */
193                 if (!eth_env_get_enetaddr_by_index("eth", eth_dev->index,
194                                                    env_enetaddr))
195                         return err;
196         } else {
197                 size = MC_DT_INCREASE_SIZE + strlen(propname) + len;
198                 /* make room for mac address property */
199                 err = fdt_increase_size(blob, size);
200                 if (err) {
201                         printf("fdt_increase_size: err=%s\n",
202                                fdt_strerror(err));
203                         return err;
204                 }
205         }
206
207         err = fdt_setprop(blob, nodeoffset, propname, val, len);
208         if (err) {
209                 printf("fdt_setprop: err=%s\n", fdt_strerror(err));
210                 return err;
211         }
212
213         return err;
214 }
215
216 #define is_dpni(s) (s != NULL ? !strncmp(s, "dpni@", 5) : 0)
217
218 const char *dpl_get_connection_endpoint(void *blob, char *endpoint)
219 {
220         int connoffset = fdt_path_offset(blob, "/connections"), off;
221         const char *s1, *s2;
222
223         for (off = fdt_first_subnode(blob, connoffset);
224              off >= 0;
225              off = fdt_next_subnode(blob, off)) {
226                 s1 = fdt_stringlist_get(blob, off, "endpoint1", 0, NULL);
227                 s2 = fdt_stringlist_get(blob, off, "endpoint2", 0, NULL);
228
229                 if (!s1 || !s2)
230                         continue;
231
232                 if (strcmp(endpoint, s1) == 0)
233                         return s2;
234
235                 if (strcmp(endpoint, s2) == 0)
236                         return s1;
237         }
238
239         return NULL;
240 }
241
242 static int mc_fixup_dpl_mac_addr(void *blob, int dpmac_id,
243                                  struct eth_device *eth_dev)
244 {
245         int objoff = fdt_path_offset(blob, "/objects");
246         int dpmacoff = -1, dpnioff = -1;
247         const char *endpoint;
248         char mac_name[10];
249         int err;
250
251         sprintf(mac_name, "dpmac@%d", dpmac_id);
252         dpmacoff = fdt_subnode_offset(blob, objoff, mac_name);
253         if (dpmacoff < 0)
254                 /* dpmac not defined in DPL, so skip it. */
255                 return 0;
256
257         err = mc_fixup_mac_addr(blob, dpmacoff, "mac_addr", eth_dev,
258                                 MC_FIXUP_DPL);
259         if (err) {
260                 printf("Error fixing up dpmac mac_addr in DPL\n");
261                 return err;
262         }
263
264         /* now we need to figure out if there is any
265          * DPNI connected to this MAC, so we walk the
266          * connection list
267          */
268         endpoint = dpl_get_connection_endpoint(blob, mac_name);
269         if (!is_dpni(endpoint))
270                 return 0;
271
272         /* let's see if we can fixup the DPNI as well */
273         dpnioff = fdt_subnode_offset(blob, objoff, endpoint);
274         if (dpnioff < 0)
275                 /* DPNI not defined in DPL in the objects area */
276                 return 0;
277
278         return mc_fixup_mac_addr(blob, dpnioff, "mac_addr", eth_dev,
279                                  MC_FIXUP_DPL);
280 }
281
282 static int mc_fixup_dpc_mac_addr(void *blob, int dpmac_id,
283                                  struct eth_device *eth_dev)
284 {
285         int nodeoffset = fdt_path_offset(blob, "/board_info/ports"), noff;
286         int err = 0;
287         char mac_name[10];
288         const char link_type_mode[] = "MAC_LINK_TYPE_FIXED";
289
290         sprintf(mac_name, "mac@%d", dpmac_id);
291
292         /* node not found - create it */
293         noff = fdt_subnode_offset(blob, nodeoffset, (const char *)mac_name);
294         if (noff < 0) {
295                 err = fdt_increase_size(blob, 200);
296                 if (err) {
297                         printf("fdt_increase_size: err=%s\n",
298                                 fdt_strerror(err));
299                         return err;
300                 }
301
302                 noff = fdt_add_subnode(blob, nodeoffset, mac_name);
303                 if (noff < 0) {
304                         printf("fdt_add_subnode: err=%s\n",
305                                fdt_strerror(err));
306                         return err;
307                 }
308
309                 /* add default property of fixed link */
310                 err = fdt_appendprop_string(blob, noff,
311                                             "link_type", link_type_mode);
312                 if (err) {
313                         printf("fdt_appendprop_string: err=%s\n",
314                                 fdt_strerror(err));
315                         return err;
316                 }
317         }
318
319         return mc_fixup_mac_addr(blob, noff, "port_mac_address", eth_dev,
320                                  MC_FIXUP_DPC);
321 }
322
323 static int mc_fixup_mac_addrs(void *blob, enum mc_fixup_type type)
324 {
325         int i, err = 0, ret = 0;
326         char ethname[10];
327         struct eth_device *eth_dev;
328
329         for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
330                 /* port not enabled */
331                 if ((wriop_is_enabled_dpmac(i) != 1) ||
332                     (wriop_get_phy_address(i) == -1))
333                         continue;
334
335                 sprintf(ethname, "DPMAC%d@%s", i,
336                         phy_interface_strings[wriop_get_enet_if(i)]);
337
338                 eth_dev = eth_get_dev_by_name(ethname);
339                 if (eth_dev == NULL)
340                         continue;
341
342                 switch (type) {
343                 case MC_FIXUP_DPL:
344                         err = mc_fixup_dpl_mac_addr(blob, i, eth_dev);
345                         break;
346                 case MC_FIXUP_DPC:
347                         err = mc_fixup_dpc_mac_addr(blob, i, eth_dev);
348                         break;
349                 default:
350                         break;
351                 }
352
353                 if (err)
354                         printf("fsl-mc: ERROR fixing mac address for %s\n",
355                                ethname);
356                 ret |= err;
357         }
358
359         return ret;
360 }
361
362 static int mc_fixup_dpc(u64 dpc_addr)
363 {
364         void *blob = (void *)dpc_addr;
365         int nodeoffset, err = 0;
366
367         /* delete any existing ICID pools */
368         nodeoffset = fdt_path_offset(blob, "/resources/icid_pools");
369         if (fdt_del_node(blob, nodeoffset) < 0)
370                 printf("\nfsl-mc: WARNING: could not delete ICID pool\n");
371
372         /* add a new pool */
373         nodeoffset = fdt_path_offset(blob, "/resources");
374         if (nodeoffset < 0) {
375                 printf("\nfsl-mc: ERROR: DPC is missing /resources\n");
376                 return -EINVAL;
377         }
378         nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pools");
379         nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pool@0");
380         do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
381                              "base_icid", FSL_DPAA2_STREAM_ID_START, 1);
382         do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
383                              "num",
384                              FSL_DPAA2_STREAM_ID_END -
385                              FSL_DPAA2_STREAM_ID_START + 1, 1);
386
387         /* fixup MAC addresses for dpmac ports */
388         nodeoffset = fdt_path_offset(blob, "/board_info/ports");
389         if (nodeoffset < 0)
390                 return 0;
391
392         err = mc_fixup_mac_addrs(blob, MC_FIXUP_DPC);
393         flush_dcache_range(dpc_addr, dpc_addr + fdt_totalsize(blob));
394
395         return err;
396 }
397
398 static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpc_addr)
399 {
400         u64 mc_dpc_offset;
401 #ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
402         int error;
403         void *dpc_fdt_hdr;
404         int dpc_size;
405 #endif
406
407 #ifdef CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET
408         BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET & 0x3) != 0 ||
409                      CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET > 0xffffffff);
410
411         mc_dpc_offset = CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET;
412 #else
413 #error "CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET not defined"
414 #endif
415
416         /*
417          * Load the MC DPC blob in the MC private DRAM block:
418          */
419 #ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
420         printf("MC DPC is preloaded to %#llx\n", mc_ram_addr + mc_dpc_offset);
421 #else
422         /*
423          * Get address and size of the DPC blob stored in flash:
424          */
425         dpc_fdt_hdr = (void *)mc_dpc_addr;
426
427         error = fdt_check_header(dpc_fdt_hdr);
428         if (error != 0) {
429                 /*
430                  * Don't return with error here, since the MC firmware can
431                  * still boot without a DPC
432                  */
433                 printf("\nfsl-mc: WARNING: No DPC image found");
434                 return 0;
435         }
436
437         dpc_size = fdt_totalsize(dpc_fdt_hdr);
438         if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) {
439                 printf("\nfsl-mc: ERROR: Bad DPC image (too large: %d)\n",
440                        dpc_size);
441                 return -EINVAL;
442         }
443
444         mc_copy_image("MC DPC blob",
445                       (u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset);
446 #endif /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */
447
448         if (mc_fixup_dpc(mc_ram_addr + mc_dpc_offset))
449                 return -EINVAL;
450
451         dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset));
452         return 0;
453 }
454
455
456 static int mc_fixup_dpl(u64 dpl_addr)
457 {
458         void *blob = (void *)dpl_addr;
459         u32 ver = fdt_getprop_u32_default(blob, "/", "dpl-version", 0);
460         int err = 0;
461
462         /* The DPL fixup for mac addresses is only relevant
463          * for old-style DPLs
464          */
465         if (ver >= 10)
466                 return 0;
467
468         err = mc_fixup_mac_addrs(blob, MC_FIXUP_DPL);
469         flush_dcache_range(dpl_addr, dpl_addr + fdt_totalsize(blob));
470
471         return err;
472 }
473
474 static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpl_addr)
475 {
476         u64 mc_dpl_offset;
477 #ifndef CONFIG_SYS_LS_MC_DPL_IN_DDR
478         int error;
479         void *dpl_fdt_hdr;
480         int dpl_size;
481 #endif
482
483 #ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
484         BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
485                      CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
486
487         mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
488 #else
489 #error "CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET not defined"
490 #endif
491
492         /*
493          * Load the MC DPL blob in the MC private DRAM block:
494          */
495 #ifdef CONFIG_SYS_LS_MC_DPL_IN_DDR
496         printf("MC DPL is preloaded to %#llx\n", mc_ram_addr + mc_dpl_offset);
497 #else
498         /*
499          * Get address and size of the DPL blob stored in flash:
500          */
501         dpl_fdt_hdr = (void *)mc_dpl_addr;
502
503         error = fdt_check_header(dpl_fdt_hdr);
504         if (error != 0) {
505                 printf("\nfsl-mc: ERROR: Bad DPL image (bad header)\n");
506                 return error;
507         }
508
509         dpl_size = fdt_totalsize(dpl_fdt_hdr);
510         if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
511                 printf("\nfsl-mc: ERROR: Bad DPL image (too large: %d)\n",
512                        dpl_size);
513                 return -EINVAL;
514         }
515
516         mc_copy_image("MC DPL blob",
517                       (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
518 #endif /* not defined CONFIG_SYS_LS_MC_DPL_IN_DDR */
519
520         if (mc_fixup_dpl(mc_ram_addr + mc_dpl_offset))
521                 return -EINVAL;
522         dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset));
523         return 0;
524 }
525
526 /**
527  * Return the MC boot timeout value in milliseconds
528  */
529 static unsigned long get_mc_boot_timeout_ms(void)
530 {
531         unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
532
533         char *timeout_ms_env_var = env_get(MC_BOOT_TIMEOUT_ENV_VAR);
534
535         if (timeout_ms_env_var) {
536                 timeout_ms = simple_strtoul(timeout_ms_env_var, NULL, 10);
537                 if (timeout_ms == 0) {
538                         printf("fsl-mc: WARNING: Invalid value for \'"
539                                MC_BOOT_TIMEOUT_ENV_VAR
540                                "\' environment variable: %lu\n",
541                                timeout_ms);
542
543                         timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
544                 }
545         }
546
547         return timeout_ms;
548 }
549
550 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
551
552 __weak bool soc_has_aiop(void)
553 {
554         return false;
555 }
556
557 static int load_mc_aiop_img(u64 aiop_fw_addr)
558 {
559         u64 mc_ram_addr = mc_get_dram_addr();
560 #ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
561         void *aiop_img;
562 #endif
563
564         /* Check if AIOP is available */
565         if (!soc_has_aiop())
566                 return -ENODEV;
567         /*
568          * Load the MC AIOP image in the MC private DRAM block:
569          */
570
571 #ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
572         printf("MC AIOP is preloaded to %#llx\n", mc_ram_addr +
573                CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
574 #else
575         aiop_img = (void *)aiop_fw_addr;
576         mc_copy_image("MC AIOP image",
577                       (u64)aiop_img, CONFIG_SYS_LS_MC_AIOP_IMG_MAX_LENGTH,
578                       mc_ram_addr + CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
579 #endif
580         mc_aiop_applied = 0;
581
582         return 0;
583 }
584 #endif
585
586 static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr)
587 {
588         u32 reg_gsr;
589         u32 mc_fw_boot_status;
590         unsigned long timeout_ms = get_mc_boot_timeout_ms();
591         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
592
593         dmb();
594         assert(timeout_ms > 0);
595         for (;;) {
596                 udelay(1000);   /* throttle polling */
597                 reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
598                 mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
599                 if (mc_fw_boot_status & 0x1)
600                         break;
601
602                 timeout_ms--;
603                 if (timeout_ms == 0)
604                         break;
605         }
606
607         if (timeout_ms == 0) {
608                 printf("ERROR: timeout\n");
609
610                 /* TODO: Get an error status from an MC CCSR register */
611                 return -ETIMEDOUT;
612         }
613
614         if (mc_fw_boot_status != 0x1) {
615                 /*
616                  * TODO: Identify critical errors from the GSR register's FS
617                  * field and for those errors, set error to -ENODEV or other
618                  * appropriate errno, so that the status property is set to
619                  * failure in the fsl,dprc device tree node.
620                  */
621                 printf("WARNING: Firmware returned an error (GSR: %#x)\n",
622                        reg_gsr);
623         } else {
624                 printf("SUCCESS\n");
625         }
626
627
628         *final_reg_gsr = reg_gsr;
629         return 0;
630 }
631
632 int mc_init(u64 mc_fw_addr, u64 mc_dpc_addr)
633 {
634         int error = 0;
635         int portal_id = 0;
636         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
637         u64 mc_ram_addr = mc_get_dram_addr();
638         u32 reg_gsr;
639         u32 reg_mcfbalr;
640 #ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
641         const void *raw_image_addr;
642         size_t raw_image_size = 0;
643 #endif
644         struct mc_version mc_ver_info;
645         u8 mc_ram_num_256mb_blocks;
646         size_t mc_ram_size = mc_get_dram_block_size();
647
648         mc_ram_num_256mb_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT;
649         if (mc_ram_num_256mb_blocks < 1 || mc_ram_num_256mb_blocks > 0xff) {
650                 error = -EINVAL;
651                 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
652                        mc_ram_size);
653                 goto out;
654         }
655
656         /*
657          * Management Complex cores should be held at reset out of POR.
658          * U-Boot should be the first software to touch MC. To be safe,
659          * we reset all cores again by setting GCR1 to 0. It doesn't do
660          * anything if they are held at reset. After we setup the firmware
661          * we kick off MC by deasserting the reset bit for core 0, and
662          * deasserting the reset bits for Command Portal Managers.
663          * The stop bits are not touched here. They are used to stop the
664          * cores when they are active. Setting stop bits doesn't stop the
665          * cores from fetching instructions when they are released from
666          * reset.
667          */
668         out_le32(&mc_ccsr_regs->reg_gcr1, 0);
669         dmb();
670
671 #ifdef CONFIG_SYS_LS_MC_FW_IN_DDR
672         printf("MC firmware is preloaded to %#llx\n", mc_ram_addr);
673 #else
674         error = parse_mc_firmware_fit_image(mc_fw_addr, &raw_image_addr,
675                                             &raw_image_size);
676         if (error != 0)
677                 goto out;
678         /*
679          * Load the MC FW at the beginning of the MC private DRAM block:
680          */
681         mc_copy_image("MC Firmware",
682                       (u64)raw_image_addr, raw_image_size, mc_ram_addr);
683 #endif
684         dump_ram_words("firmware", (void *)mc_ram_addr);
685
686         error = load_mc_dpc(mc_ram_addr, mc_ram_size, mc_dpc_addr);
687         if (error != 0)
688                 goto out;
689
690         debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
691         dump_mc_ccsr_regs(mc_ccsr_regs);
692
693         /*
694          * Tell MC what is the address range of the DRAM block assigned to it:
695          */
696         reg_mcfbalr = (u32)mc_ram_addr |
697                       (mc_ram_num_256mb_blocks - 1);
698         out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr);
699         out_le32(&mc_ccsr_regs->reg_mcfbahr,
700                  (u32)(mc_ram_addr >> 32));
701         out_le32(&mc_ccsr_regs->reg_mcfapr, FSL_BYPASS_AMQ);
702
703         /*
704          * Tell the MC that we want delayed DPL deployment.
705          */
706         out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00);
707
708         printf("\nfsl-mc: Booting Management Complex ... ");
709
710         /*
711          * Deassert reset and release MC core 0 to run
712          */
713         out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
714         error = wait_for_mc(true, &reg_gsr);
715         if (error != 0)
716                 goto out;
717
718         /*
719          * TODO: need to obtain the portal_id for the root container from the
720          * DPL
721          */
722         portal_id = 0;
723
724         /*
725          * Initialize the global default MC portal
726          * And check that the MC firmware is responding portal commands:
727          */
728         root_mc_io = (struct fsl_mc_io *)calloc(sizeof(struct fsl_mc_io), 1);
729         if (!root_mc_io) {
730                 printf(" No memory: calloc() failed\n");
731                 return -ENOMEM;
732         }
733
734         root_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
735         debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
736               portal_id, root_mc_io->mmio_regs);
737
738         error = mc_get_version(root_mc_io, MC_CMD_NO_FLAGS, &mc_ver_info);
739         if (error != 0) {
740                 printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n",
741                        error);
742                 goto out;
743         }
744
745         printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n",
746                mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision,
747                reg_gsr & GSR_FS_MASK);
748
749 out:
750         if (error != 0)
751                 mc_boot_status = error;
752         else
753                 mc_boot_status = 0;
754
755         return error;
756 }
757
758 int mc_apply_dpl(u64 mc_dpl_addr)
759 {
760         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
761         int error = 0;
762         u32 reg_gsr;
763         u64 mc_ram_addr = mc_get_dram_addr();
764         size_t mc_ram_size = mc_get_dram_block_size();
765
766         if (!mc_dpl_addr)
767                 return -1;
768
769         error = load_mc_dpl(mc_ram_addr, mc_ram_size, mc_dpl_addr);
770         if (error != 0)
771                 return error;
772
773         /*
774          * Tell the MC to deploy the DPL:
775          */
776         out_le32(&mc_ccsr_regs->reg_gsr, 0x0);
777         printf("fsl-mc: Deploying data path layout ... ");
778         error = wait_for_mc(false, &reg_gsr);
779
780         if (!error)
781                 mc_dpl_applied = 0;
782
783         return error;
784 }
785
786 int get_mc_boot_status(void)
787 {
788         return mc_boot_status;
789 }
790
791 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
792 int get_aiop_apply_status(void)
793 {
794         return mc_aiop_applied;
795 }
796 #endif
797
798 int get_dpl_apply_status(void)
799 {
800         return mc_dpl_applied;
801 }
802
803 /*
804  * Return the MC address of private DRAM block.
805  * As per MC design document, MC initial base address
806  * should be least significant 512MB address of MC private
807  * memory, i.e. address should point to end address masked
808  * with 512MB offset in private DRAM block.
809  */
810 u64 mc_get_dram_addr(void)
811 {
812         size_t mc_ram_size = mc_get_dram_block_size();
813
814         return (gd->arch.resv_ram + mc_ram_size - 1) &
815                 MC_RAM_BASE_ADDR_ALIGNMENT_MASK;
816 }
817
818 /**
819  * Return the actual size of the MC private DRAM block.
820  */
821 unsigned long mc_get_dram_block_size(void)
822 {
823         unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
824
825         char *dram_block_size_env_var = env_get(MC_MEM_SIZE_ENV_VAR);
826
827         if (dram_block_size_env_var) {
828                 dram_block_size = simple_strtoul(dram_block_size_env_var, NULL,
829                                                  10);
830
831                 if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
832                         printf("fsl-mc: WARNING: Invalid value for \'"
833                                MC_MEM_SIZE_ENV_VAR
834                                "\' environment variable: %lu\n",
835                                dram_block_size);
836
837                         dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
838                 }
839         }
840
841         return dram_block_size;
842 }
843
844 int fsl_mc_ldpaa_init(bd_t *bis)
845 {
846         int i;
847
848         for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++)
849                 if ((wriop_is_enabled_dpmac(i) == 1) &&
850                     (wriop_get_phy_address(i) != -1))
851                         ldpaa_eth_init(i, wriop_get_enet_if(i));
852         return 0;
853 }
854
855 static int dprc_version_check(struct fsl_mc_io *mc_io, uint16_t handle)
856 {
857         struct dprc_attributes attr;
858         int error;
859
860         memset(&attr, 0, sizeof(struct dprc_attributes));
861         error = dprc_get_attributes(mc_io, MC_CMD_NO_FLAGS, handle, &attr);
862         if (error == 0) {
863                 if ((attr.version.major != DPRC_VER_MAJOR) ||
864                     (attr.version.minor != DPRC_VER_MINOR)) {
865                         printf("DPRC version mismatch found %u.%u,",
866                                attr.version.major,
867                                attr.version.minor);
868                         printf("supported version is %u.%u\n",
869                                DPRC_VER_MAJOR, DPRC_VER_MINOR);
870                 }
871         }
872         return error;
873 }
874
875 static int dpio_init(void)
876 {
877         struct qbman_swp_desc p_des;
878         struct dpio_attr attr;
879         struct dpio_cfg dpio_cfg;
880         int err = 0;
881
882         dflt_dpio = (struct fsl_dpio_obj *)calloc(
883                                         sizeof(struct fsl_dpio_obj), 1);
884         if (!dflt_dpio) {
885                 printf("No memory: calloc() failed\n");
886                 err = -ENOMEM;
887                 goto err_calloc;
888         }
889
890         dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL;
891         dpio_cfg.num_priorities = 8;
892
893         err = dpio_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpio_cfg,
894                           &dflt_dpio->dpio_handle);
895         if (err < 0) {
896                 printf("dpio_create() failed: %d\n", err);
897                 err = -ENODEV;
898                 goto err_create;
899         }
900
901         memset(&attr, 0, sizeof(struct dpio_attr));
902         err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
903                                   dflt_dpio->dpio_handle, &attr);
904         if (err < 0) {
905                 printf("dpio_get_attributes() failed: %d\n", err);
906                 goto err_get_attr;
907         }
908
909         if ((attr.version.major != DPIO_VER_MAJOR) ||
910             (attr.version.minor != DPIO_VER_MINOR)) {
911                 printf("DPIO version mismatch found %u.%u,",
912                        attr.version.major, attr.version.minor);
913                 printf("supported version is %u.%u\n",
914                        DPIO_VER_MAJOR, DPIO_VER_MINOR);
915         }
916
917         dflt_dpio->dpio_id = attr.id;
918 #ifdef DEBUG
919         printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id);
920 #endif
921         err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
922         if (err < 0) {
923                 printf("dpio_enable() failed %d\n", err);
924                 goto err_get_enable;
925         }
926         debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n",
927               attr.qbman_portal_ce_offset,
928               attr.qbman_portal_ci_offset,
929               attr.qbman_portal_id,
930               attr.num_priorities);
931
932         p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
933                                         + attr.qbman_portal_ce_offset);
934         p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
935                                         + attr.qbman_portal_ci_offset);
936
937         dflt_dpio->sw_portal = qbman_swp_init(&p_des);
938         if (dflt_dpio->sw_portal == NULL) {
939                 printf("qbman_swp_init() failed\n");
940                 goto err_get_swp_init;
941         }
942         return 0;
943
944 err_get_swp_init:
945         dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
946 err_get_enable:
947 err_get_attr:
948         dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
949         dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
950 err_create:
951         free(dflt_dpio);
952 err_calloc:
953         return err;
954 }
955
956 static int dpio_exit(void)
957 {
958         int err;
959
960         err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
961         if (err < 0) {
962                 printf("dpio_disable() failed: %d\n", err);
963                 goto err;
964         }
965
966         err = dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
967         if (err < 0) {
968                 printf("dpio_destroy() failed: %d\n", err);
969                 goto err;
970         }
971
972 #ifdef DEBUG
973         printf("Exit: DPIO id=0x%d\n", dflt_dpio->dpio_id);
974 #endif
975
976         if (dflt_dpio)
977                 free(dflt_dpio);
978
979         return 0;
980 err:
981         return err;
982 }
983
984 static int dprc_init(void)
985 {
986         int err, child_portal_id, container_id;
987         struct dprc_cfg cfg;
988         uint64_t mc_portal_offset;
989
990         /* Open root container */
991         err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id);
992         if (err < 0) {
993                 printf("dprc_get_container_id(): Root failed: %d\n", err);
994                 goto err_root_container_id;
995         }
996
997 #ifdef DEBUG
998         printf("Root container id = %d\n", container_id);
999 #endif
1000         err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id,
1001                         &root_dprc_handle);
1002         if (err < 0) {
1003                 printf("dprc_open(): Root Container failed: %d\n", err);
1004                 goto err_root_open;
1005         }
1006
1007         if (!root_dprc_handle) {
1008                 printf("dprc_open(): Root Container Handle is not valid\n");
1009                 goto err_root_open;
1010         }
1011
1012         err = dprc_version_check(root_mc_io, root_dprc_handle);
1013         if (err < 0) {
1014                 printf("dprc_version_check() failed: %d\n", err);
1015                 goto err_root_open;
1016         }
1017
1018         memset(&cfg, 0, sizeof(struct dprc_cfg));
1019         cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED |
1020                       DPRC_CFG_OPT_OBJ_CREATE_ALLOWED |
1021                       DPRC_CFG_OPT_ALLOC_ALLOWED;
1022         cfg.icid = DPRC_GET_ICID_FROM_POOL;
1023         cfg.portal_id = DPRC_GET_PORTAL_ID_FROM_POOL;
1024         err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS,
1025                         root_dprc_handle,
1026                         &cfg,
1027                         &child_dprc_id,
1028                         &mc_portal_offset);
1029         if (err < 0) {
1030                 printf("dprc_create_container() failed: %d\n", err);
1031                 goto err_create;
1032         }
1033
1034         dflt_mc_io = (struct fsl_mc_io *)calloc(sizeof(struct fsl_mc_io), 1);
1035         if (!dflt_mc_io) {
1036                 err  = -ENOMEM;
1037                 printf(" No memory: calloc() failed\n");
1038                 goto err_calloc;
1039         }
1040
1041         child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset);
1042         dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id);
1043 #ifdef DEBUG
1044         printf("MC portal of child DPRC container: %d, physical addr %p)\n",
1045                child_dprc_id, dflt_mc_io->mmio_regs);
1046 #endif
1047
1048         err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id,
1049                         &dflt_dprc_handle);
1050         if (err < 0) {
1051                 printf("dprc_open(): Child container failed: %d\n", err);
1052                 goto err_child_open;
1053         }
1054
1055         if (!dflt_dprc_handle) {
1056                 printf("dprc_open(): Child container Handle is not valid\n");
1057                 goto err_child_open;
1058         }
1059
1060         return 0;
1061 err_child_open:
1062         free(dflt_mc_io);
1063 err_calloc:
1064         dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
1065                                root_dprc_handle, child_dprc_id);
1066 err_create:
1067         dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
1068 err_root_open:
1069 err_root_container_id:
1070         return err;
1071 }
1072
1073 static int dprc_exit(void)
1074 {
1075         int err;
1076
1077         err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle);
1078         if (err < 0) {
1079                 printf("dprc_close(): Child failed: %d\n", err);
1080                 goto err;
1081         }
1082
1083         err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
1084                                      root_dprc_handle, child_dprc_id);
1085         if (err < 0) {
1086                 printf("dprc_destroy_container() failed: %d\n", err);
1087                 goto err;
1088         }
1089
1090         err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
1091         if (err < 0) {
1092                 printf("dprc_close(): Root failed: %d\n", err);
1093                 goto err;
1094         }
1095
1096         if (dflt_mc_io)
1097                 free(dflt_mc_io);
1098
1099         if (root_mc_io)
1100                 free(root_mc_io);
1101
1102         return 0;
1103
1104 err:
1105         return err;
1106 }
1107
1108 static int dpbp_init(void)
1109 {
1110         int err;
1111         struct dpbp_attr dpbp_attr;
1112         struct dpbp_cfg dpbp_cfg;
1113
1114         dflt_dpbp = (struct fsl_dpbp_obj *)calloc(
1115                                         sizeof(struct fsl_dpbp_obj), 1);
1116         if (!dflt_dpbp) {
1117                 printf("No memory: calloc() failed\n");
1118                 err = -ENOMEM;
1119                 goto err_calloc;
1120         }
1121
1122         dpbp_cfg.options = 512;
1123
1124         err = dpbp_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpbp_cfg,
1125                           &dflt_dpbp->dpbp_handle);
1126
1127         if (err < 0) {
1128                 err = -ENODEV;
1129                 printf("dpbp_create() failed: %d\n", err);
1130                 goto err_create;
1131         }
1132
1133         memset(&dpbp_attr, 0, sizeof(struct dpbp_attr));
1134         err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1135                                   dflt_dpbp->dpbp_handle,
1136                                   &dpbp_attr);
1137         if (err < 0) {
1138                 printf("dpbp_get_attributes() failed: %d\n", err);
1139                 goto err_get_attr;
1140         }
1141
1142         if ((dpbp_attr.version.major != DPBP_VER_MAJOR) ||
1143             (dpbp_attr.version.minor != DPBP_VER_MINOR)) {
1144                 printf("DPBP version mismatch found %u.%u,",
1145                        dpbp_attr.version.major, dpbp_attr.version.minor);
1146                 printf("supported version is %u.%u\n",
1147                        DPBP_VER_MAJOR, DPBP_VER_MINOR);
1148         }
1149
1150         dflt_dpbp->dpbp_attr.id = dpbp_attr.id;
1151 #ifdef DEBUG
1152         printf("Init: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
1153 #endif
1154
1155         err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1156         if (err < 0) {
1157                 printf("dpbp_close() failed: %d\n", err);
1158                 goto err_close;
1159         }
1160
1161         return 0;
1162
1163 err_close:
1164         free(dflt_dpbp);
1165 err_get_attr:
1166         dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1167         dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1168 err_create:
1169 err_calloc:
1170         return err;
1171 }
1172
1173 static int dpbp_exit(void)
1174 {
1175         int err;
1176
1177         err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
1178                         &dflt_dpbp->dpbp_handle);
1179         if (err < 0) {
1180                 printf("dpbp_open() failed: %d\n", err);
1181                 goto err;
1182         }
1183
1184         err = dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
1185                            dflt_dpbp->dpbp_handle);
1186         if (err < 0) {
1187                 printf("dpbp_destroy() failed: %d\n", err);
1188                 goto err;
1189         }
1190
1191 #ifdef DEBUG
1192         printf("Exit: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
1193 #endif
1194
1195         if (dflt_dpbp)
1196                 free(dflt_dpbp);
1197         return 0;
1198
1199 err:
1200         return err;
1201 }
1202
1203 static int dpni_init(void)
1204 {
1205         int err;
1206         struct dpni_attr dpni_attr;
1207         uint8_t ext_cfg_buf[256] = {0};
1208         struct dpni_extended_cfg dpni_extended_cfg;
1209         struct dpni_cfg dpni_cfg;
1210
1211         dflt_dpni = (struct fsl_dpni_obj *)calloc(
1212                                         sizeof(struct fsl_dpni_obj), 1);
1213         if (!dflt_dpni) {
1214                 printf("No memory: calloc() failed\n");
1215                 err = -ENOMEM;
1216                 goto err_calloc;
1217         }
1218
1219         memset(&dpni_extended_cfg, 0, sizeof(dpni_extended_cfg));
1220         err = dpni_prepare_extended_cfg(&dpni_extended_cfg, &ext_cfg_buf[0]);
1221         if (err < 0) {
1222                 err = -ENODEV;
1223                 printf("dpni_prepare_extended_cfg() failed: %d\n", err);
1224                 goto err_prepare_extended_cfg;
1225         }
1226
1227         memset(&dpni_cfg, 0, sizeof(dpni_cfg));
1228         dpni_cfg.adv.options = DPNI_OPT_UNICAST_FILTER |
1229                                DPNI_OPT_MULTICAST_FILTER;
1230
1231         dpni_cfg.adv.ext_cfg_iova = (uint64_t)&ext_cfg_buf[0];
1232         err = dpni_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpni_cfg,
1233                           &dflt_dpni->dpni_handle);
1234
1235         if (err < 0) {
1236                 err = -ENODEV;
1237                 printf("dpni_create() failed: %d\n", err);
1238                 goto err_create;
1239         }
1240
1241         memset(&dpni_attr, 0, sizeof(struct dpni_attr));
1242         err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1243                                   dflt_dpni->dpni_handle,
1244                                   &dpni_attr);
1245         if (err < 0) {
1246                 printf("dpni_get_attributes() failed: %d\n", err);
1247                 goto err_get_attr;
1248         }
1249
1250         if ((dpni_attr.version.major != DPNI_VER_MAJOR) ||
1251             (dpni_attr.version.minor != DPNI_VER_MINOR)) {
1252                 printf("DPNI version mismatch found %u.%u,",
1253                        dpni_attr.version.major, dpni_attr.version.minor);
1254                 printf("supported version is %u.%u\n",
1255                        DPNI_VER_MAJOR, DPNI_VER_MINOR);
1256         }
1257
1258         dflt_dpni->dpni_id = dpni_attr.id;
1259 #ifdef DEBUG
1260         printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1261 #endif
1262
1263         err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1264         if (err < 0) {
1265                 printf("dpni_close() failed: %d\n", err);
1266                 goto err_close;
1267         }
1268
1269         return 0;
1270
1271 err_close:
1272 err_get_attr:
1273         dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1274         dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1275 err_create:
1276 err_prepare_extended_cfg:
1277         free(dflt_dpni);
1278 err_calloc:
1279         return err;
1280 }
1281
1282 static int dpni_exit(void)
1283 {
1284         int err;
1285
1286         err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
1287                         &dflt_dpni->dpni_handle);
1288         if (err < 0) {
1289                 printf("dpni_open() failed: %d\n", err);
1290                 goto err;
1291         }
1292
1293         err = dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
1294                            dflt_dpni->dpni_handle);
1295         if (err < 0) {
1296                 printf("dpni_destroy() failed: %d\n", err);
1297                 goto err;
1298         }
1299
1300 #ifdef DEBUG
1301         printf("Exit: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1302 #endif
1303
1304         if (dflt_dpni)
1305                 free(dflt_dpni);
1306         return 0;
1307
1308 err:
1309         return err;
1310 }
1311
1312 static int mc_init_object(void)
1313 {
1314         int err = 0;
1315
1316         err = dprc_init();
1317         if (err < 0) {
1318                 printf("dprc_init() failed: %d\n", err);
1319                 goto err;
1320         }
1321
1322         err = dpbp_init();
1323         if (err < 0) {
1324                 printf("dpbp_init() failed: %d\n", err);
1325                 goto err;
1326         }
1327
1328         err = dpio_init();
1329         if (err < 0) {
1330                 printf("dpio_init() failed: %d\n", err);
1331                 goto err;
1332         }
1333
1334         err = dpni_init();
1335         if (err < 0) {
1336                 printf("dpni_init() failed: %d\n", err);
1337                 goto err;
1338         }
1339
1340         return 0;
1341 err:
1342         return err;
1343 }
1344
1345 int fsl_mc_ldpaa_exit(bd_t *bd)
1346 {
1347         int err = 0;
1348         bool is_dpl_apply_status = false;
1349         bool mc_boot_status = false;
1350
1351         if (bd && mc_lazy_dpl_addr && !fsl_mc_ldpaa_exit(NULL)) {
1352                 mc_apply_dpl(mc_lazy_dpl_addr);
1353                 mc_lazy_dpl_addr = 0;
1354         }
1355
1356         if (!get_mc_boot_status())
1357                 mc_boot_status = true;
1358
1359         /* MC is not loaded intentionally, So return success. */
1360         if (bd && !mc_boot_status)
1361                 return 0;
1362
1363         /* If DPL is deployed, set is_dpl_apply_status as TRUE. */
1364         if (!get_dpl_apply_status())
1365                 is_dpl_apply_status = true;
1366
1367         /*
1368          * For case MC is loaded but DPL is not deployed, return success and
1369          * print message on console. Else FDT fix-up code execution hanged.
1370          */
1371         if (bd && mc_boot_status && !is_dpl_apply_status) {
1372                 printf("fsl-mc: DPL not deployed, DPAA2 ethernet not work\n");
1373                 return 0;
1374         }
1375
1376         if (bd && mc_boot_status && is_dpl_apply_status)
1377                 return 0;
1378
1379         err = dpbp_exit();
1380         if (err < 0) {
1381                 printf("dpbp_exit() failed: %d\n", err);
1382                 goto err;
1383         }
1384
1385         err = dpio_exit();
1386         if (err < 0) {
1387                 printf("dpio_exit() failed: %d\n", err);
1388                 goto err;
1389         }
1390
1391         err = dpni_exit();
1392         if (err < 0) {
1393                 printf("dpni_exit() failed: %d\n", err);
1394                 goto err;
1395         }
1396
1397         err = dprc_exit();
1398         if (err < 0) {
1399                 printf("dprc_exit() failed: %d\n", err);
1400                 goto err;
1401         }
1402
1403         return 0;
1404 err:
1405         return err;
1406 }
1407
1408 static int do_fsl_mc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1409 {
1410         int err = 0;
1411         if (argc < 3)
1412                 goto usage;
1413
1414         switch (argv[1][0]) {
1415         case 's': {
1416                         char sub_cmd;
1417                         u64 mc_fw_addr, mc_dpc_addr;
1418 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1419                         u64 aiop_fw_addr;
1420 #endif
1421
1422                         sub_cmd = argv[2][0];
1423                         switch (sub_cmd) {
1424                         case 'm':
1425                                 if (argc < 5)
1426                                         goto usage;
1427
1428                                 if (get_mc_boot_status() == 0) {
1429                                         printf("fsl-mc: MC is already booted");
1430                                         printf("\n");
1431                                         return err;
1432                                 }
1433                                 mc_fw_addr = simple_strtoull(argv[3], NULL, 16);
1434                                 mc_dpc_addr = simple_strtoull(argv[4], NULL,
1435                                                               16);
1436
1437                                 if (!mc_init(mc_fw_addr, mc_dpc_addr))
1438                                         err = mc_init_object();
1439                                 break;
1440
1441 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1442                         case 'a':
1443                                 if (argc < 4)
1444                                         goto usage;
1445                                 if (get_aiop_apply_status() == 0) {
1446                                         printf("fsl-mc: AIOP FW is already");
1447                                         printf(" applied\n");
1448                                         return err;
1449                                 }
1450
1451                                 aiop_fw_addr = simple_strtoull(argv[3], NULL,
1452                                                                16);
1453
1454                                 /* if SoC doesn't have AIOP, err = -ENODEV */
1455                                 err = load_mc_aiop_img(aiop_fw_addr);
1456                                 if (!err)
1457                                         printf("fsl-mc: AIOP FW applied\n");
1458                                 break;
1459 #endif
1460                         default:
1461                                 printf("Invalid option: %s\n", argv[2]);
1462                                 goto usage;
1463
1464                                 break;
1465                         }
1466                 }
1467                 break;
1468
1469         case 'l':
1470         case 'a': {
1471                         u64 mc_dpl_addr;
1472
1473                         if (argc < 4)
1474                                 goto usage;
1475
1476                         if (get_dpl_apply_status() == 0) {
1477                                 printf("fsl-mc: DPL already applied\n");
1478                                 return err;
1479                         }
1480
1481                         mc_dpl_addr = simple_strtoull(argv[3], NULL,
1482                                                               16);
1483
1484                         if (get_mc_boot_status() != 0) {
1485                                 printf("fsl-mc: Deploying data path layout ..");
1486                                 printf("ERROR (MC is not booted)\n");
1487                                 return -ENODEV;
1488                         }
1489
1490                         if (argv[1][0] == 'l') {
1491                                 /*
1492                                  * We will do the actual dpaa exit and dpl apply
1493                                  * later from announce_and_cleanup().
1494                                  */
1495                                 mc_lazy_dpl_addr = mc_dpl_addr;
1496                         } else {
1497                                 /* The user wants it applied now */
1498                                 if (!fsl_mc_ldpaa_exit(NULL))
1499                                         err = mc_apply_dpl(mc_dpl_addr);
1500                         }
1501                         break;
1502                 }
1503         default:
1504                 printf("Invalid option: %s\n", argv[1]);
1505                 goto usage;
1506                 break;
1507         }
1508         return err;
1509  usage:
1510         return CMD_RET_USAGE;
1511 }
1512
1513 U_BOOT_CMD(
1514         fsl_mc,  CONFIG_SYS_MAXARGS,  1,   do_fsl_mc,
1515         "DPAA2 command to manage Management Complex (MC)",
1516         "start mc [FW_addr] [DPC_addr] - Start Management Complex\n"
1517         "fsl_mc apply DPL [DPL_addr] - Apply DPL file\n"
1518         "fsl_mc lazyapply DPL [DPL_addr] - Apply DPL file on exit\n"
1519         "fsl_mc start aiop [FW_addr] - Start AIOP\n"
1520 );
1521
1522 void mc_env_boot(void)
1523 {
1524 #if defined(CONFIG_FSL_MC_ENET)
1525         char *mc_boot_env_var;
1526         /* The MC may only be initialized in the reset PHY function
1527          * because otherwise U-Boot has not yet set up all the MAC
1528          * address info properly. Without MAC addresses, the MC code
1529          * can not properly initialize the DPC.
1530          */
1531         mc_boot_env_var = env_get(MC_BOOT_ENV_VAR);
1532         if (mc_boot_env_var)
1533                 run_command_list(mc_boot_env_var, -1, 0);
1534 #endif /* CONFIG_FSL_MC_ENET */
1535 }