]> git.sur5r.net Git - u-boot/blob - drivers/net/fsl-mc/mc.c
be823717665420b80ae803391ee85f0aa797e9c2
[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_getenv_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 *)malloc(sizeof(struct fsl_mc_io));
729         if (!root_mc_io) {
730                 printf(" No memory: malloc() 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  */
806 u64 mc_get_dram_addr(void)
807 {
808         return gd->arch.resv_ram;
809 }
810
811 /**
812  * Return the actual size of the MC private DRAM block.
813  */
814 unsigned long mc_get_dram_block_size(void)
815 {
816         unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
817
818         char *dram_block_size_env_var = env_get(MC_MEM_SIZE_ENV_VAR);
819
820         if (dram_block_size_env_var) {
821                 dram_block_size = simple_strtoul(dram_block_size_env_var, NULL,
822                                                  10);
823
824                 if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
825                         printf("fsl-mc: WARNING: Invalid value for \'"
826                                MC_MEM_SIZE_ENV_VAR
827                                "\' environment variable: %lu\n",
828                                dram_block_size);
829
830                         dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
831                 }
832         }
833
834         return dram_block_size;
835 }
836
837 int fsl_mc_ldpaa_init(bd_t *bis)
838 {
839         int i;
840
841         for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++)
842                 if ((wriop_is_enabled_dpmac(i) == 1) &&
843                     (wriop_get_phy_address(i) != -1))
844                         ldpaa_eth_init(i, wriop_get_enet_if(i));
845         return 0;
846 }
847
848 static int dprc_version_check(struct fsl_mc_io *mc_io, uint16_t handle)
849 {
850         struct dprc_attributes attr;
851         int error;
852
853         memset(&attr, 0, sizeof(struct dprc_attributes));
854         error = dprc_get_attributes(mc_io, MC_CMD_NO_FLAGS, handle, &attr);
855         if (error == 0) {
856                 if ((attr.version.major != DPRC_VER_MAJOR) ||
857                     (attr.version.minor != DPRC_VER_MINOR)) {
858                         printf("DPRC version mismatch found %u.%u,",
859                                attr.version.major,
860                                attr.version.minor);
861                         printf("supported version is %u.%u\n",
862                                DPRC_VER_MAJOR, DPRC_VER_MINOR);
863                 }
864         }
865         return error;
866 }
867
868 static int dpio_init(void)
869 {
870         struct qbman_swp_desc p_des;
871         struct dpio_attr attr;
872         struct dpio_cfg dpio_cfg;
873         int err = 0;
874
875         dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj));
876         if (!dflt_dpio) {
877                 printf("No memory: malloc() failed\n");
878                 err = -ENOMEM;
879                 goto err_malloc;
880         }
881
882         dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL;
883         dpio_cfg.num_priorities = 8;
884
885         err = dpio_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpio_cfg,
886                           &dflt_dpio->dpio_handle);
887         if (err < 0) {
888                 printf("dpio_create() failed: %d\n", err);
889                 err = -ENODEV;
890                 goto err_create;
891         }
892
893         memset(&attr, 0, sizeof(struct dpio_attr));
894         err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
895                                   dflt_dpio->dpio_handle, &attr);
896         if (err < 0) {
897                 printf("dpio_get_attributes() failed: %d\n", err);
898                 goto err_get_attr;
899         }
900
901         if ((attr.version.major != DPIO_VER_MAJOR) ||
902             (attr.version.minor != DPIO_VER_MINOR)) {
903                 printf("DPIO version mismatch found %u.%u,",
904                        attr.version.major, attr.version.minor);
905                 printf("supported version is %u.%u\n",
906                        DPIO_VER_MAJOR, DPIO_VER_MINOR);
907         }
908
909         dflt_dpio->dpio_id = attr.id;
910 #ifdef DEBUG
911         printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id);
912 #endif
913         err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
914         if (err < 0) {
915                 printf("dpio_enable() failed %d\n", err);
916                 goto err_get_enable;
917         }
918         debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n",
919               attr.qbman_portal_ce_offset,
920               attr.qbman_portal_ci_offset,
921               attr.qbman_portal_id,
922               attr.num_priorities);
923
924         p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
925                                         + attr.qbman_portal_ce_offset);
926         p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
927                                         + attr.qbman_portal_ci_offset);
928
929         dflt_dpio->sw_portal = qbman_swp_init(&p_des);
930         if (dflt_dpio->sw_portal == NULL) {
931                 printf("qbman_swp_init() failed\n");
932                 goto err_get_swp_init;
933         }
934         return 0;
935
936 err_get_swp_init:
937         dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
938 err_get_enable:
939 err_get_attr:
940         dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
941         dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
942 err_create:
943         free(dflt_dpio);
944 err_malloc:
945         return err;
946 }
947
948 static int dpio_exit(void)
949 {
950         int err;
951
952         err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
953         if (err < 0) {
954                 printf("dpio_disable() failed: %d\n", err);
955                 goto err;
956         }
957
958         err = dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
959         if (err < 0) {
960                 printf("dpio_destroy() failed: %d\n", err);
961                 goto err;
962         }
963
964 #ifdef DEBUG
965         printf("Exit: DPIO id=0x%d\n", dflt_dpio->dpio_id);
966 #endif
967
968         if (dflt_dpio)
969                 free(dflt_dpio);
970
971         return 0;
972 err:
973         return err;
974 }
975
976 static int dprc_init(void)
977 {
978         int err, child_portal_id, container_id;
979         struct dprc_cfg cfg;
980         uint64_t mc_portal_offset;
981
982         /* Open root container */
983         err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id);
984         if (err < 0) {
985                 printf("dprc_get_container_id(): Root failed: %d\n", err);
986                 goto err_root_container_id;
987         }
988
989 #ifdef DEBUG
990         printf("Root container id = %d\n", container_id);
991 #endif
992         err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id,
993                         &root_dprc_handle);
994         if (err < 0) {
995                 printf("dprc_open(): Root Container failed: %d\n", err);
996                 goto err_root_open;
997         }
998
999         if (!root_dprc_handle) {
1000                 printf("dprc_open(): Root Container Handle is not valid\n");
1001                 goto err_root_open;
1002         }
1003
1004         err = dprc_version_check(root_mc_io, root_dprc_handle);
1005         if (err < 0) {
1006                 printf("dprc_version_check() failed: %d\n", err);
1007                 goto err_root_open;
1008         }
1009
1010         memset(&cfg, 0, sizeof(struct dprc_cfg));
1011         cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED |
1012                       DPRC_CFG_OPT_OBJ_CREATE_ALLOWED |
1013                       DPRC_CFG_OPT_ALLOC_ALLOWED;
1014         cfg.icid = DPRC_GET_ICID_FROM_POOL;
1015         cfg.portal_id = DPRC_GET_PORTAL_ID_FROM_POOL;
1016         err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS,
1017                         root_dprc_handle,
1018                         &cfg,
1019                         &child_dprc_id,
1020                         &mc_portal_offset);
1021         if (err < 0) {
1022                 printf("dprc_create_container() failed: %d\n", err);
1023                 goto err_create;
1024         }
1025
1026         dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
1027         if (!dflt_mc_io) {
1028                 err  = -ENOMEM;
1029                 printf(" No memory: malloc() failed\n");
1030                 goto err_malloc;
1031         }
1032
1033         child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset);
1034         dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id);
1035 #ifdef DEBUG
1036         printf("MC portal of child DPRC container: %d, physical addr %p)\n",
1037                child_dprc_id, dflt_mc_io->mmio_regs);
1038 #endif
1039
1040         err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id,
1041                         &dflt_dprc_handle);
1042         if (err < 0) {
1043                 printf("dprc_open(): Child container failed: %d\n", err);
1044                 goto err_child_open;
1045         }
1046
1047         if (!dflt_dprc_handle) {
1048                 printf("dprc_open(): Child container Handle is not valid\n");
1049                 goto err_child_open;
1050         }
1051
1052         return 0;
1053 err_child_open:
1054         free(dflt_mc_io);
1055 err_malloc:
1056         dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
1057                                root_dprc_handle, child_dprc_id);
1058 err_create:
1059         dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
1060 err_root_open:
1061 err_root_container_id:
1062         return err;
1063 }
1064
1065 static int dprc_exit(void)
1066 {
1067         int err;
1068
1069         err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle);
1070         if (err < 0) {
1071                 printf("dprc_close(): Child failed: %d\n", err);
1072                 goto err;
1073         }
1074
1075         err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
1076                                      root_dprc_handle, child_dprc_id);
1077         if (err < 0) {
1078                 printf("dprc_destroy_container() failed: %d\n", err);
1079                 goto err;
1080         }
1081
1082         err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
1083         if (err < 0) {
1084                 printf("dprc_close(): Root failed: %d\n", err);
1085                 goto err;
1086         }
1087
1088         if (dflt_mc_io)
1089                 free(dflt_mc_io);
1090
1091         if (root_mc_io)
1092                 free(root_mc_io);
1093
1094         return 0;
1095
1096 err:
1097         return err;
1098 }
1099
1100 static int dpbp_init(void)
1101 {
1102         int err;
1103         struct dpbp_attr dpbp_attr;
1104         struct dpbp_cfg dpbp_cfg;
1105
1106         dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj));
1107         if (!dflt_dpbp) {
1108                 printf("No memory: malloc() failed\n");
1109                 err = -ENOMEM;
1110                 goto err_malloc;
1111         }
1112
1113         dpbp_cfg.options = 512;
1114
1115         err = dpbp_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpbp_cfg,
1116                           &dflt_dpbp->dpbp_handle);
1117
1118         if (err < 0) {
1119                 err = -ENODEV;
1120                 printf("dpbp_create() failed: %d\n", err);
1121                 goto err_create;
1122         }
1123
1124         memset(&dpbp_attr, 0, sizeof(struct dpbp_attr));
1125         err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1126                                   dflt_dpbp->dpbp_handle,
1127                                   &dpbp_attr);
1128         if (err < 0) {
1129                 printf("dpbp_get_attributes() failed: %d\n", err);
1130                 goto err_get_attr;
1131         }
1132
1133         if ((dpbp_attr.version.major != DPBP_VER_MAJOR) ||
1134             (dpbp_attr.version.minor != DPBP_VER_MINOR)) {
1135                 printf("DPBP version mismatch found %u.%u,",
1136                        dpbp_attr.version.major, dpbp_attr.version.minor);
1137                 printf("supported version is %u.%u\n",
1138                        DPBP_VER_MAJOR, DPBP_VER_MINOR);
1139         }
1140
1141         dflt_dpbp->dpbp_attr.id = dpbp_attr.id;
1142 #ifdef DEBUG
1143         printf("Init: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
1144 #endif
1145
1146         err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1147         if (err < 0) {
1148                 printf("dpbp_close() failed: %d\n", err);
1149                 goto err_close;
1150         }
1151
1152         return 0;
1153
1154 err_close:
1155         free(dflt_dpbp);
1156 err_get_attr:
1157         dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1158         dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1159 err_create:
1160 err_malloc:
1161         return err;
1162 }
1163
1164 static int dpbp_exit(void)
1165 {
1166         int err;
1167
1168         err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
1169                         &dflt_dpbp->dpbp_handle);
1170         if (err < 0) {
1171                 printf("dpbp_open() failed: %d\n", err);
1172                 goto err;
1173         }
1174
1175         err = dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
1176                            dflt_dpbp->dpbp_handle);
1177         if (err < 0) {
1178                 printf("dpbp_destroy() failed: %d\n", err);
1179                 goto err;
1180         }
1181
1182 #ifdef DEBUG
1183         printf("Exit: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
1184 #endif
1185
1186         if (dflt_dpbp)
1187                 free(dflt_dpbp);
1188         return 0;
1189
1190 err:
1191         return err;
1192 }
1193
1194 static int dpni_init(void)
1195 {
1196         int err;
1197         struct dpni_attr dpni_attr;
1198         uint8_t ext_cfg_buf[256] = {0};
1199         struct dpni_extended_cfg dpni_extended_cfg;
1200         struct dpni_cfg dpni_cfg;
1201
1202         dflt_dpni = (struct fsl_dpni_obj *)malloc(sizeof(struct fsl_dpni_obj));
1203         if (!dflt_dpni) {
1204                 printf("No memory: malloc() failed\n");
1205                 err = -ENOMEM;
1206                 goto err_malloc;
1207         }
1208
1209         memset(&dpni_extended_cfg, 0, sizeof(dpni_extended_cfg));
1210         err = dpni_prepare_extended_cfg(&dpni_extended_cfg, &ext_cfg_buf[0]);
1211         if (err < 0) {
1212                 err = -ENODEV;
1213                 printf("dpni_prepare_extended_cfg() failed: %d\n", err);
1214                 goto err_prepare_extended_cfg;
1215         }
1216
1217         memset(&dpni_cfg, 0, sizeof(dpni_cfg));
1218         dpni_cfg.adv.options = DPNI_OPT_UNICAST_FILTER |
1219                                DPNI_OPT_MULTICAST_FILTER;
1220
1221         dpni_cfg.adv.ext_cfg_iova = (uint64_t)&ext_cfg_buf[0];
1222         err = dpni_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpni_cfg,
1223                           &dflt_dpni->dpni_handle);
1224
1225         if (err < 0) {
1226                 err = -ENODEV;
1227                 printf("dpni_create() failed: %d\n", err);
1228                 goto err_create;
1229         }
1230
1231         memset(&dpni_attr, 0, sizeof(struct dpni_attr));
1232         err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1233                                   dflt_dpni->dpni_handle,
1234                                   &dpni_attr);
1235         if (err < 0) {
1236                 printf("dpni_get_attributes() failed: %d\n", err);
1237                 goto err_get_attr;
1238         }
1239
1240         if ((dpni_attr.version.major != DPNI_VER_MAJOR) ||
1241             (dpni_attr.version.minor != DPNI_VER_MINOR)) {
1242                 printf("DPNI version mismatch found %u.%u,",
1243                        dpni_attr.version.major, dpni_attr.version.minor);
1244                 printf("supported version is %u.%u\n",
1245                        DPNI_VER_MAJOR, DPNI_VER_MINOR);
1246         }
1247
1248         dflt_dpni->dpni_id = dpni_attr.id;
1249 #ifdef DEBUG
1250         printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1251 #endif
1252
1253         err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1254         if (err < 0) {
1255                 printf("dpni_close() failed: %d\n", err);
1256                 goto err_close;
1257         }
1258
1259         return 0;
1260
1261 err_close:
1262 err_get_attr:
1263         dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1264         dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1265 err_create:
1266 err_prepare_extended_cfg:
1267         free(dflt_dpni);
1268 err_malloc:
1269         return err;
1270 }
1271
1272 static int dpni_exit(void)
1273 {
1274         int err;
1275
1276         err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
1277                         &dflt_dpni->dpni_handle);
1278         if (err < 0) {
1279                 printf("dpni_open() failed: %d\n", err);
1280                 goto err;
1281         }
1282
1283         err = dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
1284                            dflt_dpni->dpni_handle);
1285         if (err < 0) {
1286                 printf("dpni_destroy() failed: %d\n", err);
1287                 goto err;
1288         }
1289
1290 #ifdef DEBUG
1291         printf("Exit: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1292 #endif
1293
1294         if (dflt_dpni)
1295                 free(dflt_dpni);
1296         return 0;
1297
1298 err:
1299         return err;
1300 }
1301
1302 static int mc_init_object(void)
1303 {
1304         int err = 0;
1305
1306         err = dprc_init();
1307         if (err < 0) {
1308                 printf("dprc_init() failed: %d\n", err);
1309                 goto err;
1310         }
1311
1312         err = dpbp_init();
1313         if (err < 0) {
1314                 printf("dpbp_init() failed: %d\n", err);
1315                 goto err;
1316         }
1317
1318         err = dpio_init();
1319         if (err < 0) {
1320                 printf("dpio_init() failed: %d\n", err);
1321                 goto err;
1322         }
1323
1324         err = dpni_init();
1325         if (err < 0) {
1326                 printf("dpni_init() failed: %d\n", err);
1327                 goto err;
1328         }
1329
1330         return 0;
1331 err:
1332         return err;
1333 }
1334
1335 int fsl_mc_ldpaa_exit(bd_t *bd)
1336 {
1337         int err = 0;
1338         bool is_dpl_apply_status = false;
1339         bool mc_boot_status = false;
1340
1341         if (bd && mc_lazy_dpl_addr && !fsl_mc_ldpaa_exit(NULL)) {
1342                 mc_apply_dpl(mc_lazy_dpl_addr);
1343                 mc_lazy_dpl_addr = 0;
1344         }
1345
1346         if (!get_mc_boot_status())
1347                 mc_boot_status = true;
1348
1349         /* MC is not loaded intentionally, So return success. */
1350         if (bd && !mc_boot_status)
1351                 return 0;
1352
1353         /* If DPL is deployed, set is_dpl_apply_status as TRUE. */
1354         if (!get_dpl_apply_status())
1355                 is_dpl_apply_status = true;
1356
1357         /*
1358          * For case MC is loaded but DPL is not deployed, return success and
1359          * print message on console. Else FDT fix-up code execution hanged.
1360          */
1361         if (bd && mc_boot_status && !is_dpl_apply_status) {
1362                 printf("fsl-mc: DPL not deployed, DPAA2 ethernet not work\n");
1363                 return 0;
1364         }
1365
1366         if (bd && mc_boot_status && is_dpl_apply_status)
1367                 return 0;
1368
1369         err = dpbp_exit();
1370         if (err < 0) {
1371                 printf("dpbp_exit() failed: %d\n", err);
1372                 goto err;
1373         }
1374
1375         err = dpio_exit();
1376         if (err < 0) {
1377                 printf("dpio_exit() failed: %d\n", err);
1378                 goto err;
1379         }
1380
1381         err = dpni_exit();
1382         if (err < 0) {
1383                 printf("dpni_exit() failed: %d\n", err);
1384                 goto err;
1385         }
1386
1387         err = dprc_exit();
1388         if (err < 0) {
1389                 printf("dprc_exit() failed: %d\n", err);
1390                 goto err;
1391         }
1392
1393         return 0;
1394 err:
1395         return err;
1396 }
1397
1398 static int do_fsl_mc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1399 {
1400         int err = 0;
1401         if (argc < 3)
1402                 goto usage;
1403
1404         switch (argv[1][0]) {
1405         case 's': {
1406                         char sub_cmd;
1407                         u64 mc_fw_addr, mc_dpc_addr;
1408 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1409                         u64 aiop_fw_addr;
1410 #endif
1411
1412                         sub_cmd = argv[2][0];
1413                         switch (sub_cmd) {
1414                         case 'm':
1415                                 if (argc < 5)
1416                                         goto usage;
1417
1418                                 if (get_mc_boot_status() == 0) {
1419                                         printf("fsl-mc: MC is already booted");
1420                                         printf("\n");
1421                                         return err;
1422                                 }
1423                                 mc_fw_addr = simple_strtoull(argv[3], NULL, 16);
1424                                 mc_dpc_addr = simple_strtoull(argv[4], NULL,
1425                                                               16);
1426
1427                                 if (!mc_init(mc_fw_addr, mc_dpc_addr))
1428                                         err = mc_init_object();
1429                                 break;
1430
1431 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1432                         case 'a':
1433                                 if (argc < 4)
1434                                         goto usage;
1435                                 if (get_aiop_apply_status() == 0) {
1436                                         printf("fsl-mc: AIOP FW is already");
1437                                         printf(" applied\n");
1438                                         return err;
1439                                 }
1440
1441                                 aiop_fw_addr = simple_strtoull(argv[3], NULL,
1442                                                                16);
1443
1444                                 /* if SoC doesn't have AIOP, err = -ENODEV */
1445                                 err = load_mc_aiop_img(aiop_fw_addr);
1446                                 if (!err)
1447                                         printf("fsl-mc: AIOP FW applied\n");
1448                                 break;
1449 #endif
1450                         default:
1451                                 printf("Invalid option: %s\n", argv[2]);
1452                                 goto usage;
1453
1454                                 break;
1455                         }
1456                 }
1457                 break;
1458
1459         case 'l':
1460         case 'a': {
1461                         u64 mc_dpl_addr;
1462
1463                         if (argc < 4)
1464                                 goto usage;
1465
1466                         if (get_dpl_apply_status() == 0) {
1467                                 printf("fsl-mc: DPL already applied\n");
1468                                 return err;
1469                         }
1470
1471                         mc_dpl_addr = simple_strtoull(argv[3], NULL,
1472                                                               16);
1473
1474                         if (get_mc_boot_status() != 0) {
1475                                 printf("fsl-mc: Deploying data path layout ..");
1476                                 printf("ERROR (MC is not booted)\n");
1477                                 return -ENODEV;
1478                         }
1479
1480                         if (argv[1][0] == 'l') {
1481                                 /*
1482                                  * We will do the actual dpaa exit and dpl apply
1483                                  * later from announce_and_cleanup().
1484                                  */
1485                                 mc_lazy_dpl_addr = mc_dpl_addr;
1486                         } else {
1487                                 /* The user wants it applied now */
1488                                 if (!fsl_mc_ldpaa_exit(NULL))
1489                                         err = mc_apply_dpl(mc_dpl_addr);
1490                         }
1491                         break;
1492                 }
1493         default:
1494                 printf("Invalid option: %s\n", argv[1]);
1495                 goto usage;
1496                 break;
1497         }
1498         return err;
1499  usage:
1500         return CMD_RET_USAGE;
1501 }
1502
1503 U_BOOT_CMD(
1504         fsl_mc,  CONFIG_SYS_MAXARGS,  1,   do_fsl_mc,
1505         "DPAA2 command to manage Management Complex (MC)",
1506         "start mc [FW_addr] [DPC_addr] - Start Management Complex\n"
1507         "fsl_mc apply DPL [DPL_addr] - Apply DPL file\n"
1508         "fsl_mc lazyapply DPL [DPL_addr] - Apply DPL file on exit\n"
1509         "fsl_mc start aiop [FW_addr] - Start AIOP\n"
1510 );
1511
1512 void mc_env_boot(void)
1513 {
1514 #if defined(CONFIG_FSL_MC_ENET)
1515         char *mc_boot_env_var;
1516         /* The MC may only be initialized in the reset PHY function
1517          * because otherwise U-Boot has not yet set up all the MAC
1518          * address info properly. Without MAC addresses, the MC code
1519          * can not properly initialize the DPC.
1520          */
1521         mc_boot_env_var = env_get(MC_BOOT_ENV_VAR);
1522         if (mc_boot_env_var)
1523                 run_command_list(mc_boot_env_var, -1, 0);
1524 #endif /* CONFIG_FSL_MC_ENET */
1525 }