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