Merge branch 'master' of git://git.denx.de/u-boot-usb
[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         printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n",
545                mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision,
546                reg_gsr & GSR_FS_MASK);
547
548 out:
549         if (error != 0)
550                 mc_boot_status = error;
551         else
552                 mc_boot_status = 0;
553
554         return error;
555 }
556
557 int mc_apply_dpl(u64 mc_dpl_addr)
558 {
559         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
560         int error = 0;
561         u32 reg_gsr;
562         u64 mc_ram_addr = mc_get_dram_addr();
563         size_t mc_ram_size = mc_get_dram_block_size();
564
565         error = load_mc_dpl(mc_ram_addr, mc_ram_size, mc_dpl_addr);
566         if (error != 0)
567                 return error;
568
569         /*
570          * Tell the MC to deploy the DPL:
571          */
572         out_le32(&mc_ccsr_regs->reg_gsr, 0x0);
573         printf("fsl-mc: Deploying data path layout ... ");
574         error = wait_for_mc(false, &reg_gsr);
575
576         if (!error)
577                 mc_dpl_applied = 0;
578
579         return error;
580 }
581
582 int get_mc_boot_status(void)
583 {
584         return mc_boot_status;
585 }
586
587 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
588 int get_aiop_apply_status(void)
589 {
590         return mc_aiop_applied;
591 }
592 #endif
593
594 int get_dpl_apply_status(void)
595 {
596         return mc_dpl_applied;
597 }
598
599 /**
600  * Return the MC address of private DRAM block.
601  */
602 u64 mc_get_dram_addr(void)
603 {
604         u64 mc_ram_addr;
605
606         /*
607          * The MC private DRAM block was already carved at the end of DRAM
608          * by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE:
609          */
610         if (gd->bd->bi_dram[1].start) {
611                 mc_ram_addr =
612                         gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size;
613         } else {
614                 mc_ram_addr =
615                         gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
616         }
617
618         return mc_ram_addr;
619 }
620
621 /**
622  * Return the actual size of the MC private DRAM block.
623  */
624 unsigned long mc_get_dram_block_size(void)
625 {
626         unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
627
628         char *dram_block_size_env_var = getenv(MC_MEM_SIZE_ENV_VAR);
629
630         if (dram_block_size_env_var) {
631                 dram_block_size = simple_strtoul(dram_block_size_env_var, NULL,
632                                                  10);
633
634                 if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
635                         printf("fsl-mc: WARNING: Invalid value for \'"
636                                MC_MEM_SIZE_ENV_VAR
637                                "\' environment variable: %lu\n",
638                                dram_block_size);
639
640                         dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
641                 }
642         }
643
644         return dram_block_size;
645 }
646
647 int fsl_mc_ldpaa_init(bd_t *bis)
648 {
649         int i;
650
651         for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++)
652                 if ((wriop_is_enabled_dpmac(i) == 1) &&
653                     (wriop_get_phy_address(i) != -1))
654                         ldpaa_eth_init(i, wriop_get_enet_if(i));
655         return 0;
656 }
657
658 static int dpio_init(void)
659 {
660         struct qbman_swp_desc p_des;
661         struct dpio_attr attr;
662         struct dpio_cfg dpio_cfg;
663         int err = 0;
664
665         dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj));
666         if (!dflt_dpio) {
667                 printf("No memory: malloc() failed\n");
668                 err = -ENOMEM;
669                 goto err_malloc;
670         }
671
672         dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL;
673         dpio_cfg.num_priorities = 8;
674
675         err = dpio_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpio_cfg,
676                           &dflt_dpio->dpio_handle);
677         if (err < 0) {
678                 printf("dpio_create() failed: %d\n", err);
679                 err = -ENODEV;
680                 goto err_create;
681         }
682
683         memset(&attr, 0, sizeof(struct dpio_attr));
684         err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
685                                   dflt_dpio->dpio_handle, &attr);
686         if (err < 0) {
687                 printf("dpio_get_attributes() failed: %d\n", err);
688                 goto err_get_attr;
689         }
690
691         dflt_dpio->dpio_id = attr.id;
692 #ifdef DEBUG
693         printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id);
694 #endif
695
696         err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
697         if (err < 0) {
698                 printf("dpio_enable() failed %d\n", err);
699                 goto err_get_enable;
700         }
701         debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n",
702               attr.qbman_portal_ce_offset,
703               attr.qbman_portal_ci_offset,
704               attr.qbman_portal_id,
705               attr.num_priorities);
706
707         p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
708                                         + attr.qbman_portal_ce_offset);
709         p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
710                                         + attr.qbman_portal_ci_offset);
711
712         dflt_dpio->sw_portal = qbman_swp_init(&p_des);
713         if (dflt_dpio->sw_portal == NULL) {
714                 printf("qbman_swp_init() failed\n");
715                 goto err_get_swp_init;
716         }
717         return 0;
718
719 err_get_swp_init:
720         dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
721 err_get_enable:
722         free(dflt_dpio);
723 err_get_attr:
724         dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
725         dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
726 err_create:
727 err_malloc:
728         return err;
729 }
730
731 static int dpio_exit(void)
732 {
733         int err;
734
735         err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
736         if (err < 0) {
737                 printf("dpio_disable() failed: %d\n", err);
738                 goto err;
739         }
740
741         err = dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
742         if (err < 0) {
743                 printf("dpio_destroy() failed: %d\n", err);
744                 goto err;
745         }
746
747 #ifdef DEBUG
748         printf("Exit: DPIO id=0x%d\n", dflt_dpio->dpio_id);
749 #endif
750
751         if (dflt_dpio)
752                 free(dflt_dpio);
753
754         return 0;
755 err:
756         return err;
757 }
758
759 static int dprc_init(void)
760 {
761         int err, child_portal_id, container_id;
762         struct dprc_cfg cfg;
763         uint64_t mc_portal_offset;
764
765         /* Open root container */
766         err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id);
767         if (err < 0) {
768                 printf("dprc_get_container_id(): Root failed: %d\n", err);
769                 goto err_root_container_id;
770         }
771
772 #ifdef DEBUG
773         printf("Root container id = %d\n", container_id);
774 #endif
775         err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id,
776                         &root_dprc_handle);
777         if (err < 0) {
778                 printf("dprc_open(): Root Container failed: %d\n", err);
779                 goto err_root_open;
780         }
781
782         if (!root_dprc_handle) {
783                 printf("dprc_open(): Root Container Handle is not valid\n");
784                 goto err_root_open;
785         }
786
787         cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED |
788                       DPRC_CFG_OPT_OBJ_CREATE_ALLOWED |
789                       DPRC_CFG_OPT_ALLOC_ALLOWED;
790         cfg.icid = DPRC_GET_ICID_FROM_POOL;
791         cfg.portal_id = 250;
792         err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS,
793                         root_dprc_handle,
794                         &cfg,
795                         &child_dprc_id,
796                         &mc_portal_offset);
797         if (err < 0) {
798                 printf("dprc_create_container() failed: %d\n", err);
799                 goto err_create;
800         }
801
802         dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
803         if (!dflt_mc_io) {
804                 err  = -ENOMEM;
805                 printf(" No memory: malloc() failed\n");
806                 goto err_malloc;
807         }
808
809         child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset);
810         dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id);
811 #ifdef DEBUG
812         printf("MC portal of child DPRC container: %d, physical addr %p)\n",
813                child_dprc_id, dflt_mc_io->mmio_regs);
814 #endif
815
816         err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id,
817                         &dflt_dprc_handle);
818         if (err < 0) {
819                 printf("dprc_open(): Child container failed: %d\n", err);
820                 goto err_child_open;
821         }
822
823         if (!dflt_dprc_handle) {
824                 printf("dprc_open(): Child container Handle is not valid\n");
825                 goto err_child_open;
826         }
827
828         return 0;
829 err_child_open:
830         free(dflt_mc_io);
831 err_malloc:
832         dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
833                                root_dprc_handle, child_dprc_id);
834 err_create:
835         dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
836 err_root_open:
837 err_root_container_id:
838         return err;
839 }
840
841 static int dprc_exit(void)
842 {
843         int err;
844
845         err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle);
846         if (err < 0) {
847                 printf("dprc_close(): Child failed: %d\n", err);
848                 goto err;
849         }
850
851         err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
852                                      root_dprc_handle, child_dprc_id);
853         if (err < 0) {
854                 printf("dprc_destroy_container() failed: %d\n", err);
855                 goto err;
856         }
857
858         err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
859         if (err < 0) {
860                 printf("dprc_close(): Root failed: %d\n", err);
861                 goto err;
862         }
863
864         if (dflt_mc_io)
865                 free(dflt_mc_io);
866
867         if (root_mc_io)
868                 free(root_mc_io);
869
870         return 0;
871
872 err:
873         return err;
874 }
875
876 static int dpbp_init(void)
877 {
878         int err;
879         struct dpbp_attr dpbp_attr;
880         struct dpbp_cfg dpbp_cfg;
881
882         dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj));
883         if (!dflt_dpbp) {
884                 printf("No memory: malloc() failed\n");
885                 err = -ENOMEM;
886                 goto err_malloc;
887         }
888
889         dpbp_cfg.options = 512;
890
891         err = dpbp_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpbp_cfg,
892                           &dflt_dpbp->dpbp_handle);
893
894         if (err < 0) {
895                 err = -ENODEV;
896                 printf("dpbp_create() failed: %d\n", err);
897                 goto err_create;
898         }
899
900         memset(&dpbp_attr, 0, sizeof(struct dpbp_attr));
901         err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
902                                   dflt_dpbp->dpbp_handle,
903                                   &dpbp_attr);
904         if (err < 0) {
905                 printf("dpbp_get_attributes() failed: %d\n", err);
906                 goto err_get_attr;
907         }
908
909         dflt_dpbp->dpbp_attr.id = dpbp_attr.id;
910 #ifdef DEBUG
911         printf("Init: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
912 #endif
913
914         err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
915         if (err < 0) {
916                 printf("dpbp_close() failed: %d\n", err);
917                 goto err_close;
918         }
919
920         return 0;
921
922 err_close:
923         free(dflt_dpbp);
924 err_get_attr:
925         dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
926         dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
927 err_create:
928 err_malloc:
929         return err;
930 }
931
932 static int dpbp_exit(void)
933 {
934         int err;
935
936         err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
937                         &dflt_dpbp->dpbp_handle);
938         if (err < 0) {
939                 printf("dpbp_open() failed: %d\n", err);
940                 goto err;
941         }
942
943         err = dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
944                            dflt_dpbp->dpbp_handle);
945         if (err < 0) {
946                 printf("dpbp_destroy() failed: %d\n", err);
947                 goto err;
948         }
949
950 #ifdef DEBUG
951         printf("Exit: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
952 #endif
953
954         if (dflt_dpbp)
955                 free(dflt_dpbp);
956         return 0;
957
958 err:
959         return err;
960 }
961
962 static int dpni_init(void)
963 {
964         int err;
965         struct dpni_attr dpni_attr;
966         struct dpni_cfg dpni_cfg;
967
968         dflt_dpni = (struct fsl_dpni_obj *)malloc(sizeof(struct fsl_dpni_obj));
969         if (!dflt_dpni) {
970                 printf("No memory: malloc() failed\n");
971                 err = -ENOMEM;
972                 goto err_malloc;
973         }
974
975         memset(&dpni_cfg, 0, sizeof(dpni_cfg));
976         dpni_cfg.adv.options = DPNI_OPT_UNICAST_FILTER |
977                                DPNI_OPT_MULTICAST_FILTER;
978
979         err = dpni_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpni_cfg,
980                           &dflt_dpni->dpni_handle);
981
982         if (err < 0) {
983                 err = -ENODEV;
984                 printf("dpni_create() failed: %d\n", err);
985                 goto err_create;
986         }
987
988         memset(&dpni_attr, 0, sizeof(struct dpni_attr));
989         err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
990                                   dflt_dpni->dpni_handle,
991                                   &dpni_attr);
992         if (err < 0) {
993                 printf("dpni_get_attributes() failed: %d\n", err);
994                 goto err_get_attr;
995         }
996
997         dflt_dpni->dpni_id = dpni_attr.id;
998 #ifdef DEBUG
999         printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1000 #endif
1001
1002         err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1003         if (err < 0) {
1004                 printf("dpni_close() failed: %d\n", err);
1005                 goto err_close;
1006         }
1007
1008         return 0;
1009
1010 err_close:
1011         free(dflt_dpni);
1012 err_get_attr:
1013         dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1014         dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1015 err_create:
1016 err_malloc:
1017         return err;
1018 }
1019
1020 static int dpni_exit(void)
1021 {
1022         int err;
1023
1024         err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
1025                         &dflt_dpni->dpni_handle);
1026         if (err < 0) {
1027                 printf("dpni_open() failed: %d\n", err);
1028                 goto err;
1029         }
1030
1031         err = dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
1032                            dflt_dpni->dpni_handle);
1033         if (err < 0) {
1034                 printf("dpni_destroy() failed: %d\n", err);
1035                 goto err;
1036         }
1037
1038 #ifdef DEBUG
1039         printf("Exit: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1040 #endif
1041
1042         if (dflt_dpni)
1043                 free(dflt_dpni);
1044         return 0;
1045
1046 err:
1047         return err;
1048 }
1049
1050 static int mc_init_object(void)
1051 {
1052         int err = 0;
1053
1054         err = dprc_init();
1055         if (err < 0) {
1056                 printf("dprc_init() failed: %d\n", err);
1057                 goto err;
1058         }
1059
1060         err = dpbp_init();
1061         if (err < 0) {
1062                 printf("dpbp_init() failed: %d\n", err);
1063                 goto err;
1064         }
1065
1066         err = dpio_init();
1067         if (err < 0) {
1068                 printf("dpio_init() failed: %d\n", err);
1069                 goto err;
1070         }
1071
1072         err = dpni_init();
1073         if (err < 0) {
1074                 printf("dpni_init() failed: %d\n", err);
1075                 goto err;
1076         }
1077
1078         return 0;
1079 err:
1080         return err;
1081 }
1082
1083 int fsl_mc_ldpaa_exit(bd_t *bd)
1084 {
1085         int err = 0;
1086
1087         if (bd && get_mc_boot_status() == -1)
1088                 return 0;
1089
1090         if (bd && !get_mc_boot_status() && get_dpl_apply_status() == -1) {
1091                 printf("ERROR: fsl-mc: DPL is not applied\n");
1092                 err = -ENODEV;
1093                 return err;
1094         }
1095
1096         if (bd && !get_mc_boot_status() && !get_dpl_apply_status())
1097                 return err;
1098
1099         err = dpbp_exit();
1100         if (err < 0) {
1101                 printf("dpni_exit() failed: %d\n", err);
1102                 goto err;
1103         }
1104
1105         err = dpio_exit();
1106         if (err < 0) {
1107                 printf("dpio_exit() failed: %d\n", err);
1108                 goto err;
1109         }
1110
1111         err = dpni_exit();
1112         if (err < 0) {
1113                 printf("dpni_exit() failed: %d\n", err);
1114                 goto err;
1115         }
1116
1117         err = dprc_exit();
1118         if (err < 0) {
1119                 printf("dprc_exit() failed: %d\n", err);
1120                 goto err;
1121         }
1122
1123         return 0;
1124 err:
1125         return err;
1126 }
1127
1128 static int do_fsl_mc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1129 {
1130         int err = 0;
1131         if (argc < 3)
1132                 goto usage;
1133
1134         switch (argv[1][0]) {
1135         case 's': {
1136                         char sub_cmd;
1137                         u64 mc_fw_addr, mc_dpc_addr;
1138 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1139                         u64 aiop_fw_addr;
1140 #endif
1141
1142                         sub_cmd = argv[2][0];
1143                         switch (sub_cmd) {
1144                         case 'm':
1145                                 if (argc < 5)
1146                                         goto usage;
1147
1148                                 if (get_mc_boot_status() == 0) {
1149                                         printf("fsl-mc: MC is already booted");
1150                                         printf("\n");
1151                                         return err;
1152                                 }
1153                                 mc_fw_addr = simple_strtoull(argv[3], NULL, 16);
1154                                 mc_dpc_addr = simple_strtoull(argv[4], NULL,
1155                                                               16);
1156
1157                                 if (!mc_init(mc_fw_addr, mc_dpc_addr))
1158                                         err = mc_init_object();
1159                                 break;
1160
1161 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1162                         case 'a':
1163                                 if (argc < 4)
1164                                         goto usage;
1165                                 if (get_aiop_apply_status() == 0) {
1166                                         printf("fsl-mc: AIOP FW is already");
1167                                         printf(" applied\n");
1168                                         return err;
1169                                 }
1170
1171                                 aiop_fw_addr = simple_strtoull(argv[3], NULL,
1172                                                                16);
1173
1174                                 err = load_mc_aiop_img(aiop_fw_addr);
1175                                 if (!err)
1176                                         printf("fsl-mc: AIOP FW applied\n");
1177                                 break;
1178 #endif
1179                         default:
1180                                 printf("Invalid option: %s\n", argv[2]);
1181                                 goto usage;
1182
1183                                 break;
1184                         }
1185                 }
1186                 break;
1187
1188         case 'a': {
1189                         u64 mc_dpl_addr;
1190
1191                         if (argc < 4)
1192                                 goto usage;
1193
1194                         if (get_dpl_apply_status() == 0) {
1195                                 printf("fsl-mc: DPL already applied\n");
1196                                 return err;
1197                         }
1198
1199                         mc_dpl_addr = simple_strtoull(argv[3], NULL,
1200                                                               16);
1201
1202                         if (get_mc_boot_status() != 0) {
1203                                 printf("fsl-mc: Deploying data path layout ..");
1204                                 printf("ERROR (MC is not booted)\n");
1205                                 return -ENODEV;
1206                         }
1207
1208                         if (!fsl_mc_ldpaa_exit(NULL))
1209                                 err = mc_apply_dpl(mc_dpl_addr);
1210                         break;
1211                 }
1212         default:
1213                 printf("Invalid option: %s\n", argv[1]);
1214                 goto usage;
1215                 break;
1216         }
1217         return err;
1218  usage:
1219         return CMD_RET_USAGE;
1220 }
1221
1222 U_BOOT_CMD(
1223         fsl_mc,  CONFIG_SYS_MAXARGS,  1,   do_fsl_mc,
1224         "DPAA2 command to manage Management Complex (MC)",
1225         "start mc [FW_addr] [DPC_addr] - Start Management Complex\n"
1226         "fsl_mc apply DPL [DPL_addr] - Apply DPL file\n"
1227         "fsl_mc start aiop [FW_addr] - Start AIOP\n"
1228 );