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