Merge branch 'master' of git://git.denx.de/u-boot-fsl-qoriq
[oweals/u-boot.git] / drivers / net / fsl-mc / mc.c
1 /*
2  * Copyright (C) 2014 Freescale Semiconductor
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6 #include <common.h>
7 #include <errno.h>
8 #include <asm/io.h>
9 #include <libfdt.h>
10 #include <fdt_support.h>
11 #include <fsl-mc/fsl_mc.h>
12 #include <fsl-mc/fsl_mc_sys.h>
13 #include <fsl-mc/fsl_mc_private.h>
14 #include <fsl-mc/fsl_dpmng.h>
15 #include <fsl-mc/fsl_dprc.h>
16 #include <fsl-mc/fsl_dpio.h>
17 #include <fsl-mc/fsl_dpni.h>
18 #include <fsl-mc/fsl_qbman_portal.h>
19 #include <fsl-mc/ldpaa_wriop.h>
20
21 #define MC_RAM_BASE_ADDR_ALIGNMENT  (512UL * 1024 * 1024)
22 #define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1))
23 #define MC_RAM_SIZE_ALIGNMENT       (256UL * 1024 * 1024)
24
25 #define MC_MEM_SIZE_ENV_VAR     "mcmemsize"
26 #define MC_BOOT_TIMEOUT_ENV_VAR "mcboottimeout"
27
28 DECLARE_GLOBAL_DATA_PTR;
29 static int mc_boot_status = -1;
30 static int mc_dpl_applied = -1;
31 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
32 static int mc_aiop_applied = -1;
33 #endif
34 struct fsl_mc_io *root_mc_io = NULL;
35 struct fsl_mc_io *dflt_mc_io = NULL; /* child container */
36 uint16_t root_dprc_handle = 0;
37 uint16_t dflt_dprc_handle = 0;
38 int child_dprc_id;
39 struct fsl_dpbp_obj *dflt_dpbp = NULL;
40 struct fsl_dpio_obj *dflt_dpio = NULL;
41 struct fsl_dpni_obj *dflt_dpni = NULL;
42
43 #ifdef DEBUG
44 void dump_ram_words(const char *title, void *addr)
45 {
46         int i;
47         uint32_t *words = addr;
48
49         printf("Dumping beginning of %s (%p):\n", title, addr);
50         for (i = 0; i < 16; i++)
51                 printf("%#x ", words[i]);
52
53         printf("\n");
54 }
55
56 void dump_mc_ccsr_regs(struct mc_ccsr_registers __iomem *mc_ccsr_regs)
57 {
58         printf("MC CCSR registers:\n"
59                 "reg_gcr1 %#x\n"
60                 "reg_gsr %#x\n"
61                 "reg_sicbalr %#x\n"
62                 "reg_sicbahr %#x\n"
63                 "reg_sicapr %#x\n"
64                 "reg_mcfbalr %#x\n"
65                 "reg_mcfbahr %#x\n"
66                 "reg_mcfapr %#x\n"
67                 "reg_psr %#x\n",
68                 mc_ccsr_regs->reg_gcr1,
69                 mc_ccsr_regs->reg_gsr,
70                 mc_ccsr_regs->reg_sicbalr,
71                 mc_ccsr_regs->reg_sicbahr,
72                 mc_ccsr_regs->reg_sicapr,
73                 mc_ccsr_regs->reg_mcfbalr,
74                 mc_ccsr_regs->reg_mcfbahr,
75                 mc_ccsr_regs->reg_mcfapr,
76                 mc_ccsr_regs->reg_psr);
77 }
78 #else
79
80 #define dump_ram_words(title, addr)
81 #define dump_mc_ccsr_regs(mc_ccsr_regs)
82
83 #endif /* DEBUG */
84
85 #ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
86 /**
87  * Copying MC firmware or DPL image to DDR
88  */
89 static int mc_copy_image(const char *title,
90                          u64 image_addr, u32 image_size, u64 mc_ram_addr)
91 {
92         debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
93         memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
94         flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size);
95         return 0;
96 }
97
98 /**
99  * MC firmware FIT image parser checks if the image is in FIT
100  * format, verifies integrity of the image and calculates
101  * raw image address and size values.
102  * Returns 0 on success and a negative errno on error.
103  * task fail.
104  **/
105 int parse_mc_firmware_fit_image(u64 mc_fw_addr,
106                                 const void **raw_image_addr,
107                                 size_t *raw_image_size)
108 {
109         int format;
110         void *fit_hdr;
111         int node_offset;
112         const void *data;
113         size_t size;
114         const char *uname = "firmware";
115
116         fit_hdr = (void *)mc_fw_addr;
117
118         /* Check if Image is in FIT format */
119         format = genimg_get_format(fit_hdr);
120
121         if (format != IMAGE_FORMAT_FIT) {
122                 printf("fsl-mc: ERR: Bad firmware image (not a FIT image)\n");
123                 return -EINVAL;
124         }
125
126         if (!fit_check_format(fit_hdr)) {
127                 printf("fsl-mc: ERR: Bad firmware image (bad FIT header)\n");
128                 return -EINVAL;
129         }
130
131         node_offset = fit_image_get_node(fit_hdr, uname);
132
133         if (node_offset < 0) {
134                 printf("fsl-mc: ERR: Bad firmware image (missing subimage)\n");
135                 return -ENOENT;
136         }
137
138         /* Verify MC firmware image */
139         if (!(fit_image_verify(fit_hdr, node_offset))) {
140                 printf("fsl-mc: ERR: Bad firmware image (bad CRC)\n");
141                 return -EINVAL;
142         }
143
144         /* Get address and size of raw image */
145         fit_image_get_data(fit_hdr, node_offset, &data, &size);
146
147         *raw_image_addr = data;
148         *raw_image_size = size;
149
150         return 0;
151 }
152 #endif
153
154 /*
155  * Calculates the values to be used to specify the address range
156  * for the MC private DRAM block, in the MCFBALR/MCFBAHR registers.
157  * It returns the highest 512MB-aligned address within the given
158  * address range, in '*aligned_base_addr', and the number of 256 MiB
159  * blocks in it, in 'num_256mb_blocks'.
160  */
161 static int calculate_mc_private_ram_params(u64 mc_private_ram_start_addr,
162                                            size_t mc_ram_size,
163                                            u64 *aligned_base_addr,
164                                            u8 *num_256mb_blocks)
165 {
166         u64 addr;
167         u16 num_blocks;
168
169         if (mc_ram_size % MC_RAM_SIZE_ALIGNMENT != 0) {
170                 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
171                        mc_ram_size);
172                 return -EINVAL;
173         }
174
175         num_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT;
176         if (num_blocks < 1 || num_blocks > 0xff) {
177                 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
178                        mc_ram_size);
179                 return -EINVAL;
180         }
181
182         addr = (mc_private_ram_start_addr + mc_ram_size - 1) &
183                 MC_RAM_BASE_ADDR_ALIGNMENT_MASK;
184
185         if (addr < mc_private_ram_start_addr) {
186                 printf("fsl-mc: ERROR: bad start address %#llx\n",
187                        mc_private_ram_start_addr);
188                 return -EFAULT;
189         }
190
191         *aligned_base_addr = addr;
192         *num_256mb_blocks = num_blocks;
193         return 0;
194 }
195
196 static int mc_fixup_dpc(u64 dpc_addr)
197 {
198         void *blob = (void *)dpc_addr;
199         int nodeoffset;
200
201         /* delete any existing ICID pools */
202         nodeoffset = fdt_path_offset(blob, "/resources/icid_pools");
203         if (fdt_del_node(blob, nodeoffset) < 0)
204                 printf("\nfsl-mc: WARNING: could not delete ICID pool\n");
205
206         /* add a new pool */
207         nodeoffset = fdt_path_offset(blob, "/resources");
208         if (nodeoffset < 0) {
209                 printf("\nfsl-mc: ERROR: DPC is missing /resources\n");
210                 return -EINVAL;
211         }
212         nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pools");
213         nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pool@0");
214         do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
215                              "base_icid", FSL_DPAA2_STREAM_ID_START, 1);
216         do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
217                              "num",
218                              FSL_DPAA2_STREAM_ID_END -
219                              FSL_DPAA2_STREAM_ID_START + 1, 1);
220
221         flush_dcache_range(dpc_addr, dpc_addr + fdt_totalsize(blob));
222
223         return 0;
224 }
225
226 static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpc_addr)
227 {
228         u64 mc_dpc_offset;
229 #ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
230         int error;
231         void *dpc_fdt_hdr;
232         int dpc_size;
233 #endif
234
235 #ifdef CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET
236         BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET & 0x3) != 0 ||
237                      CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET > 0xffffffff);
238
239         mc_dpc_offset = CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET;
240 #else
241 #error "CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET not defined"
242 #endif
243
244         /*
245          * Load the MC DPC blob in the MC private DRAM block:
246          */
247 #ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
248         printf("MC DPC is preloaded to %#llx\n", mc_ram_addr + mc_dpc_offset);
249 #else
250         /*
251          * Get address and size of the DPC blob stored in flash:
252          */
253         dpc_fdt_hdr = (void *)mc_dpc_addr;
254
255         error = fdt_check_header(dpc_fdt_hdr);
256         if (error != 0) {
257                 /*
258                  * Don't return with error here, since the MC firmware can
259                  * still boot without a DPC
260                  */
261                 printf("\nfsl-mc: WARNING: No DPC image found");
262                 return 0;
263         }
264
265         dpc_size = fdt_totalsize(dpc_fdt_hdr);
266         if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) {
267                 printf("\nfsl-mc: ERROR: Bad DPC image (too large: %d)\n",
268                        dpc_size);
269                 return -EINVAL;
270         }
271
272         mc_copy_image("MC DPC blob",
273                       (u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset);
274 #endif /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */
275
276         if (mc_fixup_dpc(mc_ram_addr + mc_dpc_offset))
277                 return -EINVAL;
278
279         dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset));
280         return 0;
281 }
282
283 static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpl_addr)
284 {
285         u64 mc_dpl_offset;
286 #ifndef CONFIG_SYS_LS_MC_DPL_IN_DDR
287         int error;
288         void *dpl_fdt_hdr;
289         int dpl_size;
290 #endif
291
292 #ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
293         BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
294                      CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
295
296         mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
297 #else
298 #error "CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET not defined"
299 #endif
300
301         /*
302          * Load the MC DPL blob in the MC private DRAM block:
303          */
304 #ifdef CONFIG_SYS_LS_MC_DPL_IN_DDR
305         printf("MC DPL is preloaded to %#llx\n", mc_ram_addr + mc_dpl_offset);
306 #else
307         /*
308          * Get address and size of the DPL blob stored in flash:
309          */
310         dpl_fdt_hdr = (void *)mc_dpl_addr;
311
312         error = fdt_check_header(dpl_fdt_hdr);
313         if (error != 0) {
314                 printf("\nfsl-mc: ERROR: Bad DPL image (bad header)\n");
315                 return error;
316         }
317
318         dpl_size = fdt_totalsize(dpl_fdt_hdr);
319         if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
320                 printf("\nfsl-mc: ERROR: Bad DPL image (too large: %d)\n",
321                        dpl_size);
322                 return -EINVAL;
323         }
324
325         mc_copy_image("MC DPL blob",
326                       (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
327 #endif /* not defined CONFIG_SYS_LS_MC_DPL_IN_DDR */
328
329         dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset));
330         return 0;
331 }
332
333 /**
334  * Return the MC boot timeout value in milliseconds
335  */
336 static unsigned long get_mc_boot_timeout_ms(void)
337 {
338         unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
339
340         char *timeout_ms_env_var = getenv(MC_BOOT_TIMEOUT_ENV_VAR);
341
342         if (timeout_ms_env_var) {
343                 timeout_ms = simple_strtoul(timeout_ms_env_var, NULL, 10);
344                 if (timeout_ms == 0) {
345                         printf("fsl-mc: WARNING: Invalid value for \'"
346                                MC_BOOT_TIMEOUT_ENV_VAR
347                                "\' environment variable: %lu\n",
348                                timeout_ms);
349
350                         timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
351                 }
352         }
353
354         return timeout_ms;
355 }
356
357 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
358 static int load_mc_aiop_img(u64 aiop_fw_addr)
359 {
360         u64 mc_ram_addr = mc_get_dram_addr();
361 #ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
362         void *aiop_img;
363 #endif
364
365         /*
366          * Load the MC AIOP image in the MC private DRAM block:
367          */
368
369 #ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
370         printf("MC AIOP is preloaded to %#llx\n", mc_ram_addr +
371                CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
372 #else
373         aiop_img = (void *)aiop_fw_addr;
374         mc_copy_image("MC AIOP image",
375                       (u64)aiop_img, CONFIG_SYS_LS_MC_AIOP_IMG_MAX_LENGTH,
376                       mc_ram_addr + CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
377 #endif
378         mc_aiop_applied = 0;
379
380         return 0;
381 }
382 #endif
383
384 static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr)
385 {
386         u32 reg_gsr;
387         u32 mc_fw_boot_status;
388         unsigned long timeout_ms = get_mc_boot_timeout_ms();
389         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
390
391         dmb();
392         assert(timeout_ms > 0);
393         for (;;) {
394                 udelay(1000);   /* throttle polling */
395                 reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
396                 mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
397                 if (mc_fw_boot_status & 0x1)
398                         break;
399
400                 timeout_ms--;
401                 if (timeout_ms == 0)
402                         break;
403         }
404
405         if (timeout_ms == 0) {
406                 printf("ERROR: timeout\n");
407
408                 /* TODO: Get an error status from an MC CCSR register */
409                 return -ETIMEDOUT;
410         }
411
412         if (mc_fw_boot_status != 0x1) {
413                 /*
414                  * TODO: Identify critical errors from the GSR register's FS
415                  * field and for those errors, set error to -ENODEV or other
416                  * appropriate errno, so that the status property is set to
417                  * failure in the fsl,dprc device tree node.
418                  */
419                 printf("WARNING: Firmware returned an error (GSR: %#x)\n",
420                        reg_gsr);
421         } else {
422                 printf("SUCCESS\n");
423         }
424
425
426         *final_reg_gsr = reg_gsr;
427         return 0;
428 }
429
430 int mc_init(u64 mc_fw_addr, u64 mc_dpc_addr)
431 {
432         int error = 0;
433         int portal_id = 0;
434         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
435         u64 mc_ram_addr = mc_get_dram_addr();
436         u32 reg_gsr;
437         u32 reg_mcfbalr;
438 #ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
439         const void *raw_image_addr;
440         size_t raw_image_size = 0;
441 #endif
442         struct mc_version mc_ver_info;
443         u64 mc_ram_aligned_base_addr;
444         u8 mc_ram_num_256mb_blocks;
445         size_t mc_ram_size = mc_get_dram_block_size();
446
447
448         error = calculate_mc_private_ram_params(mc_ram_addr,
449                                                 mc_ram_size,
450                                                 &mc_ram_aligned_base_addr,
451                                                 &mc_ram_num_256mb_blocks);
452         if (error != 0)
453                 goto out;
454
455         /*
456          * Management Complex cores should be held at reset out of POR.
457          * U-boot should be the first software to touch MC. To be safe,
458          * we reset all cores again by setting GCR1 to 0. It doesn't do
459          * anything if they are held at reset. After we setup the firmware
460          * we kick off MC by deasserting the reset bit for core 0, and
461          * deasserting the reset bits for Command Portal Managers.
462          * The stop bits are not touched here. They are used to stop the
463          * cores when they are active. Setting stop bits doesn't stop the
464          * cores from fetching instructions when they are released from
465          * reset.
466          */
467         out_le32(&mc_ccsr_regs->reg_gcr1, 0);
468         dmb();
469
470 #ifdef CONFIG_SYS_LS_MC_FW_IN_DDR
471         printf("MC firmware is preloaded to %#llx\n", mc_ram_addr);
472 #else
473         error = parse_mc_firmware_fit_image(mc_fw_addr, &raw_image_addr,
474                                             &raw_image_size);
475         if (error != 0)
476                 goto out;
477         /*
478          * Load the MC FW at the beginning of the MC private DRAM block:
479          */
480         mc_copy_image("MC Firmware",
481                       (u64)raw_image_addr, raw_image_size, mc_ram_addr);
482 #endif
483         dump_ram_words("firmware", (void *)mc_ram_addr);
484
485         error = load_mc_dpc(mc_ram_addr, mc_ram_size, mc_dpc_addr);
486         if (error != 0)
487                 goto out;
488
489         debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
490         dump_mc_ccsr_regs(mc_ccsr_regs);
491
492         /*
493          * Tell MC what is the address range of the DRAM block assigned to it:
494          */
495         reg_mcfbalr = (u32)mc_ram_aligned_base_addr |
496                       (mc_ram_num_256mb_blocks - 1);
497         out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr);
498         out_le32(&mc_ccsr_regs->reg_mcfbahr,
499                  (u32)(mc_ram_aligned_base_addr >> 32));
500         out_le32(&mc_ccsr_regs->reg_mcfapr, FSL_BYPASS_AMQ);
501
502         /*
503          * Tell the MC that we want delayed DPL deployment.
504          */
505         out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00);
506
507         printf("\nfsl-mc: Booting Management Complex ... ");
508
509         /*
510          * Deassert reset and release MC core 0 to run
511          */
512         out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
513         error = wait_for_mc(true, &reg_gsr);
514         if (error != 0)
515                 goto out;
516
517         /*
518          * TODO: need to obtain the portal_id for the root container from the
519          * DPL
520          */
521         portal_id = 0;
522
523         /*
524          * Initialize the global default MC portal
525          * And check that the MC firmware is responding portal commands:
526          */
527         root_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
528         if (!root_mc_io) {
529                 printf(" No memory: malloc() failed\n");
530                 return -ENOMEM;
531         }
532
533         root_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
534         debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
535               portal_id, root_mc_io->mmio_regs);
536
537         error = mc_get_version(root_mc_io, MC_CMD_NO_FLAGS, &mc_ver_info);
538         if (error != 0) {
539                 printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n",
540                        error);
541                 goto out;
542         }
543
544         if (MC_VER_MAJOR != mc_ver_info.major) {
545                 printf("fsl-mc: ERROR: Firmware major version mismatch (found: %d, expected: %d)\n",
546                        mc_ver_info.major, MC_VER_MAJOR);
547                 printf("fsl-mc: Update the Management Complex firmware\n");
548
549                 error = -ENODEV;
550                 goto out;
551         }
552
553         if (MC_VER_MINOR != mc_ver_info.minor)
554                 printf("fsl-mc: WARNING: Firmware minor version mismatch (found: %d, expected: %d)\n",
555                        mc_ver_info.minor, MC_VER_MINOR);
556
557         printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n",
558                mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision,
559                reg_gsr & GSR_FS_MASK);
560
561 out:
562         if (error != 0)
563                 mc_boot_status = error;
564         else
565                 mc_boot_status = 0;
566
567         return error;
568 }
569
570 int mc_apply_dpl(u64 mc_dpl_addr)
571 {
572         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
573         int error = 0;
574         u32 reg_gsr;
575         u64 mc_ram_addr = mc_get_dram_addr();
576         size_t mc_ram_size = mc_get_dram_block_size();
577
578         error = load_mc_dpl(mc_ram_addr, mc_ram_size, mc_dpl_addr);
579         if (error != 0)
580                 return error;
581
582         /*
583          * Tell the MC to deploy the DPL:
584          */
585         out_le32(&mc_ccsr_regs->reg_gsr, 0x0);
586         printf("fsl-mc: Deploying data path layout ... ");
587         error = wait_for_mc(false, &reg_gsr);
588
589         if (!error)
590                 mc_dpl_applied = 0;
591
592         return error;
593 }
594
595 int get_mc_boot_status(void)
596 {
597         return mc_boot_status;
598 }
599
600 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
601 int get_aiop_apply_status(void)
602 {
603         return mc_aiop_applied;
604 }
605 #endif
606
607 int get_dpl_apply_status(void)
608 {
609         return mc_dpl_applied;
610 }
611
612 /**
613  * Return the MC address of private DRAM block.
614  */
615 u64 mc_get_dram_addr(void)
616 {
617         u64 mc_ram_addr;
618
619         /*
620          * The MC private DRAM block was already carved at the end of DRAM
621          * by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE:
622          */
623         if (gd->bd->bi_dram[1].start) {
624                 mc_ram_addr =
625                         gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size;
626         } else {
627                 mc_ram_addr =
628                         gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
629         }
630
631         return mc_ram_addr;
632 }
633
634 /**
635  * Return the actual size of the MC private DRAM block.
636  */
637 unsigned long mc_get_dram_block_size(void)
638 {
639         unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
640
641         char *dram_block_size_env_var = getenv(MC_MEM_SIZE_ENV_VAR);
642
643         if (dram_block_size_env_var) {
644                 dram_block_size = simple_strtoul(dram_block_size_env_var, NULL,
645                                                  10);
646
647                 if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
648                         printf("fsl-mc: WARNING: Invalid value for \'"
649                                MC_MEM_SIZE_ENV_VAR
650                                "\' environment variable: %lu\n",
651                                dram_block_size);
652
653                         dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
654                 }
655         }
656
657         return dram_block_size;
658 }
659
660 int fsl_mc_ldpaa_init(bd_t *bis)
661 {
662         int i;
663
664         for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++)
665                 if ((wriop_is_enabled_dpmac(i) == 1) &&
666                     (wriop_get_phy_address(i) != -1))
667                         ldpaa_eth_init(i, wriop_get_enet_if(i));
668         return 0;
669 }
670
671 static int dpio_init(void)
672 {
673         struct qbman_swp_desc p_des;
674         struct dpio_attr attr;
675         struct dpio_cfg dpio_cfg;
676         int err = 0;
677
678         dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj));
679         if (!dflt_dpio) {
680                 printf("No memory: malloc() failed\n");
681                 err = -ENOMEM;
682                 goto err_malloc;
683         }
684
685         dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL;
686         dpio_cfg.num_priorities = 8;
687
688         err = dpio_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpio_cfg,
689                           &dflt_dpio->dpio_handle);
690         if (err < 0) {
691                 printf("dpio_create() failed: %d\n", err);
692                 err = -ENODEV;
693                 goto err_create;
694         }
695
696         memset(&attr, 0, sizeof(struct dpio_attr));
697         err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
698                                   dflt_dpio->dpio_handle, &attr);
699         if (err < 0) {
700                 printf("dpio_get_attributes() failed: %d\n", err);
701                 goto err_get_attr;
702         }
703
704         dflt_dpio->dpio_id = attr.id;
705 #ifdef DEBUG
706         printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id);
707 #endif
708
709         err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
710         if (err < 0) {
711                 printf("dpio_enable() failed %d\n", err);
712                 goto err_get_enable;
713         }
714         debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n",
715               attr.qbman_portal_ce_offset,
716               attr.qbman_portal_ci_offset,
717               attr.qbman_portal_id,
718               attr.num_priorities);
719
720         p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
721                                         + attr.qbman_portal_ce_offset);
722         p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
723                                         + attr.qbman_portal_ci_offset);
724
725         dflt_dpio->sw_portal = qbman_swp_init(&p_des);
726         if (dflt_dpio->sw_portal == NULL) {
727                 printf("qbman_swp_init() failed\n");
728                 goto err_get_swp_init;
729         }
730         return 0;
731
732 err_get_swp_init:
733         dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
734 err_get_enable:
735         free(dflt_dpio);
736 err_get_attr:
737         dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
738         dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
739 err_create:
740 err_malloc:
741         return err;
742 }
743
744 static int dpio_exit(void)
745 {
746         int err;
747
748         err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
749         if (err < 0) {
750                 printf("dpio_disable() failed: %d\n", err);
751                 goto err;
752         }
753
754         err = dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
755         if (err < 0) {
756                 printf("dpio_destroy() failed: %d\n", err);
757                 goto err;
758         }
759
760 #ifdef DEBUG
761         printf("Exit: DPIO id=0x%d\n", dflt_dpio->dpio_id);
762 #endif
763
764         if (dflt_dpio)
765                 free(dflt_dpio);
766
767         return 0;
768 err:
769         return err;
770 }
771
772 static int dprc_init(void)
773 {
774         int err, child_portal_id, container_id;
775         struct dprc_cfg cfg;
776         uint64_t mc_portal_offset;
777
778         /* Open root container */
779         err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id);
780         if (err < 0) {
781                 printf("dprc_get_container_id(): Root failed: %d\n", err);
782                 goto err_root_container_id;
783         }
784
785 #ifdef DEBUG
786         printf("Root container id = %d\n", container_id);
787 #endif
788         err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id,
789                         &root_dprc_handle);
790         if (err < 0) {
791                 printf("dprc_open(): Root Container failed: %d\n", err);
792                 goto err_root_open;
793         }
794
795         if (!root_dprc_handle) {
796                 printf("dprc_open(): Root Container Handle is not valid\n");
797                 goto err_root_open;
798         }
799
800         cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED |
801                       DPRC_CFG_OPT_OBJ_CREATE_ALLOWED |
802                       DPRC_CFG_OPT_ALLOC_ALLOWED;
803         cfg.icid = DPRC_GET_ICID_FROM_POOL;
804         cfg.portal_id = 250;
805         err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS,
806                         root_dprc_handle,
807                         &cfg,
808                         &child_dprc_id,
809                         &mc_portal_offset);
810         if (err < 0) {
811                 printf("dprc_create_container() failed: %d\n", err);
812                 goto err_create;
813         }
814
815         dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
816         if (!dflt_mc_io) {
817                 err  = -ENOMEM;
818                 printf(" No memory: malloc() failed\n");
819                 goto err_malloc;
820         }
821
822         child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset);
823         dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id);
824 #ifdef DEBUG
825         printf("MC portal of child DPRC container: %d, physical addr %p)\n",
826                child_dprc_id, dflt_mc_io->mmio_regs);
827 #endif
828
829         err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id,
830                         &dflt_dprc_handle);
831         if (err < 0) {
832                 printf("dprc_open(): Child container failed: %d\n", err);
833                 goto err_child_open;
834         }
835
836         if (!dflt_dprc_handle) {
837                 printf("dprc_open(): Child container Handle is not valid\n");
838                 goto err_child_open;
839         }
840
841         return 0;
842 err_child_open:
843         free(dflt_mc_io);
844 err_malloc:
845         dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
846                                root_dprc_handle, child_dprc_id);
847 err_create:
848         dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
849 err_root_open:
850 err_root_container_id:
851         return err;
852 }
853
854 static int dprc_exit(void)
855 {
856         int err;
857
858         err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle);
859         if (err < 0) {
860                 printf("dprc_close(): Child failed: %d\n", err);
861                 goto err;
862         }
863
864         err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
865                                      root_dprc_handle, child_dprc_id);
866         if (err < 0) {
867                 printf("dprc_destroy_container() failed: %d\n", err);
868                 goto err;
869         }
870
871         err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
872         if (err < 0) {
873                 printf("dprc_close(): Root failed: %d\n", err);
874                 goto err;
875         }
876
877         if (dflt_mc_io)
878                 free(dflt_mc_io);
879
880         if (root_mc_io)
881                 free(root_mc_io);
882
883         return 0;
884
885 err:
886         return err;
887 }
888
889 static int dpbp_init(void)
890 {
891         int err;
892         struct dpbp_attr dpbp_attr;
893         struct dpbp_cfg dpbp_cfg;
894
895         dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj));
896         if (!dflt_dpbp) {
897                 printf("No memory: malloc() failed\n");
898                 err = -ENOMEM;
899                 goto err_malloc;
900         }
901
902         dpbp_cfg.options = 512;
903
904         err = dpbp_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpbp_cfg,
905                           &dflt_dpbp->dpbp_handle);
906
907         if (err < 0) {
908                 err = -ENODEV;
909                 printf("dpbp_create() failed: %d\n", err);
910                 goto err_create;
911         }
912
913         memset(&dpbp_attr, 0, sizeof(struct dpbp_attr));
914         err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
915                                   dflt_dpbp->dpbp_handle,
916                                   &dpbp_attr);
917         if (err < 0) {
918                 printf("dpbp_get_attributes() failed: %d\n", err);
919                 goto err_get_attr;
920         }
921
922         dflt_dpbp->dpbp_attr.id = dpbp_attr.id;
923 #ifdef DEBUG
924         printf("Init: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
925 #endif
926
927         err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
928         if (err < 0) {
929                 printf("dpbp_close() failed: %d\n", err);
930                 goto err_close;
931         }
932
933         return 0;
934
935 err_close:
936         free(dflt_dpbp);
937 err_get_attr:
938         dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
939         dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
940 err_create:
941 err_malloc:
942         return err;
943 }
944
945 static int dpbp_exit(void)
946 {
947         int err;
948
949         err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
950                         &dflt_dpbp->dpbp_handle);
951         if (err < 0) {
952                 printf("dpbp_open() failed: %d\n", err);
953                 goto err;
954         }
955
956         err = dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
957                            dflt_dpbp->dpbp_handle);
958         if (err < 0) {
959                 printf("dpbp_destroy() failed: %d\n", err);
960                 goto err;
961         }
962
963 #ifdef DEBUG
964         printf("Exit: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
965 #endif
966
967         if (dflt_dpbp)
968                 free(dflt_dpbp);
969         return 0;
970
971 err:
972         return err;
973 }
974
975 static int dpni_init(void)
976 {
977         int err;
978         struct dpni_attr dpni_attr;
979         struct dpni_cfg dpni_cfg;
980
981         dflt_dpni = (struct fsl_dpni_obj *)malloc(sizeof(struct fsl_dpni_obj));
982         if (!dflt_dpni) {
983                 printf("No memory: malloc() failed\n");
984                 err = -ENOMEM;
985                 goto err_malloc;
986         }
987
988         memset(&dpni_cfg, 0, sizeof(dpni_cfg));
989         dpni_cfg.adv.options = DPNI_OPT_UNICAST_FILTER |
990                                DPNI_OPT_MULTICAST_FILTER;
991
992         err = dpni_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpni_cfg,
993                           &dflt_dpni->dpni_handle);
994
995         if (err < 0) {
996                 err = -ENODEV;
997                 printf("dpni_create() failed: %d\n", err);
998                 goto err_create;
999         }
1000
1001         memset(&dpni_attr, 0, sizeof(struct dpni_attr));
1002         err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1003                                   dflt_dpni->dpni_handle,
1004                                   &dpni_attr);
1005         if (err < 0) {
1006                 printf("dpni_get_attributes() failed: %d\n", err);
1007                 goto err_get_attr;
1008         }
1009
1010         dflt_dpni->dpni_id = dpni_attr.id;
1011 #ifdef DEBUG
1012         printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1013 #endif
1014
1015         err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1016         if (err < 0) {
1017                 printf("dpni_close() failed: %d\n", err);
1018                 goto err_close;
1019         }
1020
1021         return 0;
1022
1023 err_close:
1024         free(dflt_dpni);
1025 err_get_attr:
1026         dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1027         dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1028 err_create:
1029 err_malloc:
1030         return err;
1031 }
1032
1033 static int dpni_exit(void)
1034 {
1035         int err;
1036
1037         err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
1038                         &dflt_dpni->dpni_handle);
1039         if (err < 0) {
1040                 printf("dpni_open() failed: %d\n", err);
1041                 goto err;
1042         }
1043
1044         err = dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
1045                            dflt_dpni->dpni_handle);
1046         if (err < 0) {
1047                 printf("dpni_destroy() failed: %d\n", err);
1048                 goto err;
1049         }
1050
1051 #ifdef DEBUG
1052         printf("Exit: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1053 #endif
1054
1055         if (dflt_dpni)
1056                 free(dflt_dpni);
1057         return 0;
1058
1059 err:
1060         return err;
1061 }
1062
1063 static int mc_init_object(void)
1064 {
1065         int err = 0;
1066
1067         err = dprc_init();
1068         if (err < 0) {
1069                 printf("dprc_init() failed: %d\n", err);
1070                 goto err;
1071         }
1072
1073         err = dpbp_init();
1074         if (err < 0) {
1075                 printf("dpbp_init() failed: %d\n", err);
1076                 goto err;
1077         }
1078
1079         err = dpio_init();
1080         if (err < 0) {
1081                 printf("dpio_init() failed: %d\n", err);
1082                 goto err;
1083         }
1084
1085         err = dpni_init();
1086         if (err < 0) {
1087                 printf("dpni_init() failed: %d\n", err);
1088                 goto err;
1089         }
1090
1091         return 0;
1092 err:
1093         return err;
1094 }
1095
1096 int fsl_mc_ldpaa_exit(bd_t *bd)
1097 {
1098         int err = 0;
1099
1100         if (bd && get_mc_boot_status() == -1)
1101                 return 0;
1102
1103         if (bd && !get_mc_boot_status() && get_dpl_apply_status() == -1) {
1104                 printf("ERROR: fsl-mc: DPL is not applied\n");
1105                 err = -ENODEV;
1106                 return err;
1107         }
1108
1109         if (bd && !get_mc_boot_status() && !get_dpl_apply_status())
1110                 return err;
1111
1112         err = dpbp_exit();
1113         if (err < 0) {
1114                 printf("dpni_exit() failed: %d\n", err);
1115                 goto err;
1116         }
1117
1118         err = dpio_exit();
1119         if (err < 0) {
1120                 printf("dpio_exit() failed: %d\n", err);
1121                 goto err;
1122         }
1123
1124         err = dpni_exit();
1125         if (err < 0) {
1126                 printf("dpni_exit() failed: %d\n", err);
1127                 goto err;
1128         }
1129
1130         err = dprc_exit();
1131         if (err < 0) {
1132                 printf("dprc_exit() failed: %d\n", err);
1133                 goto err;
1134         }
1135
1136         return 0;
1137 err:
1138         return err;
1139 }
1140
1141 static int do_fsl_mc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1142 {
1143         int err = 0;
1144         if (argc < 3)
1145                 goto usage;
1146
1147         switch (argv[1][0]) {
1148         case 's': {
1149                         char sub_cmd;
1150                         u64 mc_fw_addr, mc_dpc_addr;
1151 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1152                         u64 aiop_fw_addr;
1153 #endif
1154
1155                         sub_cmd = argv[2][0];
1156                         switch (sub_cmd) {
1157                         case 'm':
1158                                 if (argc < 5)
1159                                         goto usage;
1160
1161                                 if (get_mc_boot_status() == 0) {
1162                                         printf("fsl-mc: MC is already booted");
1163                                         printf("\n");
1164                                         return err;
1165                                 }
1166                                 mc_fw_addr = simple_strtoull(argv[3], NULL, 16);
1167                                 mc_dpc_addr = simple_strtoull(argv[4], NULL,
1168                                                               16);
1169
1170                                 if (!mc_init(mc_fw_addr, mc_dpc_addr))
1171                                         err = mc_init_object();
1172                                 break;
1173
1174 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1175                         case 'a':
1176                                 if (argc < 4)
1177                                         goto usage;
1178                                 if (get_aiop_apply_status() == 0) {
1179                                         printf("fsl-mc: AIOP FW is already");
1180                                         printf(" applied\n");
1181                                         return err;
1182                                 }
1183
1184                                 aiop_fw_addr = simple_strtoull(argv[3], NULL,
1185                                                                16);
1186
1187                                 err = load_mc_aiop_img(aiop_fw_addr);
1188                                 if (!err)
1189                                         printf("fsl-mc: AIOP FW applied\n");
1190                                 break;
1191 #endif
1192                         default:
1193                                 printf("Invalid option: %s\n", argv[2]);
1194                                 goto usage;
1195
1196                                 break;
1197                         }
1198                 }
1199                 break;
1200
1201         case 'a': {
1202                         u64 mc_dpl_addr;
1203
1204                         if (argc < 4)
1205                                 goto usage;
1206
1207                         if (get_dpl_apply_status() == 0) {
1208                                 printf("fsl-mc: DPL already applied\n");
1209                                 return err;
1210                         }
1211
1212                         mc_dpl_addr = simple_strtoull(argv[3], NULL,
1213                                                               16);
1214
1215                         if (get_mc_boot_status() != 0) {
1216                                 printf("fsl-mc: Deploying data path layout ..");
1217                                 printf("ERROR (MC is not booted)\n");
1218                                 return -ENODEV;
1219                         }
1220
1221                         if (!fsl_mc_ldpaa_exit(NULL))
1222                                 err = mc_apply_dpl(mc_dpl_addr);
1223                         break;
1224                 }
1225         default:
1226                 printf("Invalid option: %s\n", argv[1]);
1227                 goto usage;
1228                 break;
1229         }
1230         return err;
1231  usage:
1232         return CMD_RET_USAGE;
1233 }
1234
1235 U_BOOT_CMD(
1236         fsl_mc,  CONFIG_SYS_MAXARGS,  1,   do_fsl_mc,
1237         "DPAA2 command to manage Management Complex (MC)",
1238         "start mc [FW_addr] [DPC_addr] - Start Management Complex\n"
1239         "fsl_mc apply DPL [DPL_addr] - Apply DPL file\n"
1240         "fsl_mc start aiop [FW_addr] - Start AIOP\n"
1241 );