]>
Commit | Line | Data |
---|---|---|
b940ca64 GR |
1 | /* |
2 | * Copyright (C) 2014 Freescale Semiconductor | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
7b3bd9a7 | 6 | |
b940ca64 GR |
7 | #include <errno.h> |
8 | #include <asm/io.h> | |
7b3bd9a7 GR |
9 | #include <fsl-mc/fsl_mc.h> |
10 | #include <fsl-mc/fsl_mc_sys.h> | |
a2a55e51 | 11 | #include <fsl-mc/fsl_mc_private.h> |
7b3bd9a7 | 12 | #include <fsl-mc/fsl_dpmng.h> |
422cb08a | 13 | #include <fsl_debug_server.h> |
a2a55e51 PK |
14 | #include <fsl-mc/fsl_dprc.h> |
15 | #include <fsl-mc/fsl_dpio.h> | |
16 | #include <fsl-mc/fsl_qbman_portal.h> | |
b940ca64 GR |
17 | |
18 | DECLARE_GLOBAL_DATA_PTR; | |
19 | static int mc_boot_status; | |
a2a55e51 PK |
20 | struct fsl_mc_io *dflt_mc_io = NULL; |
21 | uint16_t dflt_dprc_handle = 0; | |
22 | struct fsl_dpbp_obj *dflt_dpbp = NULL; | |
23 | struct fsl_dpio_obj *dflt_dpio = NULL; | |
24 | uint16_t dflt_dpio_handle = NULL; | |
b940ca64 GR |
25 | |
26 | /** | |
27 | * Copying MC firmware or DPL image to DDR | |
28 | */ | |
29 | static int mc_copy_image(const char *title, | |
7b3bd9a7 | 30 | u64 image_addr, u32 image_size, u64 mc_ram_addr) |
b940ca64 GR |
31 | { |
32 | debug("%s copied to address %p\n", title, (void *)mc_ram_addr); | |
33 | memcpy((void *)mc_ram_addr, (void *)image_addr, image_size); | |
34 | return 0; | |
35 | } | |
36 | ||
37 | /** | |
38 | * MC firmware FIT image parser checks if the image is in FIT | |
39 | * format, verifies integrity of the image and calculates | |
40 | * raw image address and size values. | |
7b3bd9a7 | 41 | * Returns 0 on success and a negative errno on error. |
b940ca64 GR |
42 | * task fail. |
43 | **/ | |
b940ca64 GR |
44 | int parse_mc_firmware_fit_image(const void **raw_image_addr, |
45 | size_t *raw_image_size) | |
46 | { | |
47 | int format; | |
48 | void *fit_hdr; | |
49 | int node_offset; | |
50 | const void *data; | |
51 | size_t size; | |
52 | const char *uname = "firmware"; | |
53 | ||
7b3bd9a7 | 54 | /* Check if the image is in NOR flash */ |
b940ca64 GR |
55 | #ifdef CONFIG_SYS_LS_MC_FW_IN_NOR |
56 | fit_hdr = (void *)CONFIG_SYS_LS_MC_FW_ADDR; | |
57 | #else | |
58 | #error "No CONFIG_SYS_LS_MC_FW_IN_xxx defined" | |
59 | #endif | |
60 | ||
61 | /* Check if Image is in FIT format */ | |
62 | format = genimg_get_format(fit_hdr); | |
63 | ||
64 | if (format != IMAGE_FORMAT_FIT) { | |
7b3bd9a7 GR |
65 | printf("fsl-mc: ERROR: Bad firmware image (not a FIT image)\n"); |
66 | return -EINVAL; | |
b940ca64 GR |
67 | } |
68 | ||
69 | if (!fit_check_format(fit_hdr)) { | |
7b3bd9a7 GR |
70 | printf("fsl-mc: ERROR: Bad firmware image (bad FIT header)\n"); |
71 | return -EINVAL; | |
b940ca64 GR |
72 | } |
73 | ||
74 | node_offset = fit_image_get_node(fit_hdr, uname); | |
75 | ||
76 | if (node_offset < 0) { | |
7b3bd9a7 GR |
77 | printf("fsl-mc: ERROR: Bad firmware image (missing subimage)\n"); |
78 | return -ENOENT; | |
b940ca64 GR |
79 | } |
80 | ||
81 | /* Verify MC firmware image */ | |
82 | if (!(fit_image_verify(fit_hdr, node_offset))) { | |
7b3bd9a7 GR |
83 | printf("fsl-mc: ERROR: Bad firmware image (bad CRC)\n"); |
84 | return -EINVAL; | |
b940ca64 GR |
85 | } |
86 | ||
87 | /* Get address and size of raw image */ | |
88 | fit_image_get_data(fit_hdr, node_offset, &data, &size); | |
89 | ||
90 | *raw_image_addr = data; | |
91 | *raw_image_size = size; | |
92 | ||
93 | return 0; | |
94 | } | |
95 | ||
a2a55e51 | 96 | int mc_init(void) |
b940ca64 GR |
97 | { |
98 | int error = 0; | |
99 | int timeout = 200000; | |
a2a55e51 | 100 | int portal_id = 0; |
b940ca64 GR |
101 | struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR; |
102 | u64 mc_ram_addr; | |
103 | u64 mc_dpl_offset; | |
104 | u32 reg_gsr; | |
105 | u32 mc_fw_boot_status; | |
7b3bd9a7 | 106 | void *dpl_fdt_hdr; |
b940ca64 GR |
107 | int dpl_size; |
108 | const void *raw_image_addr; | |
109 | size_t raw_image_size = 0; | |
7b3bd9a7 | 110 | struct mc_version mc_ver_info; |
b940ca64 GR |
111 | |
112 | /* | |
113 | * The MC private DRAM block was already carved at the end of DRAM | |
114 | * by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE: | |
115 | */ | |
116 | if (gd->bd->bi_dram[1].start) { | |
117 | mc_ram_addr = | |
118 | gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size; | |
119 | } else { | |
120 | mc_ram_addr = | |
121 | gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size; | |
122 | } | |
123 | ||
422cb08a BS |
124 | #ifdef CONFIG_FSL_DEBUG_SERVER |
125 | mc_ram_addr -= debug_server_get_dram_block_size(); | |
126 | #endif | |
b940ca64 GR |
127 | /* |
128 | * Management Complex cores should be held at reset out of POR. | |
129 | * U-boot should be the first software to touch MC. To be safe, | |
130 | * we reset all cores again by setting GCR1 to 0. It doesn't do | |
131 | * anything if they are held at reset. After we setup the firmware | |
132 | * we kick off MC by deasserting the reset bit for core 0, and | |
133 | * deasserting the reset bits for Command Portal Managers. | |
134 | * The stop bits are not touched here. They are used to stop the | |
135 | * cores when they are active. Setting stop bits doesn't stop the | |
136 | * cores from fetching instructions when they are released from | |
137 | * reset. | |
138 | */ | |
139 | out_le32(&mc_ccsr_regs->reg_gcr1, 0); | |
140 | dmb(); | |
141 | ||
142 | error = parse_mc_firmware_fit_image(&raw_image_addr, &raw_image_size); | |
143 | if (error != 0) | |
144 | goto out; | |
145 | /* | |
146 | * Load the MC FW at the beginning of the MC private DRAM block: | |
147 | */ | |
7b3bd9a7 GR |
148 | mc_copy_image("MC Firmware", |
149 | (u64)raw_image_addr, raw_image_size, mc_ram_addr); | |
150 | ||
151 | /* | |
152 | * Get address and size of the DPL blob stored in flash: | |
153 | */ | |
154 | #ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR | |
155 | dpl_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR; | |
156 | #else | |
157 | #error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined" | |
158 | #endif | |
159 | ||
160 | error = fdt_check_header(dpl_fdt_hdr); | |
161 | if (error != 0) { | |
162 | printf("fsl-mc: ERROR: Bad DPL image (bad header)\n"); | |
163 | goto out; | |
164 | } | |
165 | ||
166 | dpl_size = fdt_totalsize(dpl_fdt_hdr); | |
167 | if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) { | |
168 | printf("fsl-mc: ERROR: Bad DPL image (too large: %d)\n", | |
169 | dpl_size); | |
170 | error = -EINVAL; | |
171 | goto out; | |
172 | } | |
b940ca64 GR |
173 | |
174 | /* | |
175 | * Calculate offset in the MC private DRAM block at which the MC DPL | |
176 | * blob is to be placed: | |
177 | */ | |
178 | #ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET | |
7b3bd9a7 GR |
179 | BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 || |
180 | CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff); | |
b940ca64 GR |
181 | |
182 | mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET; | |
183 | #else | |
184 | mc_dpl_offset = mc_get_dram_block_size() - | |
7b3bd9a7 | 185 | roundup(CONFIG_SYS_LS_MC_DPL_MAX_LENGTH, 4096); |
b940ca64 GR |
186 | |
187 | if ((mc_dpl_offset & 0x3) != 0 || mc_dpl_offset > 0xffffffff) { | |
188 | printf("%s: Invalid MC DPL offset: %llu\n", | |
189 | __func__, mc_dpl_offset); | |
190 | error = -EINVAL; | |
191 | goto out; | |
192 | } | |
193 | #endif | |
194 | ||
b940ca64 GR |
195 | /* |
196 | * Load the MC DPL blob at the far end of the MC private DRAM block: | |
7b3bd9a7 GR |
197 | * |
198 | * TODO: Should we place the DPL at a different location to match | |
199 | * assumptions of MC firmware about its memory layout? | |
b940ca64 | 200 | */ |
7b3bd9a7 GR |
201 | mc_copy_image("MC DPL blob", |
202 | (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset); | |
b940ca64 GR |
203 | |
204 | debug("mc_ccsr_regs %p\n", mc_ccsr_regs); | |
205 | ||
206 | /* | |
207 | * Tell MC where the MC Firmware image was loaded in DDR: | |
208 | */ | |
209 | out_le32(&mc_ccsr_regs->reg_mcfbalr, (u32)mc_ram_addr); | |
210 | out_le32(&mc_ccsr_regs->reg_mcfbahr, (u32)((u64)mc_ram_addr >> 32)); | |
211 | out_le32(&mc_ccsr_regs->reg_mcfapr, MCFAPR_BYPASS_ICID_MASK); | |
212 | ||
213 | /* | |
214 | * Tell MC where the DPL blob was loaded in DDR, by indicating | |
215 | * its offset relative to the beginning of the DDR block | |
216 | * allocated to the MC firmware. The MC firmware is responsible | |
217 | * for checking that there is no overlap between the DPL blob | |
218 | * and the runtime heap and stack of the MC firmware itself. | |
219 | * | |
220 | * NOTE: bits [31:2] of this offset need to be stored in bits [29:0] of | |
221 | * the GSR MC CCSR register. So, this offset is assumed to be 4-byte | |
222 | * aligned. | |
223 | * Care must be taken not to write 1s into bits 31 and 30 of the GSR in | |
224 | * this case as the SoC COP or PIC will be signaled. | |
225 | */ | |
226 | out_le32(&mc_ccsr_regs->reg_gsr, (u32)(mc_dpl_offset >> 2)); | |
227 | ||
7b3bd9a7 GR |
228 | printf("\nfsl-mc: Booting Management Complex ...\n"); |
229 | ||
b940ca64 GR |
230 | /* |
231 | * Deassert reset and release MC core 0 to run | |
232 | */ | |
233 | out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST); | |
234 | dmb(); | |
235 | debug("Polling mc_ccsr_regs->reg_gsr ...\n"); | |
236 | ||
237 | for (;;) { | |
238 | reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr); | |
239 | mc_fw_boot_status = (reg_gsr & GSR_FS_MASK); | |
240 | if (mc_fw_boot_status & 0x1) | |
241 | break; | |
242 | ||
243 | udelay(1000); /* throttle polling */ | |
244 | if (timeout-- <= 0) | |
245 | break; | |
246 | } | |
247 | ||
248 | if (timeout <= 0) { | |
7b3bd9a7 | 249 | printf("fsl-mc: timeout booting management complex firmware\n"); |
b940ca64 GR |
250 | |
251 | /* TODO: Get an error status from an MC CCSR register */ | |
252 | error = -ETIMEDOUT; | |
253 | goto out; | |
254 | } | |
255 | ||
b940ca64 GR |
256 | if (mc_fw_boot_status != 0x1) { |
257 | /* | |
258 | * TODO: Identify critical errors from the GSR register's FS | |
259 | * field and for those errors, set error to -ENODEV or other | |
260 | * appropriate errno, so that the status property is set to | |
261 | * failure in the fsl,dprc device tree node. | |
262 | */ | |
7b3bd9a7 GR |
263 | printf("fsl-mc: WARNING: Firmware booted with error (GSR: %#x)\n", |
264 | reg_gsr); | |
b940ca64 GR |
265 | } |
266 | ||
7b3bd9a7 GR |
267 | /* |
268 | * TODO: need to obtain the portal_id for the root container from the | |
269 | * DPL | |
270 | */ | |
271 | portal_id = 0; | |
272 | ||
273 | /* | |
a2a55e51 PK |
274 | * Initialize the global default MC portal |
275 | * And check that the MC firmware is responding portal commands: | |
7b3bd9a7 | 276 | */ |
a2a55e51 PK |
277 | dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io)); |
278 | if (!dflt_mc_io) { | |
279 | printf(" No memory: malloc() failed\n"); | |
280 | return -ENOMEM; | |
281 | } | |
282 | ||
283 | dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id); | |
7b3bd9a7 | 284 | debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n", |
a2a55e51 | 285 | portal_id, dflt_mc_io->mmio_regs); |
7b3bd9a7 | 286 | |
a2a55e51 | 287 | error = mc_get_version(dflt_mc_io, &mc_ver_info); |
7b3bd9a7 GR |
288 | if (error != 0) { |
289 | printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n", | |
290 | error); | |
291 | goto out; | |
292 | } | |
293 | ||
294 | if (MC_VER_MAJOR != mc_ver_info.major) | |
295 | printf("fsl-mc: ERROR: Firmware major version mismatch (found: %d, expected: %d)\n", | |
296 | mc_ver_info.major, MC_VER_MAJOR); | |
297 | ||
298 | if (MC_VER_MINOR != mc_ver_info.minor) | |
299 | printf("fsl-mc: WARNING: Firmware minor version mismatch (found: %d, expected: %d)\n", | |
300 | mc_ver_info.minor, MC_VER_MINOR); | |
301 | ||
302 | printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n", | |
303 | mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision, | |
304 | mc_fw_boot_status); | |
b940ca64 GR |
305 | out: |
306 | if (error != 0) | |
307 | mc_boot_status = -error; | |
308 | else | |
309 | mc_boot_status = 0; | |
310 | ||
311 | return error; | |
312 | } | |
313 | ||
314 | int get_mc_boot_status(void) | |
315 | { | |
316 | return mc_boot_status; | |
317 | } | |
318 | ||
319 | /** | |
320 | * Return the actual size of the MC private DRAM block. | |
321 | * | |
322 | * NOTE: For now this function always returns the minimum required size, | |
323 | * However, in the future, the actual size may be obtained from an environment | |
324 | * variable. | |
325 | */ | |
326 | unsigned long mc_get_dram_block_size(void) | |
327 | { | |
328 | return CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE; | |
329 | } | |
a2a55e51 PK |
330 | |
331 | int dpio_init(struct dprc_obj_desc obj_desc) | |
332 | { | |
333 | struct qbman_swp_desc p_des; | |
334 | struct dpio_attr attr; | |
335 | int err = 0; | |
336 | ||
337 | dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj)); | |
338 | if (!dflt_dpio) { | |
339 | printf(" No memory: malloc() failed\n"); | |
340 | return -ENOMEM; | |
341 | } | |
342 | ||
343 | dflt_dpio->dpio_id = obj_desc.id; | |
344 | ||
345 | err = dpio_open(dflt_mc_io, obj_desc.id, &dflt_dpio_handle); | |
346 | if (err) { | |
347 | printf("dpio_open() failed\n"); | |
348 | goto err_open; | |
349 | } | |
350 | ||
351 | err = dpio_get_attributes(dflt_mc_io, dflt_dpio_handle, &attr); | |
352 | if (err) { | |
353 | printf("dpio_get_attributes() failed %d\n", err); | |
354 | goto err_get_attr; | |
355 | } | |
356 | ||
357 | err = dpio_enable(dflt_mc_io, dflt_dpio_handle); | |
358 | if (err) { | |
359 | printf("dpio_enable() failed %d\n", err); | |
360 | goto err_get_enable; | |
361 | } | |
362 | debug("ce_paddr=0x%llx, ci_paddr=0x%llx, portalid=%d, prios=%d\n", | |
363 | attr.qbman_portal_ce_paddr, | |
364 | attr.qbman_portal_ci_paddr, | |
365 | attr.qbman_portal_id, | |
366 | attr.num_priorities); | |
367 | ||
368 | p_des.cena_bar = (void *)attr.qbman_portal_ce_paddr; | |
369 | p_des.cinh_bar = (void *)attr.qbman_portal_ci_paddr; | |
370 | ||
371 | dflt_dpio->sw_portal = qbman_swp_init(&p_des); | |
372 | if (dflt_dpio->sw_portal == NULL) { | |
373 | printf("qbman_swp_init() failed\n"); | |
374 | goto err_get_swp_init; | |
375 | } | |
376 | return 0; | |
377 | ||
378 | err_get_swp_init: | |
379 | err_get_enable: | |
380 | dpio_disable(dflt_mc_io, dflt_dpio_handle); | |
381 | err_get_attr: | |
382 | dpio_close(dflt_mc_io, dflt_dpio_handle); | |
383 | err_open: | |
384 | free(dflt_dpio); | |
385 | return err; | |
386 | } | |
387 | ||
388 | int dpbp_init(struct dprc_obj_desc obj_desc) | |
389 | { | |
390 | dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj)); | |
391 | if (!dflt_dpbp) { | |
392 | printf(" No memory: malloc() failed\n"); | |
393 | return -ENOMEM; | |
394 | } | |
395 | dflt_dpbp->dpbp_attr.id = obj_desc.id; | |
396 | ||
397 | return 0; | |
398 | } | |
399 | ||
c517771a | 400 | int dprc_init_container_obj(struct dprc_obj_desc obj_desc, uint16_t dprc_handle) |
a2a55e51 | 401 | { |
c517771a PK |
402 | int error = 0, state = 0; |
403 | struct dprc_endpoint dpni_endpoint, dpmac_endpoint; | |
a2a55e51 PK |
404 | if (!strcmp(obj_desc.type, "dpbp")) { |
405 | if (!dflt_dpbp) { | |
406 | error = dpbp_init(obj_desc); | |
407 | if (error < 0) | |
408 | printf("dpbp_init failed\n"); | |
409 | } | |
410 | } else if (!strcmp(obj_desc.type, "dpio")) { | |
411 | if (!dflt_dpio) { | |
412 | error = dpio_init(obj_desc); | |
413 | if (error < 0) | |
414 | printf("dpio_init failed\n"); | |
415 | } | |
c517771a PK |
416 | } else if (!strcmp(obj_desc.type, "dpni")) { |
417 | strcpy(dpni_endpoint.type, obj_desc.type); | |
418 | dpni_endpoint.id = obj_desc.id; | |
419 | error = dprc_get_connection(dflt_mc_io, dprc_handle, | |
420 | &dpni_endpoint, &dpmac_endpoint, &state); | |
421 | if (!strcmp(dpmac_endpoint.type, "dpmac")) | |
422 | error = ldpaa_eth_init(obj_desc); | |
423 | if (error < 0) | |
424 | printf("ldpaa_eth_init failed\n"); | |
a2a55e51 PK |
425 | } |
426 | ||
427 | return error; | |
428 | } | |
429 | ||
430 | int dprc_scan_container_obj(uint16_t dprc_handle, char *obj_type, int i) | |
431 | { | |
432 | int error = 0; | |
433 | struct dprc_obj_desc obj_desc; | |
434 | ||
435 | memset((void *)&obj_desc, 0x00, sizeof(struct dprc_obj_desc)); | |
436 | ||
437 | error = dprc_get_obj(dflt_mc_io, dprc_handle, | |
438 | i, &obj_desc); | |
439 | if (error < 0) { | |
440 | printf("dprc_get_obj(i=%d) failed: %d\n", | |
441 | i, error); | |
442 | return error; | |
443 | } | |
444 | ||
445 | if (!strcmp(obj_desc.type, obj_type)) { | |
446 | debug("Discovered object: type %s, id %d, req %s\n", | |
447 | obj_desc.type, obj_desc.id, obj_type); | |
448 | ||
c517771a | 449 | error = dprc_init_container_obj(obj_desc, dprc_handle); |
a2a55e51 PK |
450 | if (error < 0) { |
451 | printf("dprc_init_container_obj(i=%d) failed: %d\n", | |
452 | i, error); | |
453 | return error; | |
454 | } | |
455 | } | |
456 | ||
457 | return error; | |
458 | } | |
459 | ||
460 | int fsl_mc_ldpaa_init(bd_t *bis) | |
461 | { | |
462 | int i, error = 0; | |
463 | int dprc_opened = 0, container_id; | |
464 | int num_child_objects = 0; | |
465 | ||
466 | error = mc_init(); | |
467 | ||
468 | error = dprc_get_container_id(dflt_mc_io, &container_id); | |
469 | if (error < 0) { | |
470 | printf("dprc_get_container_id() failed: %d\n", error); | |
471 | goto error; | |
472 | } | |
473 | ||
474 | debug("fsl-mc: Container id=0x%x\n", container_id); | |
475 | ||
476 | error = dprc_open(dflt_mc_io, container_id, &dflt_dprc_handle); | |
477 | if (error < 0) { | |
478 | printf("dprc_open() failed: %d\n", error); | |
479 | goto error; | |
480 | } | |
481 | dprc_opened = true; | |
482 | ||
483 | error = dprc_get_obj_count(dflt_mc_io, | |
484 | dflt_dprc_handle, | |
485 | &num_child_objects); | |
486 | if (error < 0) { | |
487 | printf("dprc_get_obj_count() failed: %d\n", error); | |
488 | goto error; | |
489 | } | |
490 | debug("Total child in container %d = %d\n", container_id, | |
491 | num_child_objects); | |
492 | ||
493 | if (num_child_objects != 0) { | |
494 | /* | |
495 | * Discover objects currently in the DPRC container in the MC: | |
496 | */ | |
497 | for (i = 0; i < num_child_objects; i++) | |
498 | error = dprc_scan_container_obj(dflt_dprc_handle, | |
499 | "dpbp", i); | |
500 | ||
501 | for (i = 0; i < num_child_objects; i++) | |
502 | error = dprc_scan_container_obj(dflt_dprc_handle, | |
503 | "dpio", i); | |
504 | ||
505 | for (i = 0; i < num_child_objects; i++) | |
506 | error = dprc_scan_container_obj(dflt_dprc_handle, | |
507 | "dpni", i); | |
508 | } | |
509 | error: | |
510 | if (dprc_opened) | |
511 | dprc_close(dflt_mc_io, dflt_dprc_handle); | |
512 | ||
513 | return error; | |
514 | } | |
515 | ||
516 | void fsl_mc_ldpaa_exit(bd_t *bis) | |
517 | { | |
518 | int err; | |
519 | ||
520 | ||
521 | err = dpio_disable(dflt_mc_io, dflt_dpio_handle); | |
522 | if (err < 0) { | |
523 | printf("dpio_disable() failed: %d\n", err); | |
524 | return; | |
525 | } | |
526 | err = dpio_reset(dflt_mc_io, dflt_dpio_handle); | |
527 | if (err < 0) { | |
528 | printf("dpio_reset() failed: %d\n", err); | |
529 | return; | |
530 | } | |
531 | err = dpio_close(dflt_mc_io, dflt_dpio_handle); | |
532 | if (err < 0) { | |
533 | printf("dpio_close() failed: %d\n", err); | |
534 | return; | |
535 | } | |
536 | ||
537 | free(dflt_dpio); | |
538 | free(dflt_dpbp); | |
539 | free(dflt_mc_io); | |
540 | } |