driver: net: fsl-mc: Remove portal id hard-coding
[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 dprc_version_check(struct fsl_mc_io *mc_io, uint16_t handle)
659 {
660         struct dprc_attributes attr;
661         int error;
662
663         memset(&attr, 0, sizeof(struct dprc_attributes));
664         error = dprc_get_attributes(mc_io, MC_CMD_NO_FLAGS, handle, &attr);
665         if (error == 0) {
666                 if ((attr.version.major != DPRC_VER_MAJOR) ||
667                     (attr.version.minor != DPRC_VER_MINOR)) {
668                         printf("DPRC version mismatch found %u.%u,",
669                                attr.version.major,
670                                attr.version.minor);
671                         printf("supported version is %u.%u\n",
672                                DPRC_VER_MAJOR, DPRC_VER_MINOR);
673                 }
674         }
675         return error;
676 }
677
678 static int dpio_init(void)
679 {
680         struct qbman_swp_desc p_des;
681         struct dpio_attr attr;
682         struct dpio_cfg dpio_cfg;
683         int err = 0;
684
685         dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj));
686         if (!dflt_dpio) {
687                 printf("No memory: malloc() failed\n");
688                 err = -ENOMEM;
689                 goto err_malloc;
690         }
691
692         dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL;
693         dpio_cfg.num_priorities = 8;
694
695         err = dpio_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpio_cfg,
696                           &dflt_dpio->dpio_handle);
697         if (err < 0) {
698                 printf("dpio_create() failed: %d\n", err);
699                 err = -ENODEV;
700                 goto err_create;
701         }
702
703         memset(&attr, 0, sizeof(struct dpio_attr));
704         err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
705                                   dflt_dpio->dpio_handle, &attr);
706         if (err < 0) {
707                 printf("dpio_get_attributes() failed: %d\n", err);
708                 goto err_get_attr;
709         }
710
711         if ((attr.version.major != DPIO_VER_MAJOR) ||
712             (attr.version.minor != DPIO_VER_MINOR)) {
713                 printf("DPIO version mismatch found %u.%u,",
714                        attr.version.major, attr.version.minor);
715                 printf("supported version is %u.%u\n",
716                        DPIO_VER_MAJOR, DPIO_VER_MINOR);
717         }
718
719         dflt_dpio->dpio_id = attr.id;
720 #ifdef DEBUG
721         printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id);
722 #endif
723         err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
724         if (err < 0) {
725                 printf("dpio_enable() failed %d\n", err);
726                 goto err_get_enable;
727         }
728         debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n",
729               attr.qbman_portal_ce_offset,
730               attr.qbman_portal_ci_offset,
731               attr.qbman_portal_id,
732               attr.num_priorities);
733
734         p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
735                                         + attr.qbman_portal_ce_offset);
736         p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
737                                         + attr.qbman_portal_ci_offset);
738
739         dflt_dpio->sw_portal = qbman_swp_init(&p_des);
740         if (dflt_dpio->sw_portal == NULL) {
741                 printf("qbman_swp_init() failed\n");
742                 goto err_get_swp_init;
743         }
744         return 0;
745
746 err_get_swp_init:
747         dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
748 err_get_enable:
749         free(dflt_dpio);
750 err_get_attr:
751         dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
752         dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
753 err_create:
754 err_malloc:
755         return err;
756 }
757
758 static int dpio_exit(void)
759 {
760         int err;
761
762         err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
763         if (err < 0) {
764                 printf("dpio_disable() failed: %d\n", err);
765                 goto err;
766         }
767
768         err = dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
769         if (err < 0) {
770                 printf("dpio_destroy() failed: %d\n", err);
771                 goto err;
772         }
773
774 #ifdef DEBUG
775         printf("Exit: DPIO id=0x%d\n", dflt_dpio->dpio_id);
776 #endif
777
778         if (dflt_dpio)
779                 free(dflt_dpio);
780
781         return 0;
782 err:
783         return err;
784 }
785
786 static int dprc_init(void)
787 {
788         int err, child_portal_id, container_id;
789         struct dprc_cfg cfg;
790         uint64_t mc_portal_offset;
791
792         /* Open root container */
793         err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id);
794         if (err < 0) {
795                 printf("dprc_get_container_id(): Root failed: %d\n", err);
796                 goto err_root_container_id;
797         }
798
799 #ifdef DEBUG
800         printf("Root container id = %d\n", container_id);
801 #endif
802         err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id,
803                         &root_dprc_handle);
804         if (err < 0) {
805                 printf("dprc_open(): Root Container failed: %d\n", err);
806                 goto err_root_open;
807         }
808
809         if (!root_dprc_handle) {
810                 printf("dprc_open(): Root Container Handle is not valid\n");
811                 goto err_root_open;
812         }
813
814         err = dprc_version_check(root_mc_io, root_dprc_handle);
815         if (err < 0) {
816                 printf("dprc_version_check() failed: %d\n", err);
817                 goto err_root_open;
818         }
819
820         cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED |
821                       DPRC_CFG_OPT_OBJ_CREATE_ALLOWED |
822                       DPRC_CFG_OPT_ALLOC_ALLOWED;
823         cfg.icid = DPRC_GET_ICID_FROM_POOL;
824         cfg.portal_id = DPRC_GET_PORTAL_ID_FROM_POOL;
825         err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS,
826                         root_dprc_handle,
827                         &cfg,
828                         &child_dprc_id,
829                         &mc_portal_offset);
830         if (err < 0) {
831                 printf("dprc_create_container() failed: %d\n", err);
832                 goto err_create;
833         }
834
835         dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
836         if (!dflt_mc_io) {
837                 err  = -ENOMEM;
838                 printf(" No memory: malloc() failed\n");
839                 goto err_malloc;
840         }
841
842         child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset);
843         dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id);
844 #ifdef DEBUG
845         printf("MC portal of child DPRC container: %d, physical addr %p)\n",
846                child_dprc_id, dflt_mc_io->mmio_regs);
847 #endif
848
849         err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id,
850                         &dflt_dprc_handle);
851         if (err < 0) {
852                 printf("dprc_open(): Child container failed: %d\n", err);
853                 goto err_child_open;
854         }
855
856         if (!dflt_dprc_handle) {
857                 printf("dprc_open(): Child container Handle is not valid\n");
858                 goto err_child_open;
859         }
860
861         return 0;
862 err_child_open:
863         free(dflt_mc_io);
864 err_malloc:
865         dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
866                                root_dprc_handle, child_dprc_id);
867 err_create:
868         dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
869 err_root_open:
870 err_root_container_id:
871         return err;
872 }
873
874 static int dprc_exit(void)
875 {
876         int err;
877
878         err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle);
879         if (err < 0) {
880                 printf("dprc_close(): Child failed: %d\n", err);
881                 goto err;
882         }
883
884         err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
885                                      root_dprc_handle, child_dprc_id);
886         if (err < 0) {
887                 printf("dprc_destroy_container() failed: %d\n", err);
888                 goto err;
889         }
890
891         err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
892         if (err < 0) {
893                 printf("dprc_close(): Root failed: %d\n", err);
894                 goto err;
895         }
896
897         if (dflt_mc_io)
898                 free(dflt_mc_io);
899
900         if (root_mc_io)
901                 free(root_mc_io);
902
903         return 0;
904
905 err:
906         return err;
907 }
908
909 static int dpbp_init(void)
910 {
911         int err;
912         struct dpbp_attr dpbp_attr;
913         struct dpbp_cfg dpbp_cfg;
914
915         dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj));
916         if (!dflt_dpbp) {
917                 printf("No memory: malloc() failed\n");
918                 err = -ENOMEM;
919                 goto err_malloc;
920         }
921
922         dpbp_cfg.options = 512;
923
924         err = dpbp_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpbp_cfg,
925                           &dflt_dpbp->dpbp_handle);
926
927         if (err < 0) {
928                 err = -ENODEV;
929                 printf("dpbp_create() failed: %d\n", err);
930                 goto err_create;
931         }
932
933         memset(&dpbp_attr, 0, sizeof(struct dpbp_attr));
934         err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
935                                   dflt_dpbp->dpbp_handle,
936                                   &dpbp_attr);
937         if (err < 0) {
938                 printf("dpbp_get_attributes() failed: %d\n", err);
939                 goto err_get_attr;
940         }
941
942         if ((dpbp_attr.version.major != DPBP_VER_MAJOR) ||
943             (dpbp_attr.version.minor != DPBP_VER_MINOR)) {
944                 printf("DPBP version mismatch found %u.%u,",
945                        dpbp_attr.version.major, dpbp_attr.version.minor);
946                 printf("supported version is %u.%u\n",
947                        DPBP_VER_MAJOR, DPBP_VER_MINOR);
948         }
949
950         dflt_dpbp->dpbp_attr.id = dpbp_attr.id;
951 #ifdef DEBUG
952         printf("Init: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
953 #endif
954
955         err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
956         if (err < 0) {
957                 printf("dpbp_close() failed: %d\n", err);
958                 goto err_close;
959         }
960
961         return 0;
962
963 err_close:
964         free(dflt_dpbp);
965 err_get_attr:
966         dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
967         dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
968 err_create:
969 err_malloc:
970         return err;
971 }
972
973 static int dpbp_exit(void)
974 {
975         int err;
976
977         err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
978                         &dflt_dpbp->dpbp_handle);
979         if (err < 0) {
980                 printf("dpbp_open() failed: %d\n", err);
981                 goto err;
982         }
983
984         err = dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
985                            dflt_dpbp->dpbp_handle);
986         if (err < 0) {
987                 printf("dpbp_destroy() failed: %d\n", err);
988                 goto err;
989         }
990
991 #ifdef DEBUG
992         printf("Exit: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
993 #endif
994
995         if (dflt_dpbp)
996                 free(dflt_dpbp);
997         return 0;
998
999 err:
1000         return err;
1001 }
1002
1003 static int dpni_init(void)
1004 {
1005         int err;
1006         struct dpni_attr dpni_attr;
1007         uint8_t ext_cfg_buf[256] = {0};
1008         struct dpni_extended_cfg dpni_extended_cfg;
1009         struct dpni_cfg dpni_cfg;
1010
1011         dflt_dpni = (struct fsl_dpni_obj *)malloc(sizeof(struct fsl_dpni_obj));
1012         if (!dflt_dpni) {
1013                 printf("No memory: malloc() failed\n");
1014                 err = -ENOMEM;
1015                 goto err_malloc;
1016         }
1017
1018         memset(&dpni_extended_cfg, 0, sizeof(dpni_extended_cfg));
1019         err = dpni_prepare_extended_cfg(&dpni_extended_cfg, &ext_cfg_buf[0]);
1020         if (err < 0) {
1021                 err = -ENODEV;
1022                 printf("dpni_prepare_extended_cfg() failed: %d\n", err);
1023                 goto err_prepare_extended_cfg;
1024         }
1025
1026         memset(&dpni_cfg, 0, sizeof(dpni_cfg));
1027         dpni_cfg.adv.options = DPNI_OPT_UNICAST_FILTER |
1028                                DPNI_OPT_MULTICAST_FILTER;
1029
1030         dpni_cfg.adv.ext_cfg_iova = (uint64_t)&ext_cfg_buf[0];
1031         err = dpni_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpni_cfg,
1032                           &dflt_dpni->dpni_handle);
1033
1034         if (err < 0) {
1035                 err = -ENODEV;
1036                 printf("dpni_create() failed: %d\n", err);
1037                 goto err_create;
1038         }
1039
1040         memset(&dpni_attr, 0, sizeof(struct dpni_attr));
1041         err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1042                                   dflt_dpni->dpni_handle,
1043                                   &dpni_attr);
1044         if (err < 0) {
1045                 printf("dpni_get_attributes() failed: %d\n", err);
1046                 goto err_get_attr;
1047         }
1048
1049         if ((dpni_attr.version.major != DPNI_VER_MAJOR) ||
1050             (dpni_attr.version.minor != DPNI_VER_MINOR)) {
1051                 printf("DPNI version mismatch found %u.%u,",
1052                        dpni_attr.version.major, dpni_attr.version.minor);
1053                 printf("supported version is %u.%u\n",
1054                        DPNI_VER_MAJOR, DPNI_VER_MINOR);
1055         }
1056
1057         dflt_dpni->dpni_id = dpni_attr.id;
1058 #ifdef DEBUG
1059         printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1060 #endif
1061
1062         err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1063         if (err < 0) {
1064                 printf("dpni_close() failed: %d\n", err);
1065                 goto err_close;
1066         }
1067
1068         return 0;
1069
1070 err_close:
1071 err_get_attr:
1072         dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1073         dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1074 err_create:
1075 err_prepare_extended_cfg:
1076         free(dflt_dpni);
1077 err_malloc:
1078         return err;
1079 }
1080
1081 static int dpni_exit(void)
1082 {
1083         int err;
1084
1085         err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
1086                         &dflt_dpni->dpni_handle);
1087         if (err < 0) {
1088                 printf("dpni_open() failed: %d\n", err);
1089                 goto err;
1090         }
1091
1092         err = dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS,
1093                            dflt_dpni->dpni_handle);
1094         if (err < 0) {
1095                 printf("dpni_destroy() failed: %d\n", err);
1096                 goto err;
1097         }
1098
1099 #ifdef DEBUG
1100         printf("Exit: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1101 #endif
1102
1103         if (dflt_dpni)
1104                 free(dflt_dpni);
1105         return 0;
1106
1107 err:
1108         return err;
1109 }
1110
1111 static int mc_init_object(void)
1112 {
1113         int err = 0;
1114
1115         err = dprc_init();
1116         if (err < 0) {
1117                 printf("dprc_init() failed: %d\n", err);
1118                 goto err;
1119         }
1120
1121         err = dpbp_init();
1122         if (err < 0) {
1123                 printf("dpbp_init() failed: %d\n", err);
1124                 goto err;
1125         }
1126
1127         err = dpio_init();
1128         if (err < 0) {
1129                 printf("dpio_init() failed: %d\n", err);
1130                 goto err;
1131         }
1132
1133         err = dpni_init();
1134         if (err < 0) {
1135                 printf("dpni_init() failed: %d\n", err);
1136                 goto err;
1137         }
1138
1139         return 0;
1140 err:
1141         return err;
1142 }
1143
1144 int fsl_mc_ldpaa_exit(bd_t *bd)
1145 {
1146         int err = 0;
1147
1148         if (bd && get_mc_boot_status() == -1)
1149                 return 0;
1150
1151         if (bd && !get_mc_boot_status() && get_dpl_apply_status() == -1) {
1152                 printf("ERROR: fsl-mc: DPL is not applied\n");
1153                 err = -ENODEV;
1154                 return err;
1155         }
1156
1157         if (bd && !get_mc_boot_status() && !get_dpl_apply_status())
1158                 return err;
1159
1160         err = dpbp_exit();
1161         if (err < 0) {
1162                 printf("dpni_exit() failed: %d\n", err);
1163                 goto err;
1164         }
1165
1166         err = dpio_exit();
1167         if (err < 0) {
1168                 printf("dpio_exit() failed: %d\n", err);
1169                 goto err;
1170         }
1171
1172         err = dpni_exit();
1173         if (err < 0) {
1174                 printf("dpni_exit() failed: %d\n", err);
1175                 goto err;
1176         }
1177
1178         err = dprc_exit();
1179         if (err < 0) {
1180                 printf("dprc_exit() failed: %d\n", err);
1181                 goto err;
1182         }
1183
1184         return 0;
1185 err:
1186         return err;
1187 }
1188
1189 static int do_fsl_mc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1190 {
1191         int err = 0;
1192         if (argc < 3)
1193                 goto usage;
1194
1195         switch (argv[1][0]) {
1196         case 's': {
1197                         char sub_cmd;
1198                         u64 mc_fw_addr, mc_dpc_addr;
1199 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1200                         u64 aiop_fw_addr;
1201 #endif
1202
1203                         sub_cmd = argv[2][0];
1204                         switch (sub_cmd) {
1205                         case 'm':
1206                                 if (argc < 5)
1207                                         goto usage;
1208
1209                                 if (get_mc_boot_status() == 0) {
1210                                         printf("fsl-mc: MC is already booted");
1211                                         printf("\n");
1212                                         return err;
1213                                 }
1214                                 mc_fw_addr = simple_strtoull(argv[3], NULL, 16);
1215                                 mc_dpc_addr = simple_strtoull(argv[4], NULL,
1216                                                               16);
1217
1218                                 if (!mc_init(mc_fw_addr, mc_dpc_addr))
1219                                         err = mc_init_object();
1220                                 break;
1221
1222 #ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1223                         case 'a':
1224                                 if (argc < 4)
1225                                         goto usage;
1226                                 if (get_aiop_apply_status() == 0) {
1227                                         printf("fsl-mc: AIOP FW is already");
1228                                         printf(" applied\n");
1229                                         return err;
1230                                 }
1231
1232                                 aiop_fw_addr = simple_strtoull(argv[3], NULL,
1233                                                                16);
1234
1235                                 err = load_mc_aiop_img(aiop_fw_addr);
1236                                 if (!err)
1237                                         printf("fsl-mc: AIOP FW applied\n");
1238                                 break;
1239 #endif
1240                         default:
1241                                 printf("Invalid option: %s\n", argv[2]);
1242                                 goto usage;
1243
1244                                 break;
1245                         }
1246                 }
1247                 break;
1248
1249         case 'a': {
1250                         u64 mc_dpl_addr;
1251
1252                         if (argc < 4)
1253                                 goto usage;
1254
1255                         if (get_dpl_apply_status() == 0) {
1256                                 printf("fsl-mc: DPL already applied\n");
1257                                 return err;
1258                         }
1259
1260                         mc_dpl_addr = simple_strtoull(argv[3], NULL,
1261                                                               16);
1262
1263                         if (get_mc_boot_status() != 0) {
1264                                 printf("fsl-mc: Deploying data path layout ..");
1265                                 printf("ERROR (MC is not booted)\n");
1266                                 return -ENODEV;
1267                         }
1268
1269                         if (!fsl_mc_ldpaa_exit(NULL))
1270                                 err = mc_apply_dpl(mc_dpl_addr);
1271                         break;
1272                 }
1273         default:
1274                 printf("Invalid option: %s\n", argv[1]);
1275                 goto usage;
1276                 break;
1277         }
1278         return err;
1279  usage:
1280         return CMD_RET_USAGE;
1281 }
1282
1283 U_BOOT_CMD(
1284         fsl_mc,  CONFIG_SYS_MAXARGS,  1,   do_fsl_mc,
1285         "DPAA2 command to manage Management Complex (MC)",
1286         "start mc [FW_addr] [DPC_addr] - Start Management Complex\n"
1287         "fsl_mc apply DPL [DPL_addr] - Apply DPL file\n"
1288         "fsl_mc start aiop [FW_addr] - Start AIOP\n"
1289 );