f4a050afcca9d5fe46a3cb9751965d18e1177d0b
[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 <errno.h>
7 #include <asm/io.h>
8 #include <fsl-mc/fsl_mc.h>
9 #include <fsl-mc/fsl_mc_sys.h>
10 #include <fsl-mc/fsl_mc_private.h>
11 #include <fsl-mc/fsl_dpmng.h>
12 #include <fsl-mc/fsl_dprc.h>
13 #include <fsl-mc/fsl_dpio.h>
14 #include <fsl-mc/fsl_qbman_portal.h>
15
16 #define MC_RAM_BASE_ADDR_ALIGNMENT  (512UL * 1024 * 1024)
17 #define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1))
18 #define MC_RAM_SIZE_ALIGNMENT       (256UL * 1024 * 1024)
19
20 #define MC_MEM_SIZE_ENV_VAR     "mcmemsize"
21 #define MC_BOOT_TIMEOUT_ENV_VAR "mcboottimeout"
22
23 DECLARE_GLOBAL_DATA_PTR;
24 static int mc_boot_status;
25 struct fsl_mc_io *dflt_mc_io = NULL;
26 uint16_t dflt_dprc_handle = 0;
27 struct fsl_dpbp_obj *dflt_dpbp = NULL;
28 struct fsl_dpio_obj *dflt_dpio = NULL;
29 uint16_t dflt_dpio_handle = 0;
30
31 #ifdef DEBUG
32 void dump_ram_words(const char *title, void *addr)
33 {
34         int i;
35         uint32_t *words = addr;
36
37         printf("Dumping beginning of %s (%p):\n", title, addr);
38         for (i = 0; i < 16; i++)
39                 printf("%#x ", words[i]);
40
41         printf("\n");
42 }
43
44 void dump_mc_ccsr_regs(struct mc_ccsr_registers __iomem *mc_ccsr_regs)
45 {
46         printf("MC CCSR registers:\n"
47                 "reg_gcr1 %#x\n"
48                 "reg_gsr %#x\n"
49                 "reg_sicbalr %#x\n"
50                 "reg_sicbahr %#x\n"
51                 "reg_sicapr %#x\n"
52                 "reg_mcfbalr %#x\n"
53                 "reg_mcfbahr %#x\n"
54                 "reg_mcfapr %#x\n"
55                 "reg_psr %#x\n",
56                 mc_ccsr_regs->reg_gcr1,
57                 mc_ccsr_regs->reg_gsr,
58                 mc_ccsr_regs->reg_sicbalr,
59                 mc_ccsr_regs->reg_sicbahr,
60                 mc_ccsr_regs->reg_sicapr,
61                 mc_ccsr_regs->reg_mcfbalr,
62                 mc_ccsr_regs->reg_mcfbahr,
63                 mc_ccsr_regs->reg_mcfapr,
64                 mc_ccsr_regs->reg_psr);
65 }
66 #else
67
68 #define dump_ram_words(title, addr)
69 #define dump_mc_ccsr_regs(mc_ccsr_regs)
70
71 #endif /* DEBUG */
72
73 #ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
74 /**
75  * Copying MC firmware or DPL image to DDR
76  */
77 static int mc_copy_image(const char *title,
78                          u64 image_addr, u32 image_size, u64 mc_ram_addr)
79 {
80         debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
81         memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
82         flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size);
83         return 0;
84 }
85
86 /**
87  * MC firmware FIT image parser checks if the image is in FIT
88  * format, verifies integrity of the image and calculates
89  * raw image address and size values.
90  * Returns 0 on success and a negative errno on error.
91  * task fail.
92  **/
93 int parse_mc_firmware_fit_image(const void **raw_image_addr,
94                                 size_t *raw_image_size)
95 {
96         int format;
97         void *fit_hdr;
98         int node_offset;
99         const void *data;
100         size_t size;
101         const char *uname = "firmware";
102
103         /* Check if the image is in NOR flash */
104 #ifdef CONFIG_SYS_LS_MC_FW_IN_NOR
105         fit_hdr = (void *)CONFIG_SYS_LS_MC_FW_ADDR;
106 #else
107 #error "No CONFIG_SYS_LS_MC_FW_IN_xxx defined"
108 #endif
109
110         /* Check if Image is in FIT format */
111         format = genimg_get_format(fit_hdr);
112
113         if (format != IMAGE_FORMAT_FIT) {
114                 printf("fsl-mc: ERROR: Bad firmware image (not a FIT image)\n");
115                 return -EINVAL;
116         }
117
118         if (!fit_check_format(fit_hdr)) {
119                 printf("fsl-mc: ERROR: Bad firmware image (bad FIT header)\n");
120                 return -EINVAL;
121         }
122
123         node_offset = fit_image_get_node(fit_hdr, uname);
124
125         if (node_offset < 0) {
126                 printf("fsl-mc: ERROR: Bad firmware image (missing subimage)\n");
127                 return -ENOENT;
128         }
129
130         /* Verify MC firmware image */
131         if (!(fit_image_verify(fit_hdr, node_offset))) {
132                 printf("fsl-mc: ERROR: Bad firmware image (bad CRC)\n");
133                 return -EINVAL;
134         }
135
136         /* Get address and size of raw image */
137         fit_image_get_data(fit_hdr, node_offset, &data, &size);
138
139         *raw_image_addr = data;
140         *raw_image_size = size;
141
142         return 0;
143 }
144 #endif
145
146 /*
147  * Calculates the values to be used to specify the address range
148  * for the MC private DRAM block, in the MCFBALR/MCFBAHR registers.
149  * It returns the highest 512MB-aligned address within the given
150  * address range, in '*aligned_base_addr', and the number of 256 MiB
151  * blocks in it, in 'num_256mb_blocks'.
152  */
153 static int calculate_mc_private_ram_params(u64 mc_private_ram_start_addr,
154                                            size_t mc_ram_size,
155                                            u64 *aligned_base_addr,
156                                            u8 *num_256mb_blocks)
157 {
158         u64 addr;
159         u16 num_blocks;
160
161         if (mc_ram_size % MC_RAM_SIZE_ALIGNMENT != 0) {
162                 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
163                        mc_ram_size);
164                 return -EINVAL;
165         }
166
167         num_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT;
168         if (num_blocks < 1 || num_blocks > 0xff) {
169                 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
170                        mc_ram_size);
171                 return -EINVAL;
172         }
173
174         addr = (mc_private_ram_start_addr + mc_ram_size - 1) &
175                 MC_RAM_BASE_ADDR_ALIGNMENT_MASK;
176
177         if (addr < mc_private_ram_start_addr) {
178                 printf("fsl-mc: ERROR: bad start address %#llx\n",
179                        mc_private_ram_start_addr);
180                 return -EFAULT;
181         }
182
183         *aligned_base_addr = addr;
184         *num_256mb_blocks = num_blocks;
185         return 0;
186 }
187
188 static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size)
189 {
190         u64 mc_dpc_offset;
191 #ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
192         int error;
193         void *dpc_fdt_hdr;
194         int dpc_size;
195 #endif
196
197 #ifdef CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET
198         BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET & 0x3) != 0 ||
199                      CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET > 0xffffffff);
200
201         mc_dpc_offset = CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET;
202 #else
203 #error "CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET not defined"
204 #endif
205
206         /*
207          * Load the MC DPC blob in the MC private DRAM block:
208          */
209 #ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
210         printf("MC DPC is preloaded to %#llx\n", mc_ram_addr + mc_dpc_offset);
211 #else
212         /*
213          * Get address and size of the DPC blob stored in flash:
214          */
215 #ifdef CONFIG_SYS_LS_MC_DPC_IN_NOR
216         dpc_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPC_ADDR;
217 #else
218 #error "No CONFIG_SYS_LS_MC_DPC_IN_xxx defined"
219 #endif
220
221         error = fdt_check_header(dpc_fdt_hdr);
222         if (error != 0) {
223                 /*
224                  * Don't return with error here, since the MC firmware can
225                  * still boot without a DPC
226                  */
227                 printf("fsl-mc: WARNING: No DPC image found\n");
228                 return 0;
229         }
230
231         dpc_size = fdt_totalsize(dpc_fdt_hdr);
232         if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) {
233                 printf("fsl-mc: ERROR: Bad DPC image (too large: %d)\n",
234                        dpc_size);
235                 return -EINVAL;
236         }
237
238         mc_copy_image("MC DPC blob",
239                       (u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset);
240 #endif /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */
241
242         dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset));
243         return 0;
244 }
245
246 static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size)
247 {
248         u64 mc_dpl_offset;
249 #ifndef CONFIG_SYS_LS_MC_DPL_IN_DDR
250         int error;
251         void *dpl_fdt_hdr;
252         int dpl_size;
253 #endif
254
255 #ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
256         BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
257                      CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
258
259         mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
260 #else
261 #error "CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET not defined"
262 #endif
263
264         /*
265          * Load the MC DPL blob in the MC private DRAM block:
266          */
267 #ifdef CONFIG_SYS_LS_MC_DPL_IN_DDR
268         printf("MC DPL is preloaded to %#llx\n", mc_ram_addr + mc_dpl_offset);
269 #else
270         /*
271          * Get address and size of the DPL blob stored in flash:
272          */
273 #ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR
274         dpl_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR;
275 #else
276 #error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined"
277 #endif
278
279         error = fdt_check_header(dpl_fdt_hdr);
280         if (error != 0) {
281                 printf("fsl-mc: ERROR: Bad DPL image (bad header)\n");
282                 return error;
283         }
284
285         dpl_size = fdt_totalsize(dpl_fdt_hdr);
286         if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
287                 printf("fsl-mc: ERROR: Bad DPL image (too large: %d)\n",
288                        dpl_size);
289                 return -EINVAL;
290         }
291
292         mc_copy_image("MC DPL blob",
293                       (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
294 #endif /* not defined CONFIG_SYS_LS_MC_DPL_IN_DDR */
295
296         dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset));
297         return 0;
298 }
299
300 /**
301  * Return the MC boot timeout value in milliseconds
302  */
303 static unsigned long get_mc_boot_timeout_ms(void)
304 {
305         unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
306
307         char *timeout_ms_env_var = getenv(MC_BOOT_TIMEOUT_ENV_VAR);
308
309         if (timeout_ms_env_var) {
310                 timeout_ms = simple_strtoul(timeout_ms_env_var, NULL, 10);
311                 if (timeout_ms == 0) {
312                         printf("fsl-mc: WARNING: Invalid value for \'"
313                                MC_BOOT_TIMEOUT_ENV_VAR
314                                "\' environment variable: %lu\n",
315                                timeout_ms);
316
317                         timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
318                 }
319         }
320
321         return timeout_ms;
322 }
323
324 static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr)
325 {
326         u32 reg_gsr;
327         u32 mc_fw_boot_status;
328         unsigned long timeout_ms = get_mc_boot_timeout_ms();
329         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
330
331         dmb();
332         debug("Polling mc_ccsr_regs->reg_gsr ...\n");
333         assert(timeout_ms > 0);
334         for (;;) {
335                 udelay(1000);   /* throttle polling */
336                 reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
337                 mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
338                 if (mc_fw_boot_status & 0x1)
339                         break;
340
341                 timeout_ms--;
342                 if (timeout_ms == 0)
343                         break;
344         }
345
346         if (timeout_ms == 0) {
347                 if (booting_mc)
348                         printf("fsl-mc: timeout booting management complex firmware\n");
349                 else
350                         printf("fsl-mc: timeout deploying data path layout\n");
351
352                 /* TODO: Get an error status from an MC CCSR register */
353                 return -ETIMEDOUT;
354         }
355
356         if (mc_fw_boot_status != 0x1) {
357                 /*
358                  * TODO: Identify critical errors from the GSR register's FS
359                  * field and for those errors, set error to -ENODEV or other
360                  * appropriate errno, so that the status property is set to
361                  * failure in the fsl,dprc device tree node.
362                  */
363                 if (booting_mc) {
364                         printf("fsl-mc: WARNING: Firmware booted with error (GSR: %#x)\n",
365                                reg_gsr);
366                 } else {
367                         printf("fsl-mc: WARNING: Data path layout deployed with error (GSR: %#x)\n",
368                                reg_gsr);
369                 }
370         }
371
372         *final_reg_gsr = reg_gsr;
373         return 0;
374 }
375
376 int mc_init(void)
377 {
378         int error = 0;
379         int portal_id = 0;
380         struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
381         u64 mc_ram_addr;
382         u32 reg_gsr;
383         u32 reg_mcfbalr;
384 #ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
385         const void *raw_image_addr;
386         size_t raw_image_size = 0;
387 #endif
388         struct mc_version mc_ver_info;
389         u64 mc_ram_aligned_base_addr;
390         u8 mc_ram_num_256mb_blocks;
391         size_t mc_ram_size = mc_get_dram_block_size();
392
393         /*
394          * The MC private DRAM block was already carved at the end of DRAM
395          * by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE:
396          */
397         if (gd->bd->bi_dram[1].start) {
398                 mc_ram_addr =
399                         gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size;
400         } else {
401                 mc_ram_addr =
402                         gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
403         }
404
405         error = calculate_mc_private_ram_params(mc_ram_addr,
406                                                 mc_ram_size,
407                                                 &mc_ram_aligned_base_addr,
408                                                 &mc_ram_num_256mb_blocks);
409         if (error != 0)
410                 goto out;
411
412         /*
413          * Management Complex cores should be held at reset out of POR.
414          * U-boot should be the first software to touch MC. To be safe,
415          * we reset all cores again by setting GCR1 to 0. It doesn't do
416          * anything if they are held at reset. After we setup the firmware
417          * we kick off MC by deasserting the reset bit for core 0, and
418          * deasserting the reset bits for Command Portal Managers.
419          * The stop bits are not touched here. They are used to stop the
420          * cores when they are active. Setting stop bits doesn't stop the
421          * cores from fetching instructions when they are released from
422          * reset.
423          */
424         out_le32(&mc_ccsr_regs->reg_gcr1, 0);
425         dmb();
426
427 #ifdef CONFIG_SYS_LS_MC_FW_IN_DDR
428         printf("MC firmware is preloaded to %#llx\n", mc_ram_addr);
429 #else
430         error = parse_mc_firmware_fit_image(&raw_image_addr, &raw_image_size);
431         if (error != 0)
432                 goto out;
433         /*
434          * Load the MC FW at the beginning of the MC private DRAM block:
435          */
436         mc_copy_image("MC Firmware",
437                       (u64)raw_image_addr, raw_image_size, mc_ram_addr);
438 #endif
439         dump_ram_words("firmware", (void *)mc_ram_addr);
440
441         error = load_mc_dpc(mc_ram_addr, mc_ram_size);
442         if (error != 0)
443                 goto out;
444
445         error = load_mc_dpl(mc_ram_addr, mc_ram_size);
446         if (error != 0)
447                 goto out;
448
449         debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
450         dump_mc_ccsr_regs(mc_ccsr_regs);
451
452         /*
453          * Tell MC what is the address range of the DRAM block assigned to it:
454          */
455         reg_mcfbalr = (u32)mc_ram_aligned_base_addr |
456                       (mc_ram_num_256mb_blocks - 1);
457         out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr);
458         out_le32(&mc_ccsr_regs->reg_mcfbahr,
459                  (u32)(mc_ram_aligned_base_addr >> 32));
460         out_le32(&mc_ccsr_regs->reg_mcfapr, MCFAPR_BYPASS_ICID_MASK);
461
462         /*
463          * Tell the MC that we want delayed DPL deployment.
464          */
465         out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00);
466
467         printf("\nfsl-mc: Booting Management Complex ...\n");
468
469         /*
470          * Deassert reset and release MC core 0 to run
471          */
472         out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
473         error = wait_for_mc(true, &reg_gsr);
474         if (error != 0)
475                 goto out;
476
477         /*
478          * TODO: need to obtain the portal_id for the root container from the
479          * DPL
480          */
481         portal_id = 0;
482
483         /*
484          * Initialize the global default MC portal
485          * And check that the MC firmware is responding portal commands:
486          */
487         dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
488         if (!dflt_mc_io) {
489                 printf(" No memory: malloc() failed\n");
490                 return -ENOMEM;
491         }
492
493         dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
494         debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
495               portal_id, dflt_mc_io->mmio_regs);
496
497         error = mc_get_version(dflt_mc_io, &mc_ver_info);
498         if (error != 0) {
499                 printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n",
500                        error);
501                 goto out;
502         }
503
504         if (MC_VER_MAJOR != mc_ver_info.major)
505                 printf("fsl-mc: ERROR: Firmware major version mismatch (found: %d, expected: %d)\n",
506                        mc_ver_info.major, MC_VER_MAJOR);
507
508         if (MC_VER_MINOR != mc_ver_info.minor)
509                 printf("fsl-mc: WARNING: Firmware minor version mismatch (found: %d, expected: %d)\n",
510                        mc_ver_info.minor, MC_VER_MINOR);
511
512         printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n",
513                mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision,
514                reg_gsr & GSR_FS_MASK);
515
516         /*
517          * Tell the MC to deploy the DPL:
518          */
519         out_le32(&mc_ccsr_regs->reg_gsr, 0x0);
520         printf("\nfsl-mc: Deploying data path layout ...\n");
521         error = wait_for_mc(false, &reg_gsr);
522         if (error != 0)
523                 goto out;
524 out:
525         if (error != 0)
526                 mc_boot_status = -error;
527         else
528                 mc_boot_status = 0;
529
530         return error;
531 }
532
533 int get_mc_boot_status(void)
534 {
535         return mc_boot_status;
536 }
537
538 /**
539  * Return the actual size of the MC private DRAM block.
540  */
541 unsigned long mc_get_dram_block_size(void)
542 {
543         unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
544
545         char *dram_block_size_env_var = getenv(MC_MEM_SIZE_ENV_VAR);
546
547         if (dram_block_size_env_var) {
548                 dram_block_size = simple_strtoul(dram_block_size_env_var, NULL,
549                                                  10);
550
551                 if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
552                         printf("fsl-mc: WARNING: Invalid value for \'"
553                                MC_MEM_SIZE_ENV_VAR
554                                "\' environment variable: %lu\n",
555                                dram_block_size);
556
557                         dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
558                 }
559         }
560
561         return dram_block_size;
562 }
563
564 int dpio_init(struct dprc_obj_desc obj_desc)
565 {
566         struct qbman_swp_desc p_des;
567         struct dpio_attr attr;
568         int err = 0;
569
570         dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj));
571         if (!dflt_dpio) {
572                 printf(" No memory: malloc() failed\n");
573                 return -ENOMEM;
574         }
575
576         dflt_dpio->dpio_id = obj_desc.id;
577
578         err = dpio_open(dflt_mc_io, obj_desc.id, &dflt_dpio_handle);
579         if (err) {
580                 printf("dpio_open() failed\n");
581                 goto err_open;
582         }
583
584         err = dpio_get_attributes(dflt_mc_io, dflt_dpio_handle, &attr);
585         if (err) {
586                 printf("dpio_get_attributes() failed %d\n", err);
587                 goto err_get_attr;
588         }
589
590         err = dpio_enable(dflt_mc_io, dflt_dpio_handle);
591         if (err) {
592                 printf("dpio_enable() failed %d\n", err);
593                 goto err_get_enable;
594         }
595         debug("ce_paddr=0x%llx, ci_paddr=0x%llx, portalid=%d, prios=%d\n",
596               attr.qbman_portal_ce_paddr,
597               attr.qbman_portal_ci_paddr,
598               attr.qbman_portal_id,
599               attr.num_priorities);
600
601         p_des.cena_bar = (void *)attr.qbman_portal_ce_paddr;
602         p_des.cinh_bar = (void *)attr.qbman_portal_ci_paddr;
603
604         dflt_dpio->sw_portal = qbman_swp_init(&p_des);
605         if (dflt_dpio->sw_portal == NULL) {
606                 printf("qbman_swp_init() failed\n");
607                 goto err_get_swp_init;
608         }
609         return 0;
610
611 err_get_swp_init:
612 err_get_enable:
613         dpio_disable(dflt_mc_io, dflt_dpio_handle);
614 err_get_attr:
615         dpio_close(dflt_mc_io, dflt_dpio_handle);
616 err_open:
617         free(dflt_dpio);
618         return err;
619 }
620
621 int dpbp_init(struct dprc_obj_desc obj_desc)
622 {
623         dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj));
624         if (!dflt_dpbp) {
625                 printf(" No memory: malloc() failed\n");
626                 return -ENOMEM;
627         }
628         dflt_dpbp->dpbp_attr.id = obj_desc.id;
629
630         return 0;
631 }
632
633 int dprc_init_container_obj(struct dprc_obj_desc obj_desc, uint16_t dprc_handle)
634 {
635         int error = 0, state = 0;
636         struct dprc_endpoint dpni_endpoint, dpmac_endpoint;
637         if (!strcmp(obj_desc.type, "dpbp")) {
638                 if (!dflt_dpbp) {
639                         error = dpbp_init(obj_desc);
640                         if (error < 0)
641                                 printf("dpbp_init failed\n");
642                 }
643         } else if (!strcmp(obj_desc.type, "dpio")) {
644                 if (!dflt_dpio) {
645                         error = dpio_init(obj_desc);
646                         if (error < 0)
647                                 printf("dpio_init failed\n");
648                 }
649         } else if (!strcmp(obj_desc.type, "dpni")) {
650                 strcpy(dpni_endpoint.type, obj_desc.type);
651                 dpni_endpoint.id = obj_desc.id;
652                 error = dprc_get_connection(dflt_mc_io, dprc_handle,
653                                      &dpni_endpoint, &dpmac_endpoint, &state);
654                 if (!strcmp(dpmac_endpoint.type, "dpmac"))
655                         error = ldpaa_eth_init(obj_desc);
656                 if (error < 0)
657                         printf("ldpaa_eth_init failed\n");
658         }
659
660         return error;
661 }
662
663 int dprc_scan_container_obj(uint16_t dprc_handle, char *obj_type, int i)
664 {
665         int error = 0;
666         struct dprc_obj_desc obj_desc;
667
668         memset((void *)&obj_desc, 0x00, sizeof(struct dprc_obj_desc));
669
670         error = dprc_get_obj(dflt_mc_io, dprc_handle,
671                              i, &obj_desc);
672         if (error < 0) {
673                 printf("dprc_get_obj(i=%d) failed: %d\n",
674                        i, error);
675                 return error;
676         }
677
678         if (!strcmp(obj_desc.type, obj_type)) {
679                 debug("Discovered object: type %s, id %d, req %s\n",
680                       obj_desc.type, obj_desc.id, obj_type);
681
682                 error = dprc_init_container_obj(obj_desc, dprc_handle);
683                 if (error < 0) {
684                         printf("dprc_init_container_obj(i=%d) failed: %d\n",
685                                i, error);
686                         return error;
687                 }
688         }
689
690         return error;
691 }
692
693 int fsl_mc_ldpaa_init(bd_t *bis)
694 {
695         int i, error = 0;
696         int dprc_opened = 0, container_id;
697         int num_child_objects = 0;
698
699         error = mc_init();
700         if (error < 0)
701                 goto error;
702
703         error = dprc_get_container_id(dflt_mc_io, &container_id);
704         if (error < 0) {
705                 printf("dprc_get_container_id() failed: %d\n", error);
706                 goto error;
707         }
708
709         debug("fsl-mc: Container id=0x%x\n", container_id);
710
711         error = dprc_open(dflt_mc_io, container_id, &dflt_dprc_handle);
712         if (error < 0) {
713                 printf("dprc_open() failed: %d\n", error);
714                 goto error;
715         }
716         dprc_opened = true;
717
718         error = dprc_get_obj_count(dflt_mc_io,
719                                    dflt_dprc_handle,
720                                    &num_child_objects);
721         if (error < 0) {
722                 printf("dprc_get_obj_count() failed: %d\n", error);
723                 goto error;
724         }
725         debug("Total child in container %d = %d\n", container_id,
726               num_child_objects);
727
728         if (num_child_objects != 0) {
729                 /*
730                  * Discover objects currently in the DPRC container in the MC:
731                  */
732                 for (i = 0; i < num_child_objects; i++)
733                         error = dprc_scan_container_obj(dflt_dprc_handle,
734                                                         "dpbp", i);
735
736                 for (i = 0; i < num_child_objects; i++)
737                         error = dprc_scan_container_obj(dflt_dprc_handle,
738                                                         "dpio", i);
739
740                 for (i = 0; i < num_child_objects; i++)
741                         error = dprc_scan_container_obj(dflt_dprc_handle,
742                                                         "dpni", i);
743         }
744 error:
745         if (dprc_opened)
746                 dprc_close(dflt_mc_io, dflt_dprc_handle);
747
748         return error;
749 }
750
751 void fsl_mc_ldpaa_exit(bd_t *bis)
752 {
753         int err;
754
755         if (get_mc_boot_status() == 0) {
756                 err = dpio_disable(dflt_mc_io, dflt_dpio_handle);
757                 if (err < 0) {
758                         printf("dpio_disable() failed: %d\n", err);
759                         return;
760                 }
761                 err = dpio_reset(dflt_mc_io, dflt_dpio_handle);
762                 if (err < 0) {
763                         printf("dpio_reset() failed: %d\n", err);
764                         return;
765                 }
766                 err = dpio_close(dflt_mc_io, dflt_dpio_handle);
767                 if (err < 0) {
768                         printf("dpio_close() failed: %d\n", err);
769                         return;
770                 }
771
772                 free(dflt_dpio);
773                 free(dflt_dpbp);
774         }
775
776         if (dflt_mc_io)
777                 free(dflt_mc_io);
778 }