1
2
3
4
5
6#include <common.h>
7#include <command.h>
8#include <cpu_func.h>
9#include <env.h>
10#include <errno.h>
11#include <image.h>
12#include <log.h>
13#include <malloc.h>
14#include <mapmem.h>
15#include <asm/global_data.h>
16#include <linux/bug.h>
17#include <asm/io.h>
18#include <linux/delay.h>
19#include <linux/libfdt.h>
20#include <net.h>
21#include <fdt_support.h>
22#include <fsl-mc/fsl_mc.h>
23#include <fsl-mc/fsl_mc_sys.h>
24#include <fsl-mc/fsl_mc_private.h>
25#include <fsl-mc/fsl_dpmng.h>
26#include <fsl-mc/fsl_dprc.h>
27#include <fsl-mc/fsl_dpio.h>
28#include <fsl-mc/fsl_dpni.h>
29#include <fsl-mc/fsl_dpsparser.h>
30#include <fsl-mc/fsl_qbman_portal.h>
31#include <fsl-mc/ldpaa_wriop.h>
32
33#define MC_RAM_BASE_ADDR_ALIGNMENT (512UL * 1024 * 1024)
34#define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1))
35#define MC_RAM_SIZE_ALIGNMENT (256UL * 1024 * 1024)
36
37#define MC_MEM_SIZE_ENV_VAR "mcmemsize"
38#define MC_BOOT_TIMEOUT_ENV_VAR "mcboottimeout"
39#define MC_BOOT_ENV_VAR "mcinitcmd"
40#define MC_DRAM_BLOCK_DEFAULT_SIZE (512UL * 1024 * 1024)
41
42#define MC_BUFFER_SIZE (1024 * 1024 * 16)
43#define MAGIC_MC 0x4d430100
44#define MC_FW_ADDR_MASK_LOW 0xE0000000
45#define MC_FW_ADDR_MASK_HIGH 0X1FFFF
46#define MC_STRUCT_BUFFER_OFFSET 0x01000000
47#define MC_OFFSET_DELTA MC_STRUCT_BUFFER_OFFSET
48
49#define LOG_HEADER_FLAG_BUFFER_WRAPAROUND 0x80000000
50#define LAST_BYTE(a) ((a) & ~(LOG_HEADER_FLAG_BUFFER_WRAPAROUND))
51
52DECLARE_GLOBAL_DATA_PTR;
53static int mc_memset_resv_ram;
54static struct mc_version mc_ver_info;
55static int mc_boot_status = -1;
56static int mc_dpl_applied = -1;
57#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
58static int mc_aiop_applied = -1;
59#endif
60struct fsl_mc_io *root_mc_io = NULL;
61struct fsl_mc_io *dflt_mc_io = NULL;
62uint16_t root_dprc_handle = 0;
63uint16_t dflt_dprc_handle = 0;
64int child_dprc_id;
65struct fsl_dpbp_obj *dflt_dpbp = NULL;
66struct fsl_dpio_obj *dflt_dpio = NULL;
67struct fsl_dpni_obj *dflt_dpni = NULL;
68static u64 mc_lazy_dpl_addr;
69static u32 dpsparser_obj_id;
70static u16 dpsparser_handle;
71static char *mc_err_msg_apply_spb[] = MC_ERROR_MSG_APPLY_SPB;
72
73#ifdef DEBUG
74void dump_ram_words(const char *title, void *addr)
75{
76 int i;
77 uint32_t *words = addr;
78
79 printf("Dumping beginning of %s (%p):\n", title, addr);
80 for (i = 0; i < 16; i++)
81 printf("%#x ", words[i]);
82
83 printf("\n");
84}
85
86void dump_mc_ccsr_regs(struct mc_ccsr_registers __iomem *mc_ccsr_regs)
87{
88 printf("MC CCSR registers:\n"
89 "reg_gcr1 %#x\n"
90 "reg_gsr %#x\n"
91 "reg_sicbalr %#x\n"
92 "reg_sicbahr %#x\n"
93 "reg_sicapr %#x\n"
94 "reg_mcfbalr %#x\n"
95 "reg_mcfbahr %#x\n"
96 "reg_mcfapr %#x\n"
97 "reg_psr %#x\n",
98 mc_ccsr_regs->reg_gcr1,
99 mc_ccsr_regs->reg_gsr,
100 mc_ccsr_regs->reg_sicbalr,
101 mc_ccsr_regs->reg_sicbahr,
102 mc_ccsr_regs->reg_sicapr,
103 mc_ccsr_regs->reg_mcfbalr,
104 mc_ccsr_regs->reg_mcfbahr,
105 mc_ccsr_regs->reg_mcfapr,
106 mc_ccsr_regs->reg_psr);
107}
108#else
109
110#define dump_ram_words(title, addr)
111#define dump_mc_ccsr_regs(mc_ccsr_regs)
112
113#endif
114
115
116
117
118static int mc_copy_image(const char *title,
119 u64 image_addr, u32 image_size, u64 mc_ram_addr)
120{
121 debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
122 memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
123 flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size);
124 return 0;
125}
126
127#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
128
129
130
131
132
133
134
135int parse_mc_firmware_fit_image(u64 mc_fw_addr,
136 const void **raw_image_addr,
137 size_t *raw_image_size)
138{
139 int format;
140 void *fit_hdr;
141 int node_offset;
142 const void *data;
143 size_t size;
144 const char *uname = "firmware";
145
146 fit_hdr = (void *)mc_fw_addr;
147
148
149 format = genimg_get_format(fit_hdr);
150
151 if (format != IMAGE_FORMAT_FIT) {
152 printf("fsl-mc: ERR: Bad firmware image (not a FIT image)\n");
153 return -EINVAL;
154 }
155
156 if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
157 printf("fsl-mc: ERR: Bad firmware image (bad FIT header)\n");
158 return -EINVAL;
159 }
160
161 node_offset = fit_image_get_node(fit_hdr, uname);
162
163 if (node_offset < 0) {
164 printf("fsl-mc: ERR: Bad firmware image (missing subimage)\n");
165 return -ENOENT;
166 }
167
168
169 if (!(fit_image_verify(fit_hdr, node_offset))) {
170 printf("fsl-mc: ERR: Bad firmware image (bad CRC)\n");
171 return -EINVAL;
172 }
173
174
175 fit_image_get_data(fit_hdr, node_offset, &data, &size);
176
177 *raw_image_addr = data;
178 *raw_image_size = size;
179
180 return 0;
181}
182#endif
183
184#define MC_DT_INCREASE_SIZE 64
185
186enum mc_fixup_type {
187 MC_FIXUP_DPL,
188 MC_FIXUP_DPC
189};
190
191static int mc_fixup_mac_addr(void *blob, int nodeoffset,
192#ifdef CONFIG_DM_ETH
193 const char *propname, struct udevice *eth_dev,
194#else
195 const char *propname, struct eth_device *eth_dev,
196#endif
197 enum mc_fixup_type type)
198{
199#ifdef CONFIG_DM_ETH
200 struct eth_pdata *plat = dev_get_plat(eth_dev);
201 unsigned char *enetaddr = plat->enetaddr;
202 int eth_index = dev_seq(eth_dev);
203#else
204 unsigned char *enetaddr = eth_dev->enetaddr;
205 int eth_index = eth_dev->index;
206#endif
207 int err = 0, len = 0, size, i;
208 unsigned char env_enetaddr[ARP_HLEN];
209 unsigned int enetaddr_32[ARP_HLEN];
210 void *val = NULL;
211
212 switch (type) {
213 case MC_FIXUP_DPL:
214
215 for (i = 0; i < ARP_HLEN; i++)
216 enetaddr_32[i] = cpu_to_fdt32(enetaddr[i]);
217 val = enetaddr_32;
218 len = sizeof(enetaddr_32);
219 break;
220 case MC_FIXUP_DPC:
221 val = enetaddr;
222 len = ARP_HLEN;
223 break;
224 }
225
226
227 if (fdt_get_property(blob, nodeoffset, propname, NULL)) {
228
229 if (!eth_env_get_enetaddr_by_index("eth", eth_index,
230 env_enetaddr))
231 return err;
232 } else {
233 size = MC_DT_INCREASE_SIZE + strlen(propname) + len;
234
235 err = fdt_increase_size(blob, size);
236 if (err) {
237 printf("fdt_increase_size: err=%s\n",
238 fdt_strerror(err));
239 return err;
240 }
241 }
242
243 err = fdt_setprop(blob, nodeoffset, propname, val, len);
244 if (err) {
245 printf("fdt_setprop: err=%s\n", fdt_strerror(err));
246 return err;
247 }
248
249 return err;
250}
251
252#define is_dpni(s) (s != NULL ? !strncmp(s, "dpni@", 5) : 0)
253
254const char *dpl_get_connection_endpoint(void *blob, char *endpoint)
255{
256 int connoffset = fdt_path_offset(blob, "/connections"), off;
257 const char *s1, *s2;
258
259 for (off = fdt_first_subnode(blob, connoffset);
260 off >= 0;
261 off = fdt_next_subnode(blob, off)) {
262 s1 = fdt_stringlist_get(blob, off, "endpoint1", 0, NULL);
263 s2 = fdt_stringlist_get(blob, off, "endpoint2", 0, NULL);
264
265 if (!s1 || !s2)
266 continue;
267
268 if (strcmp(endpoint, s1) == 0)
269 return s2;
270
271 if (strcmp(endpoint, s2) == 0)
272 return s1;
273 }
274
275 return NULL;
276}
277
278static int mc_fixup_dpl_mac_addr(void *blob, int dpmac_id,
279#ifdef CONFIG_DM_ETH
280 struct udevice *eth_dev)
281#else
282 struct eth_device *eth_dev)
283#endif
284{
285 int objoff = fdt_path_offset(blob, "/objects");
286 int dpmacoff = -1, dpnioff = -1;
287 const char *endpoint;
288 char mac_name[10];
289 int err;
290
291 sprintf(mac_name, "dpmac@%d", dpmac_id);
292 dpmacoff = fdt_subnode_offset(blob, objoff, mac_name);
293 if (dpmacoff < 0)
294
295 return 0;
296
297 err = mc_fixup_mac_addr(blob, dpmacoff, "mac_addr", eth_dev,
298 MC_FIXUP_DPL);
299 if (err) {
300 printf("Error fixing up dpmac mac_addr in DPL\n");
301 return err;
302 }
303
304
305
306
307
308 endpoint = dpl_get_connection_endpoint(blob, mac_name);
309 if (!is_dpni(endpoint))
310 return 0;
311
312
313 dpnioff = fdt_subnode_offset(blob, objoff, endpoint);
314 if (dpnioff < 0)
315
316 return 0;
317
318 return mc_fixup_mac_addr(blob, dpnioff, "mac_addr", eth_dev,
319 MC_FIXUP_DPL);
320}
321
322void fdt_fixup_mc_ddr(u64 *base, u64 *size)
323{
324 u64 mc_size = mc_get_dram_block_size();
325
326 if (mc_size < MC_DRAM_BLOCK_DEFAULT_SIZE) {
327 *base = mc_get_dram_addr() + mc_size;
328 *size = MC_DRAM_BLOCK_DEFAULT_SIZE - mc_size;
329 }
330}
331
332void fdt_fsl_mc_fixup_iommu_map_entry(void *blob)
333{
334 u32 *prop;
335 u32 iommu_map[4], phandle;
336 int offset;
337 int lenp;
338
339
340 offset = fdt_path_offset(blob, "/soc/fsl-mc");
341 if (offset < 0)
342 offset = fdt_path_offset(blob, "/fsl-mc");
343 if (offset < 0) {
344 printf("%s: fsl-mc: ERR: fsl-mc node not found in DT, err %d\n",
345 __func__, offset);
346 return;
347 }
348
349 prop = fdt_getprop_w(blob, offset, "iommu-map", &lenp);
350 if (!prop) {
351 debug("%s: fsl-mc: ERR: missing iommu-map in fsl-mc bus node\n",
352 __func__);
353 return;
354 }
355
356 iommu_map[0] = cpu_to_fdt32(FSL_DPAA2_STREAM_ID_START);
357 iommu_map[1] = *++prop;
358 iommu_map[2] = cpu_to_fdt32(FSL_DPAA2_STREAM_ID_START);
359 iommu_map[3] = cpu_to_fdt32(FSL_DPAA2_STREAM_ID_END -
360 FSL_DPAA2_STREAM_ID_START + 1);
361
362 fdt_setprop_inplace(blob, offset, "iommu-map",
363 iommu_map, sizeof(iommu_map));
364
365
366 prop = (u32 *)fdt_getprop(blob, offset, "msi-parent", 0);
367 if (!prop) {
368 debug("\n%s: ERROR: missing msi-parent\n", __func__);
369 return;
370 }
371 phandle = fdt32_to_cpu(*prop);
372
373
374 fdt_appendprop_u32(blob, offset, "msi-map", FSL_DPAA2_STREAM_ID_START);
375 fdt_appendprop_u32(blob, offset, "msi-map", phandle);
376 fdt_appendprop_u32(blob, offset, "msi-map", FSL_DPAA2_STREAM_ID_START);
377 fdt_appendprop_u32(blob, offset, "msi-map", FSL_DPAA2_STREAM_ID_END -
378 FSL_DPAA2_STREAM_ID_START + 1);
379}
380
381static int mc_fixup_dpc_mac_addr(void *blob, int dpmac_id,
382#ifdef CONFIG_DM_ETH
383 struct udevice *eth_dev)
384#else
385 struct eth_device *eth_dev)
386#endif
387{
388 int nodeoffset = fdt_path_offset(blob, "/board_info/ports"), noff;
389 int err = 0;
390 char mac_name[10];
391 const char link_type_mode[] = "MAC_LINK_TYPE_FIXED";
392
393 sprintf(mac_name, "mac@%d", dpmac_id);
394
395
396 noff = fdt_subnode_offset(blob, nodeoffset, (const char *)mac_name);
397 if (noff < 0) {
398 err = fdt_increase_size(blob, 200);
399 if (err) {
400 printf("fdt_increase_size: err=%s\n",
401 fdt_strerror(err));
402 return err;
403 }
404
405 noff = fdt_add_subnode(blob, nodeoffset, mac_name);
406 if (noff < 0) {
407 printf("fdt_add_subnode: err=%s\n",
408 fdt_strerror(err));
409 return err;
410 }
411
412
413 err = fdt_appendprop_string(blob, noff,
414 "link_type", link_type_mode);
415 if (err) {
416 printf("fdt_appendprop_string: err=%s\n",
417 fdt_strerror(err));
418 return err;
419 }
420 }
421
422 return mc_fixup_mac_addr(blob, noff, "port_mac_address", eth_dev,
423 MC_FIXUP_DPC);
424}
425
426static int mc_fixup_mac_addrs(void *blob, enum mc_fixup_type type)
427{
428 int i, err = 0, ret = 0;
429#ifdef CONFIG_DM_ETH
430#define ETH_NAME_LEN 20
431 struct udevice *eth_dev;
432#else
433 struct eth_device *eth_dev;
434#endif
435 char ethname[ETH_NAME_LEN];
436
437 for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
438
439 if (wriop_is_enabled_dpmac(i) != 1)
440 continue;
441
442 snprintf(ethname, ETH_NAME_LEN, "DPMAC%d@%s", i,
443 phy_interface_strings[wriop_get_enet_if(i)]);
444
445 eth_dev = eth_get_dev_by_name(ethname);
446 if (eth_dev == NULL)
447 continue;
448
449 switch (type) {
450 case MC_FIXUP_DPL:
451 err = mc_fixup_dpl_mac_addr(blob, i, eth_dev);
452 break;
453 case MC_FIXUP_DPC:
454 err = mc_fixup_dpc_mac_addr(blob, i, eth_dev);
455 break;
456 default:
457 break;
458 }
459
460 if (err)
461 printf("fsl-mc: ERROR fixing mac address for %s\n",
462 ethname);
463 ret |= err;
464 }
465
466 return ret;
467}
468
469static int mc_fixup_dpc(u64 dpc_addr)
470{
471 void *blob = (void *)dpc_addr;
472 int nodeoffset, err = 0;
473
474
475 nodeoffset = fdt_path_offset(blob, "/resources/icid_pools");
476 if (fdt_del_node(blob, nodeoffset) < 0)
477 printf("\nfsl-mc: WARNING: could not delete ICID pool\n");
478
479
480 nodeoffset = fdt_path_offset(blob, "/resources");
481 if (nodeoffset < 0) {
482 printf("\nfsl-mc: ERROR: DPC is missing /resources\n");
483 return -EINVAL;
484 }
485 nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pools");
486 nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pool@0");
487 do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
488 "base_icid", FSL_DPAA2_STREAM_ID_START, 1);
489 do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
490 "num",
491 FSL_DPAA2_STREAM_ID_END -
492 FSL_DPAA2_STREAM_ID_START + 1, 1);
493
494
495 nodeoffset = fdt_path_offset(blob, "/board_info/ports");
496 if (nodeoffset < 0) {
497 err = fdt_increase_size(blob, 512);
498 if (err) {
499 printf("fdt_increase_size: err=%s\n",
500 fdt_strerror(err));
501 goto out;
502 }
503 nodeoffset = fdt_path_offset(blob, "/board_info");
504 if (nodeoffset < 0)
505 nodeoffset = fdt_add_subnode(blob, 0, "board_info");
506
507 nodeoffset = fdt_add_subnode(blob, nodeoffset, "ports");
508 }
509
510 err = mc_fixup_mac_addrs(blob, MC_FIXUP_DPC);
511
512out:
513 flush_dcache_range(dpc_addr, dpc_addr + fdt_totalsize(blob));
514
515 return err;
516}
517
518static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpc_addr)
519{
520 u64 mc_dpc_offset;
521#ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
522 int error;
523 void *dpc_fdt_hdr;
524 int dpc_size;
525#endif
526
527#ifdef CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET
528 BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET & 0x3) != 0 ||
529 CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET > 0xffffffff);
530
531 mc_dpc_offset = CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET;
532#else
533#error "CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET not defined"
534#endif
535
536
537
538
539#ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
540 printf("MC DPC is preloaded to %#llx\n", mc_ram_addr + mc_dpc_offset);
541#else
542
543
544
545 dpc_fdt_hdr = (void *)mc_dpc_addr;
546
547 error = fdt_check_header(dpc_fdt_hdr);
548 if (error != 0) {
549
550
551
552
553 printf("\nfsl-mc: WARNING: No DPC image found");
554 return 0;
555 }
556
557 dpc_size = fdt_totalsize(dpc_fdt_hdr);
558 if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) {
559 printf("\nfsl-mc: ERROR: Bad DPC image (too large: %d)\n",
560 dpc_size);
561 return -EINVAL;
562 }
563
564 mc_copy_image("MC DPC blob",
565 (u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset);
566#endif
567
568 if (mc_fixup_dpc(mc_ram_addr + mc_dpc_offset))
569 return -EINVAL;
570
571 dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset));
572 return 0;
573}
574
575
576static int mc_fixup_dpl(u64 dpl_addr)
577{
578 void *blob = (void *)dpl_addr;
579 u32 ver = fdt_getprop_u32_default(blob, "/", "dpl-version", 0);
580 int err = 0;
581
582
583
584
585 if (ver >= 10)
586 return 0;
587
588 err = mc_fixup_mac_addrs(blob, MC_FIXUP_DPL);
589 flush_dcache_range(dpl_addr, dpl_addr + fdt_totalsize(blob));
590
591 return err;
592}
593
594static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpl_addr)
595{
596 u64 mc_dpl_offset;
597#ifndef CONFIG_SYS_LS_MC_DPL_IN_DDR
598 int error;
599 void *dpl_fdt_hdr;
600 int dpl_size;
601#endif
602
603#ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
604 BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
605 CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
606
607 mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
608#else
609#error "CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET not defined"
610#endif
611
612
613
614
615#ifdef CONFIG_SYS_LS_MC_DPL_IN_DDR
616 printf("MC DPL is preloaded to %#llx\n", mc_ram_addr + mc_dpl_offset);
617#else
618
619
620
621 dpl_fdt_hdr = (void *)mc_dpl_addr;
622
623 error = fdt_check_header(dpl_fdt_hdr);
624 if (error != 0) {
625 printf("\nfsl-mc: ERROR: Bad DPL image (bad header)\n");
626 return error;
627 }
628
629 dpl_size = fdt_totalsize(dpl_fdt_hdr);
630 if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
631 printf("\nfsl-mc: ERROR: Bad DPL image (too large: %d)\n",
632 dpl_size);
633 return -EINVAL;
634 }
635
636 mc_copy_image("MC DPL blob",
637 (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
638#endif
639
640 if (mc_fixup_dpl(mc_ram_addr + mc_dpl_offset))
641 return -EINVAL;
642 dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset));
643 return 0;
644}
645
646
647
648
649static unsigned long get_mc_boot_timeout_ms(void)
650{
651 unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
652
653 char *timeout_ms_env_var = env_get(MC_BOOT_TIMEOUT_ENV_VAR);
654
655 if (timeout_ms_env_var) {
656 timeout_ms = dectoul(timeout_ms_env_var, NULL);
657 if (timeout_ms == 0) {
658 printf("fsl-mc: WARNING: Invalid value for \'"
659 MC_BOOT_TIMEOUT_ENV_VAR
660 "\' environment variable: %lu\n",
661 timeout_ms);
662
663 timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
664 }
665 }
666
667 return timeout_ms;
668}
669
670#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
671
672__weak bool soc_has_aiop(void)
673{
674 return false;
675}
676
677static int load_mc_aiop_img(u64 aiop_fw_addr)
678{
679 u64 mc_ram_addr = mc_get_dram_addr();
680#ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
681 void *aiop_img;
682#endif
683
684
685 if (!soc_has_aiop())
686 return -ENODEV;
687
688
689
690
691#ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
692 printf("MC AIOP is preloaded to %#llx\n", mc_ram_addr +
693 CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
694#else
695 aiop_img = (void *)aiop_fw_addr;
696 mc_copy_image("MC AIOP image",
697 (u64)aiop_img, CONFIG_SYS_LS_MC_AIOP_IMG_MAX_LENGTH,
698 mc_ram_addr + CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
699#endif
700 mc_aiop_applied = 0;
701
702 return 0;
703}
704#endif
705
706static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr)
707{
708 u32 reg_gsr;
709 u32 mc_fw_boot_status;
710 unsigned long timeout_ms = get_mc_boot_timeout_ms();
711 struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
712
713 dmb();
714 assert(timeout_ms > 0);
715 for (;;) {
716 udelay(1000);
717 reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
718 mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
719 if (mc_fw_boot_status & 0x1)
720 break;
721
722 timeout_ms--;
723 if (timeout_ms == 0)
724 break;
725 }
726
727 if (timeout_ms == 0) {
728 printf("ERROR: timeout\n");
729
730
731 return -ETIMEDOUT;
732 }
733
734 if (mc_fw_boot_status != 0x1) {
735
736
737
738
739
740
741 printf("WARNING: Firmware returned an error (GSR: %#x)\n",
742 reg_gsr);
743 } else {
744 printf("SUCCESS\n");
745 }
746
747
748 *final_reg_gsr = reg_gsr;
749 return 0;
750}
751
752int mc_init(u64 mc_fw_addr, u64 mc_dpc_addr)
753{
754 int error = 0;
755 int portal_id = 0;
756 struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
757 u64 mc_ram_addr = mc_get_dram_addr();
758 u32 reg_gsr;
759 u32 reg_mcfbalr;
760#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
761 const void *raw_image_addr;
762 size_t raw_image_size = 0;
763#endif
764 u8 mc_ram_num_256mb_blocks;
765 size_t mc_ram_size = mc_get_dram_block_size();
766
767 mc_ram_num_256mb_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT;
768
769 if (mc_ram_num_256mb_blocks >= 0xff) {
770 error = -EINVAL;
771 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
772 mc_ram_size);
773 goto out;
774 }
775
776
777
778
779 if (mc_ram_num_256mb_blocks == 0)
780 mc_ram_num_256mb_blocks = 0xFF;
781
782
783
784
785
786
787
788
789
790
791
792
793
794 out_le32(&mc_ccsr_regs->reg_gcr1, 0);
795 dmb();
796
797#ifdef CONFIG_SYS_LS_MC_FW_IN_DDR
798 printf("MC firmware is preloaded to %#llx\n", mc_ram_addr);
799#else
800 error = parse_mc_firmware_fit_image(mc_fw_addr, &raw_image_addr,
801 &raw_image_size);
802 if (error != 0)
803 goto out;
804
805
806
807 mc_copy_image("MC Firmware",
808 (u64)raw_image_addr, raw_image_size, mc_ram_addr);
809#endif
810 dump_ram_words("firmware", (void *)mc_ram_addr);
811
812 error = load_mc_dpc(mc_ram_addr, mc_ram_size, mc_dpc_addr);
813 if (error != 0)
814 goto out;
815
816 debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
817 dump_mc_ccsr_regs(mc_ccsr_regs);
818
819
820
821
822 if (mc_ram_num_256mb_blocks < 0xFF) {
823 reg_mcfbalr = (u32)mc_ram_addr |
824 (mc_ram_num_256mb_blocks - 1);
825 } else {
826 reg_mcfbalr = (u32)mc_ram_addr |
827 (mc_ram_num_256mb_blocks);
828 }
829
830 out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr);
831 out_le32(&mc_ccsr_regs->reg_mcfbahr,
832 (u32)(mc_ram_addr >> 32));
833 out_le32(&mc_ccsr_regs->reg_mcfapr, FSL_BYPASS_AMQ);
834
835
836
837
838 out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00);
839
840 printf("\nfsl-mc: Booting Management Complex ... ");
841
842
843
844
845 out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
846 error = wait_for_mc(true, ®_gsr);
847 if (error != 0)
848 goto out;
849
850
851
852
853
854 portal_id = 0;
855
856
857
858
859
860 root_mc_io = (struct fsl_mc_io *)calloc(sizeof(struct fsl_mc_io), 1);
861 if (!root_mc_io) {
862 printf(" No memory: calloc() failed\n");
863 return -ENOMEM;
864 }
865
866 root_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
867 debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
868 portal_id, root_mc_io->mmio_regs);
869
870 error = mc_get_version(root_mc_io, MC_CMD_NO_FLAGS, &mc_ver_info);
871 if (error != 0) {
872 printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n",
873 error);
874 goto out;
875 }
876
877 printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n",
878 mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision,
879 reg_gsr & GSR_FS_MASK);
880
881out:
882 if (error != 0)
883 mc_boot_status = error;
884 else
885 mc_boot_status = 0;
886
887 return error;
888}
889
890int mc_apply_dpl(u64 mc_dpl_addr)
891{
892 struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
893 int error = 0;
894 u32 reg_gsr;
895 u64 mc_ram_addr = mc_get_dram_addr();
896 size_t mc_ram_size = mc_get_dram_block_size();
897
898 if (!mc_dpl_addr)
899 return -1;
900
901 error = load_mc_dpl(mc_ram_addr, mc_ram_size, mc_dpl_addr);
902 if (error != 0)
903 return error;
904
905
906
907
908 out_le32(&mc_ccsr_regs->reg_gsr, 0x0);
909 printf("fsl-mc: Deploying data path layout ... ");
910 error = wait_for_mc(false, ®_gsr);
911
912 if (!error)
913 mc_dpl_applied = 0;
914
915 return error;
916}
917
918int get_mc_boot_status(void)
919{
920 return mc_boot_status;
921}
922
923#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
924int get_aiop_apply_status(void)
925{
926 return mc_aiop_applied;
927}
928#endif
929
930int get_dpl_apply_status(void)
931{
932 return mc_dpl_applied;
933}
934
935int is_lazy_dpl_addr_valid(void)
936{
937 return !!mc_lazy_dpl_addr;
938}
939
940
941
942
943
944
945
946
947u64 mc_get_dram_addr(void)
948{
949 size_t mc_ram_size = mc_get_dram_block_size();
950
951 if (!mc_memset_resv_ram || (get_mc_boot_status() < 0)) {
952 mc_memset_resv_ram = 1;
953 memset((void *)gd->arch.resv_ram, 0, mc_ram_size);
954 }
955
956 return (gd->arch.resv_ram + mc_ram_size - 1) &
957 MC_RAM_BASE_ADDR_ALIGNMENT_MASK;
958}
959
960
961
962
963unsigned long mc_get_dram_block_size(void)
964{
965 unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
966
967 char *dram_block_size_env_var = env_get(MC_MEM_SIZE_ENV_VAR);
968
969 if (dram_block_size_env_var) {
970 dram_block_size = hextoul(dram_block_size_env_var, NULL);
971
972 if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
973 printf("fsl-mc: WARNING: Invalid value for \'"
974 MC_MEM_SIZE_ENV_VAR
975 "\' environment variable: %lu\n",
976 dram_block_size);
977
978 dram_block_size = MC_DRAM_BLOCK_DEFAULT_SIZE;
979 }
980 }
981
982 return dram_block_size;
983}
984
985int fsl_mc_ldpaa_init(struct bd_info *bis)
986{
987 int i;
988
989 for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++)
990 if (wriop_is_enabled_dpmac(i) == 1)
991 ldpaa_eth_init(i, wriop_get_enet_if(i));
992 return 0;
993}
994
995static int dprc_version_check(struct fsl_mc_io *mc_io, uint16_t handle)
996{
997 int error;
998 uint16_t major_ver, minor_ver;
999
1000 error = dprc_get_api_version(mc_io, 0,
1001 &major_ver,
1002 &minor_ver);
1003 if (error < 0) {
1004 printf("dprc_get_api_version() failed: %d\n", error);
1005 return error;
1006 }
1007
1008 if (major_ver < DPRC_VER_MAJOR || (major_ver == DPRC_VER_MAJOR &&
1009 minor_ver < DPRC_VER_MINOR)) {
1010 printf("DPRC version mismatch found %u.%u,",
1011 major_ver, minor_ver);
1012 printf("supported version is %u.%u\n",
1013 DPRC_VER_MAJOR, DPRC_VER_MINOR);
1014 }
1015
1016 return error;
1017}
1018
1019static int dpio_init(void)
1020{
1021 struct qbman_swp_desc p_des;
1022 struct dpio_attr attr;
1023 struct dpio_cfg dpio_cfg;
1024 int err = 0;
1025 uint16_t major_ver, minor_ver;
1026
1027 dflt_dpio = (struct fsl_dpio_obj *)calloc(
1028 sizeof(struct fsl_dpio_obj), 1);
1029 if (!dflt_dpio) {
1030 printf("No memory: calloc() failed\n");
1031 err = -ENOMEM;
1032 goto err_calloc;
1033 }
1034 dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL;
1035 dpio_cfg.num_priorities = 8;
1036
1037 err = dpio_create(dflt_mc_io,
1038 dflt_dprc_handle,
1039 MC_CMD_NO_FLAGS,
1040 &dpio_cfg,
1041 &dflt_dpio->dpio_id);
1042 if (err < 0) {
1043 printf("dpio_create() failed: %d\n", err);
1044 err = -ENODEV;
1045 goto err_create;
1046 }
1047
1048 err = dpio_get_api_version(dflt_mc_io, 0,
1049 &major_ver,
1050 &minor_ver);
1051 if (err < 0) {
1052 printf("dpio_get_api_version() failed: %d\n", err);
1053 goto err_get_api_ver;
1054 }
1055
1056 if (major_ver < DPIO_VER_MAJOR || (major_ver == DPIO_VER_MAJOR &&
1057 minor_ver < DPIO_VER_MINOR)) {
1058 printf("DPRC version mismatch found %u.%u,",
1059 major_ver,
1060 minor_ver);
1061 }
1062
1063 err = dpio_open(dflt_mc_io,
1064 MC_CMD_NO_FLAGS,
1065 dflt_dpio->dpio_id,
1066 &dflt_dpio->dpio_handle);
1067 if (err) {
1068 printf("dpio_open() failed\n");
1069 goto err_open;
1070 }
1071
1072 memset(&attr, 0, sizeof(struct dpio_attr));
1073 err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1074 dflt_dpio->dpio_handle, &attr);
1075 if (err < 0) {
1076 printf("dpio_get_attributes() failed: %d\n", err);
1077 goto err_get_attr;
1078 }
1079
1080 if (dflt_dpio->dpio_id != attr.id) {
1081 printf("dnpi object id and attribute id are not same\n");
1082 goto err_attr_not_same;
1083 }
1084
1085#ifdef DEBUG
1086 printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id);
1087#endif
1088 err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1089 if (err < 0) {
1090 printf("dpio_enable() failed %d\n", err);
1091 goto err_get_enable;
1092 }
1093 debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n",
1094 attr.qbman_portal_ce_offset,
1095 attr.qbman_portal_ci_offset,
1096 attr.qbman_portal_id,
1097 attr.num_priorities);
1098
1099 p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
1100 + attr.qbman_portal_ce_offset);
1101 p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
1102 + attr.qbman_portal_ci_offset);
1103
1104 dflt_dpio->sw_portal = qbman_swp_init(&p_des);
1105 if (dflt_dpio->sw_portal == NULL) {
1106 printf("qbman_swp_init() failed\n");
1107 goto err_get_swp_init;
1108 }
1109 return 0;
1110
1111err_get_swp_init:
1112 dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1113err_get_enable:
1114err_get_attr:
1115err_attr_not_same:
1116 dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1117err_open:
1118err_get_api_ver:
1119 dpio_destroy(dflt_mc_io,
1120 dflt_dprc_handle,
1121 MC_CMD_NO_FLAGS,
1122 dflt_dpio->dpio_id);
1123err_create:
1124 free(dflt_dpio);
1125err_calloc:
1126 return err;
1127}
1128
1129static int dpio_exit(void)
1130{
1131 int err;
1132
1133 err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1134 if (err < 0) {
1135 printf("dpio_disable() failed: %d\n", err);
1136 goto err;
1137 }
1138
1139 err = dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1140 if (err < 0) {
1141 printf("dpio_close() failed: %d\n", err);
1142 goto err;
1143 }
1144
1145 err = dpio_destroy(dflt_mc_io,
1146 dflt_dprc_handle,
1147 MC_CMD_NO_FLAGS,
1148 dflt_dpio->dpio_id);
1149 if (err < 0) {
1150 printf("dpio_destroy() failed: %d\n", err);
1151 goto err;
1152 }
1153
1154#ifdef DEBUG
1155 printf("Exit: DPIO id=0x%d\n", dflt_dpio->dpio_id);
1156#endif
1157
1158 if (dflt_dpio)
1159 free(dflt_dpio);
1160
1161 return 0;
1162err:
1163 return err;
1164}
1165
1166static int dprc_init(void)
1167{
1168 int err, child_portal_id, container_id;
1169 struct dprc_cfg cfg;
1170 uint64_t mc_portal_offset;
1171
1172
1173 err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id);
1174 if (err < 0) {
1175 printf("dprc_get_container_id(): Root failed: %d\n", err);
1176 goto err_root_container_id;
1177 }
1178
1179#ifdef DEBUG
1180 printf("Root container id = %d\n", container_id);
1181#endif
1182 err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id,
1183 &root_dprc_handle);
1184 if (err < 0) {
1185 printf("dprc_open(): Root Container failed: %d\n", err);
1186 goto err_root_open;
1187 }
1188
1189 if (!root_dprc_handle) {
1190 printf("dprc_open(): Root Container Handle is not valid\n");
1191 goto err_root_open;
1192 }
1193
1194 err = dprc_version_check(root_mc_io, root_dprc_handle);
1195 if (err < 0) {
1196 printf("dprc_version_check() failed: %d\n", err);
1197 goto err_root_open;
1198 }
1199
1200 memset(&cfg, 0, sizeof(struct dprc_cfg));
1201 cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED |
1202 DPRC_CFG_OPT_OBJ_CREATE_ALLOWED |
1203 DPRC_CFG_OPT_ALLOC_ALLOWED;
1204 cfg.icid = DPRC_GET_ICID_FROM_POOL;
1205 cfg.portal_id = DPRC_GET_PORTAL_ID_FROM_POOL;
1206 err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS,
1207 root_dprc_handle,
1208 &cfg,
1209 &child_dprc_id,
1210 &mc_portal_offset);
1211 if (err < 0) {
1212 printf("dprc_create_container() failed: %d\n", err);
1213 goto err_create;
1214 }
1215
1216 dflt_mc_io = (struct fsl_mc_io *)calloc(sizeof(struct fsl_mc_io), 1);
1217 if (!dflt_mc_io) {
1218 err = -ENOMEM;
1219 printf(" No memory: calloc() failed\n");
1220 goto err_calloc;
1221 }
1222
1223 child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset);
1224 dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id);
1225
1226#ifdef DEBUG
1227 printf("MC portal of child DPRC container: %d, physical addr %p)\n",
1228 child_dprc_id, dflt_mc_io->mmio_regs);
1229#endif
1230
1231 err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id,
1232 &dflt_dprc_handle);
1233 if (err < 0) {
1234 printf("dprc_open(): Child container failed: %d\n", err);
1235 goto err_child_open;
1236 }
1237
1238 if (!dflt_dprc_handle) {
1239 printf("dprc_open(): Child container Handle is not valid\n");
1240 goto err_child_open;
1241 }
1242
1243 return 0;
1244err_child_open:
1245 free(dflt_mc_io);
1246err_calloc:
1247 dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
1248 root_dprc_handle, child_dprc_id);
1249err_create:
1250 dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
1251err_root_open:
1252err_root_container_id:
1253 return err;
1254}
1255
1256static int dprc_exit(void)
1257{
1258 int err;
1259
1260 err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle);
1261 if (err < 0) {
1262 printf("dprc_close(): Child failed: %d\n", err);
1263 goto err;
1264 }
1265
1266 err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
1267 root_dprc_handle, child_dprc_id);
1268 if (err < 0) {
1269 printf("dprc_destroy_container() failed: %d\n", err);
1270 goto err;
1271 }
1272
1273 err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
1274 if (err < 0) {
1275 printf("dprc_close(): Root failed: %d\n", err);
1276 goto err;
1277 }
1278
1279 if (dflt_mc_io)
1280 free(dflt_mc_io);
1281
1282 if (root_mc_io)
1283 free(root_mc_io);
1284
1285 return 0;
1286
1287err:
1288 return err;
1289}
1290
1291static int dpbp_init(void)
1292{
1293 int err;
1294 struct dpbp_attr dpbp_attr;
1295 struct dpbp_cfg dpbp_cfg;
1296 uint16_t major_ver, minor_ver;
1297
1298 dflt_dpbp = (struct fsl_dpbp_obj *)calloc(
1299 sizeof(struct fsl_dpbp_obj), 1);
1300 if (!dflt_dpbp) {
1301 printf("No memory: calloc() failed\n");
1302 err = -ENOMEM;
1303 goto err_calloc;
1304 }
1305
1306 dpbp_cfg.options = 512;
1307
1308 err = dpbp_create(dflt_mc_io,
1309 dflt_dprc_handle,
1310 MC_CMD_NO_FLAGS,
1311 &dpbp_cfg,
1312 &dflt_dpbp->dpbp_id);
1313
1314 if (err < 0) {
1315 err = -ENODEV;
1316 printf("dpbp_create() failed: %d\n", err);
1317 goto err_create;
1318 }
1319
1320 err = dpbp_get_api_version(dflt_mc_io, 0,
1321 &major_ver,
1322 &minor_ver);
1323 if (err < 0) {
1324 printf("dpbp_get_api_version() failed: %d\n", err);
1325 goto err_get_api_ver;
1326 }
1327
1328 if (major_ver < DPBP_VER_MAJOR || (major_ver == DPBP_VER_MAJOR &&
1329 minor_ver < DPBP_VER_MINOR)) {
1330 printf("DPBP version mismatch found %u.%u,",
1331 major_ver, minor_ver);
1332 printf("supported version is %u.%u\n",
1333 DPBP_VER_MAJOR, DPBP_VER_MINOR);
1334 }
1335
1336 err = dpbp_open(dflt_mc_io,
1337 MC_CMD_NO_FLAGS,
1338 dflt_dpbp->dpbp_id,
1339 &dflt_dpbp->dpbp_handle);
1340 if (err) {
1341 printf("dpbp_open() failed\n");
1342 goto err_open;
1343 }
1344
1345 memset(&dpbp_attr, 0, sizeof(struct dpbp_attr));
1346 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1347 dflt_dpbp->dpbp_handle,
1348 &dpbp_attr);
1349 if (err < 0) {
1350 printf("dpbp_get_attributes() failed: %d\n", err);
1351 goto err_get_attr;
1352 }
1353
1354 if (dflt_dpbp->dpbp_id != dpbp_attr.id) {
1355 printf("dpbp object id and attribute id are not same\n");
1356 goto err_attr_not_same;
1357 }
1358
1359#ifdef DEBUG
1360 printf("Init: DPBP id=0x%x\n", dflt_dpbp->dpbp_attr.id);
1361#endif
1362
1363 err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1364 if (err < 0) {
1365 printf("dpbp_close() failed: %d\n", err);
1366 goto err_close;
1367 }
1368
1369 return 0;
1370
1371err_get_attr:
1372err_attr_not_same:
1373 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1374 dpbp_destroy(dflt_mc_io,
1375 dflt_dprc_handle,
1376 MC_CMD_NO_FLAGS,
1377 dflt_dpbp->dpbp_id);
1378err_get_api_ver:
1379err_close:
1380err_open:
1381err_create:
1382 free(dflt_dpbp);
1383err_calloc:
1384 return err;
1385}
1386
1387static int dpbp_exit(void)
1388{
1389 int err;
1390
1391 err = dpbp_destroy(dflt_mc_io, dflt_dprc_handle, MC_CMD_NO_FLAGS,
1392 dflt_dpbp->dpbp_id);
1393 if (err < 0) {
1394 printf("dpbp_destroy() failed: %d\n", err);
1395 goto err;
1396 }
1397
1398#ifdef DEBUG
1399 printf("Exit: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
1400#endif
1401
1402 if (dflt_dpbp)
1403 free(dflt_dpbp);
1404 return 0;
1405
1406err:
1407 return err;
1408}
1409
1410static int dpni_init(void)
1411{
1412 int err;
1413 uint8_t cfg_buf[256] = {0};
1414 struct dpni_cfg dpni_cfg;
1415 uint16_t major_ver, minor_ver;
1416
1417 dflt_dpni = (struct fsl_dpni_obj *)calloc(
1418 sizeof(struct fsl_dpni_obj), 1);
1419 if (!dflt_dpni) {
1420 printf("No memory: calloc() failed\n");
1421 err = -ENOMEM;
1422 goto err_calloc;
1423 }
1424
1425 memset(&dpni_cfg, 0, sizeof(dpni_cfg));
1426 err = dpni_prepare_cfg(&dpni_cfg, &cfg_buf[0]);
1427 if (err < 0) {
1428 err = -ENODEV;
1429 printf("dpni_prepare_cfg() failed: %d\n", err);
1430 goto err_prepare_cfg;
1431 }
1432
1433 err = dpni_create(dflt_mc_io,
1434 dflt_dprc_handle,
1435 MC_CMD_NO_FLAGS,
1436 &dpni_cfg,
1437 &dflt_dpni->dpni_id);
1438 if (err < 0) {
1439 err = -ENODEV;
1440 printf("dpni create() failed: %d\n", err);
1441 goto err_create;
1442 }
1443
1444 err = dpni_get_api_version(dflt_mc_io, 0,
1445 &major_ver,
1446 &minor_ver);
1447 if (err < 0) {
1448 printf("dpni_get_api_version() failed: %d\n", err);
1449 goto err_get_version;
1450 }
1451
1452 if (major_ver < DPNI_VER_MAJOR || (major_ver == DPNI_VER_MAJOR &&
1453 minor_ver < DPNI_VER_MINOR)) {
1454 printf("DPNI version mismatch found %u.%u,",
1455 major_ver, minor_ver);
1456 printf("supported version is %u.%u\n",
1457 DPNI_VER_MAJOR, DPNI_VER_MINOR);
1458 }
1459
1460 err = dpni_open(dflt_mc_io,
1461 MC_CMD_NO_FLAGS,
1462 dflt_dpni->dpni_id,
1463 &dflt_dpni->dpni_handle);
1464 if (err) {
1465 printf("dpni_open() failed\n");
1466 goto err_open;
1467 }
1468
1469#ifdef DEBUG
1470 printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1471#endif
1472 err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1473 if (err < 0) {
1474 printf("dpni_close() failed: %d\n", err);
1475 goto err_close;
1476 }
1477
1478 return 0;
1479
1480err_close:
1481 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1482err_open:
1483err_get_version:
1484 dpni_destroy(dflt_mc_io,
1485 dflt_dprc_handle,
1486 MC_CMD_NO_FLAGS,
1487 dflt_dpni->dpni_id);
1488err_create:
1489err_prepare_cfg:
1490 free(dflt_dpni);
1491err_calloc:
1492 return err;
1493}
1494
1495static int dpni_exit(void)
1496{
1497 int err;
1498
1499 err = dpni_destroy(dflt_mc_io, dflt_dprc_handle, MC_CMD_NO_FLAGS,
1500 dflt_dpni->dpni_id);
1501 if (err < 0) {
1502 printf("dpni_destroy() failed: %d\n", err);
1503 goto err;
1504 }
1505
1506#ifdef DEBUG
1507 printf("Exit: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1508#endif
1509
1510 if (dflt_dpni)
1511 free(dflt_dpni);
1512 return 0;
1513
1514err:
1515 return err;
1516}
1517
1518static bool is_dpsparser_supported(void)
1519{
1520
1521 if (mc_ver_info.major < 10)
1522 return false;
1523 if (mc_ver_info.major == 10)
1524 return (mc_ver_info.minor >= 12);
1525 return true;
1526}
1527
1528static int dpsparser_version_check(struct fsl_mc_io *mc_io)
1529{
1530 int error;
1531 u16 major_ver, minor_ver;
1532
1533 if (!is_dpsparser_supported())
1534 return 0;
1535
1536 error = dpsparser_get_api_version(mc_io, 0,
1537 &major_ver,
1538 &minor_ver);
1539 if (error < 0) {
1540 printf("dpsparser_get_api_version() failed: %d\n", error);
1541 return error;
1542 }
1543
1544 if (major_ver < DPSPARSER_VER_MAJOR || (major_ver ==
1545 DPSPARSER_VER_MAJOR && minor_ver < DPSPARSER_VER_MINOR)) {
1546 printf("DPSPARSER version mismatch found %u.%u,",
1547 major_ver, minor_ver);
1548 printf("supported version is %u.%u\n",
1549 DPSPARSER_VER_MAJOR, DPSPARSER_VER_MINOR);
1550 }
1551
1552 return error;
1553}
1554
1555static int dpsparser_init(void)
1556{
1557 int err = 0;
1558
1559 if (!is_dpsparser_supported())
1560 return 0;
1561
1562 err = dpsparser_create(dflt_mc_io,
1563 dflt_dprc_handle,
1564 MC_CMD_NO_FLAGS,
1565 &dpsparser_obj_id);
1566 if (err)
1567 printf("dpsparser_create() failed\n");
1568
1569 err = dpsparser_version_check(dflt_mc_io);
1570 if (err < 0) {
1571 printf("dpsparser_version_check() failed: %d\n", err);
1572 goto err_version_check;
1573 }
1574
1575 err = dpsparser_open(dflt_mc_io,
1576 MC_CMD_NO_FLAGS,
1577 &dpsparser_handle);
1578 if (err < 0) {
1579 printf("dpsparser_open() failed: %d\n", err);
1580 goto err_open;
1581 }
1582
1583 return err;
1584
1585err_open:
1586err_version_check:
1587 dpsparser_destroy(dflt_mc_io,
1588 dflt_dprc_handle,
1589 MC_CMD_NO_FLAGS, dpsparser_obj_id);
1590
1591 return err;
1592}
1593
1594#ifdef DPSPARSER_DESTROY
1595
1596
1597
1598
1599static int dpsparser_exit(void)
1600{
1601 int err;
1602
1603 if (!is_dpsparser_supported())
1604 return 0;
1605
1606 dpsparser_close(dflt_mc_io, MC_CMD_NO_FLAGS, dpsparser_handle);
1607 if (err < 0) {
1608 printf("dpsparser_close() failed: %d\n", err);
1609 goto err;
1610 }
1611
1612 err = dpsparser_destroy(dflt_mc_io, dflt_dprc_handle,
1613 MC_CMD_NO_FLAGS, dpsparser_obj_id);
1614 if (err < 0) {
1615 printf("dpsparser_destroy() failed: %d\n", err);
1616 goto err;
1617 }
1618 return 0;
1619
1620err:
1621 return err;
1622}
1623#endif
1624
1625int mc_apply_spb(u64 mc_spb_addr)
1626{
1627 int err = 0;
1628 u16 error, err_arr_size;
1629 u64 mc_spb_offset;
1630 u32 spb_size;
1631 struct sp_blob_header *sp_blob;
1632 u64 mc_ram_addr = mc_get_dram_addr();
1633
1634 if (!is_dpsparser_supported())
1635 return 0;
1636
1637 if (!mc_spb_addr) {
1638 printf("fsl-mc: Invalid Blob address\n");
1639 return -1;
1640 }
1641
1642#ifdef CONFIG_MC_DRAM_SPB_OFFSET
1643 mc_spb_offset = CONFIG_MC_DRAM_SPB_OFFSET;
1644#else
1645#error "CONFIG_MC_DRAM_SPB_OFFSET not defined"
1646#endif
1647
1648
1649 sp_blob = (struct sp_blob_header *)mc_spb_addr;
1650 spb_size = le32_to_cpu(sp_blob->length);
1651 if (spb_size > CONFIG_MC_SPB_MAX_SIZE) {
1652 printf("\nfsl-mc: ERROR: Bad SPB image (too large: %d)\n",
1653 spb_size);
1654 return -EINVAL;
1655 }
1656
1657 mc_copy_image("MC SP Blob", mc_spb_addr, spb_size,
1658 mc_ram_addr + mc_spb_offset);
1659
1660
1661 printf("fsl-mc: Applying soft parser blob... ");
1662 err = dpsparser_apply_spb(dflt_mc_io, MC_CMD_NO_FLAGS, dpsparser_handle,
1663 mc_spb_offset, &error);
1664 if (err)
1665 return err;
1666
1667 if (error == 0) {
1668 printf("SUCCESS\n");
1669 } else {
1670 printf("FAILED with error code = %d:\n", error);
1671 err_arr_size = (u16)ARRAY_SIZE(mc_err_msg_apply_spb);
1672
1673 if (error > 0 && error < err_arr_size)
1674 printf(mc_err_msg_apply_spb[error]);
1675 else
1676 printf(MC_ERROR_MSG_SPB_UNKNOWN);
1677 }
1678
1679 return err;
1680}
1681
1682static int mc_init_object(void)
1683{
1684 int err = 0;
1685
1686 err = dprc_init();
1687 if (err < 0) {
1688 printf("dprc_init() failed: %d\n", err);
1689 goto err;
1690 }
1691
1692 err = dpbp_init();
1693 if (err < 0) {
1694 printf("dpbp_init() failed: %d\n", err);
1695 goto err;
1696 }
1697
1698 err = dpio_init();
1699 if (err < 0) {
1700 printf("dpio_init() failed: %d\n", err);
1701 goto err;
1702 }
1703
1704 err = dpni_init();
1705 if (err < 0) {
1706 printf("dpni_init() failed: %d\n", err);
1707 goto err;
1708 }
1709
1710 err = dpsparser_init();
1711 if (err < 0) {
1712 printf("dpsparser_init() failed: %d\n", err);
1713 goto err;
1714 }
1715
1716 return 0;
1717err:
1718 return err;
1719}
1720
1721int fsl_mc_ldpaa_exit(struct bd_info *bd)
1722{
1723 int err = 0;
1724 bool is_dpl_apply_status = false;
1725 bool mc_boot_status = false;
1726
1727 if (bd && mc_lazy_dpl_addr && !fsl_mc_ldpaa_exit(NULL)) {
1728 err = mc_apply_dpl(mc_lazy_dpl_addr);
1729 if (!err)
1730 fdt_fixup_board_enet(working_fdt);
1731 mc_lazy_dpl_addr = 0;
1732 }
1733
1734 if (!get_mc_boot_status())
1735 mc_boot_status = true;
1736
1737
1738 if (bd && !mc_boot_status)
1739 return 0;
1740
1741
1742 if (!get_dpl_apply_status())
1743 is_dpl_apply_status = true;
1744
1745
1746
1747
1748
1749 if (bd && mc_boot_status && !is_dpl_apply_status) {
1750 printf("fsl-mc: DPL not deployed, DPAA2 ethernet not work\n");
1751 goto mc_obj_cleanup;
1752 }
1753
1754 if (bd && mc_boot_status && is_dpl_apply_status)
1755 return 0;
1756
1757mc_obj_cleanup:
1758 err = dpbp_exit();
1759 if (err < 0) {
1760 printf("dpbp_exit() failed: %d\n", err);
1761 goto err;
1762 }
1763
1764 err = dpio_exit();
1765 if (err < 0) {
1766 printf("dpio_exit() failed: %d\n", err);
1767 goto err;
1768 }
1769
1770 err = dpni_exit();
1771 if (err < 0) {
1772 printf("dpni_exit() failed: %d\n", err);
1773 goto err;
1774 }
1775
1776 err = dprc_exit();
1777 if (err < 0) {
1778 printf("dprc_exit() failed: %d\n", err);
1779 goto err;
1780 }
1781
1782 return 0;
1783err:
1784 return err;
1785}
1786
1787static void print_k_bytes(const void *buf, ssize_t *size)
1788{
1789 while (*size > 0) {
1790 int count = printf("%s", (char *)buf);
1791
1792 buf += count;
1793 *size -= count;
1794 }
1795}
1796
1797static void mc_dump_log(void)
1798{
1799 struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
1800 u64 high = in_le64(&mc_ccsr_regs->reg_mcfbahr) & MC_FW_ADDR_MASK_HIGH;
1801 u64 low = in_le64(&mc_ccsr_regs->reg_mcfbalr) & MC_FW_ADDR_MASK_LOW;
1802 u32 buf_len, wrapped, last_byte, magic, buf_start;
1803 u64 mc_addr = (high << 32) | low;
1804 struct log_header *header;
1805 ssize_t size, bytes_end;
1806 const void *end_of_data;
1807 const void *map_addr;
1808 const void *end_addr;
1809 const void *cur_ptr;
1810 const void *buf;
1811
1812 map_addr = map_sysmem(mc_addr + MC_STRUCT_BUFFER_OFFSET,
1813 MC_BUFFER_SIZE);
1814 header = (struct log_header *)map_addr;
1815 last_byte = in_le32(&header->last_byte);
1816 buf_len = in_le32(&header->buf_length);
1817 magic = in_le32(&header->magic_word);
1818 buf_start = in_le32(&header->buf_start);
1819 buf = map_addr + buf_start - MC_OFFSET_DELTA;
1820 end_addr = buf + buf_len;
1821 wrapped = last_byte & LOG_HEADER_FLAG_BUFFER_WRAPAROUND;
1822 end_of_data = buf + LAST_BYTE(last_byte);
1823
1824 if (magic != MAGIC_MC) {
1825 puts("Magic number is not valid\n");
1826 printf("expected = %08x, received = %08x\n", MAGIC_MC, magic);
1827 goto err_magic;
1828 }
1829
1830 if (wrapped && end_of_data != end_addr)
1831 cur_ptr = end_of_data + 1;
1832 else
1833 cur_ptr = buf;
1834
1835 if (cur_ptr <= end_of_data)
1836 size = end_of_data - cur_ptr;
1837 else
1838 size = (end_addr - cur_ptr) + (end_of_data - buf);
1839
1840 bytes_end = end_addr - cur_ptr;
1841 if (size > bytes_end) {
1842 print_k_bytes(cur_ptr, &bytes_end);
1843
1844 cur_ptr = buf;
1845 size -= bytes_end;
1846 }
1847
1848 print_k_bytes(buf, &size);
1849
1850err_magic:
1851 unmap_sysmem(map_addr);
1852}
1853
1854static int do_fsl_mc(struct cmd_tbl *cmdtp, int flag, int argc,
1855 char *const argv[])
1856{
1857 int err = 0;
1858 if (argc < 2)
1859 goto usage;
1860
1861 switch (argv[1][0]) {
1862 case 's': {
1863 char sub_cmd;
1864 u64 mc_fw_addr, mc_dpc_addr;
1865#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1866 u64 aiop_fw_addr;
1867#endif
1868 if (argc < 3)
1869 goto usage;
1870
1871 sub_cmd = argv[2][0];
1872
1873 switch (sub_cmd) {
1874 case 'm':
1875 if (argc < 5)
1876 goto usage;
1877
1878 if (get_mc_boot_status() == 0) {
1879 printf("fsl-mc: MC is already booted");
1880 printf("\n");
1881 return err;
1882 }
1883 mc_fw_addr = simple_strtoull(argv[3], NULL, 16);
1884 mc_dpc_addr = simple_strtoull(argv[4], NULL,
1885 16);
1886
1887 if (!mc_init(mc_fw_addr, mc_dpc_addr))
1888 err = mc_init_object();
1889 break;
1890
1891#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1892 case 'a':
1893 if (argc < 4)
1894 goto usage;
1895 if (get_aiop_apply_status() == 0) {
1896 printf("fsl-mc: AIOP FW is already");
1897 printf(" applied\n");
1898 return err;
1899 }
1900
1901 aiop_fw_addr = simple_strtoull(argv[3], NULL,
1902 16);
1903
1904
1905 err = load_mc_aiop_img(aiop_fw_addr);
1906 if (!err)
1907 printf("fsl-mc: AIOP FW applied\n");
1908 break;
1909#endif
1910 default:
1911 printf("Invalid option: %s\n", argv[2]);
1912 goto usage;
1913
1914 break;
1915 }
1916 }
1917 break;
1918
1919 case 'l': {
1920
1921 u64 mc_dpl_addr;
1922
1923 if (argc < 4)
1924 goto usage;
1925
1926 if (get_dpl_apply_status() == 0) {
1927 printf("fsl-mc: DPL already applied\n");
1928 return err;
1929 }
1930
1931 mc_dpl_addr = simple_strtoull(argv[3], NULL, 16);
1932
1933 if (get_mc_boot_status() != 0) {
1934 printf("fsl-mc: Deploying data path layout ..");
1935 printf("ERROR (MC is not booted)\n");
1936 return -ENODEV;
1937 }
1938
1939
1940
1941
1942
1943 mc_lazy_dpl_addr = mc_dpl_addr;
1944 break;
1945 }
1946
1947 case 'a': {
1948
1949 char sub_cmd;
1950 u64 mc_apply_addr;
1951
1952 if (argc < 4)
1953 goto usage;
1954
1955 sub_cmd = argv[2][0];
1956
1957 switch (sub_cmd) {
1958 case 'd':
1959 case 'D':
1960 if (get_dpl_apply_status() == 0) {
1961 printf("fsl-mc: DPL already applied\n");
1962 return err;
1963 }
1964 if (get_mc_boot_status() != 0) {
1965 printf("fsl-mc: Deploying data path layout ..");
1966 printf("ERROR (MC is not booted)\n");
1967 return -ENODEV;
1968 }
1969
1970 mc_apply_addr = simple_strtoull(argv[3], NULL, 16);
1971
1972
1973 if (!fsl_mc_ldpaa_exit(NULL))
1974 err = mc_apply_dpl(mc_apply_addr);
1975 break;
1976
1977 case 's':
1978 if (!is_dpsparser_supported()) {
1979 printf("fsl-mc: apply spb command .. ");
1980 printf("ERROR: requires at least MC 10.12.0\n");
1981 return err;
1982 }
1983 if (get_mc_boot_status() != 0) {
1984 printf("fsl-mc: Deploying Soft Parser Blob...");
1985 printf("ERROR (MC is not booted)\n");
1986 return err;
1987 }
1988
1989 mc_apply_addr = simple_strtoull(argv[3], NULL, 16);
1990
1991
1992 err = mc_apply_spb(mc_apply_addr);
1993 break;
1994
1995 default:
1996 printf("Invalid option: %s\n", argv[2]);
1997 goto usage;
1998 }
1999 break;
2000 }
2001 case 'd':
2002 if (argc > 2)
2003 goto usage;
2004
2005 mc_dump_log();
2006 break;
2007 default:
2008 printf("Invalid option: %s\n", argv[1]);
2009 goto usage;
2010 break;
2011 }
2012 return err;
2013 usage:
2014 return CMD_RET_USAGE;
2015}
2016
2017U_BOOT_CMD(
2018 fsl_mc, CONFIG_SYS_MAXARGS, 1, do_fsl_mc,
2019 "DPAA2 command to manage Management Complex (MC)",
2020 "start mc [FW_addr] [DPC_addr] - Start Management Complex\n"
2021 "fsl_mc apply DPL [DPL_addr] - Apply DPL file\n"
2022 "fsl_mc lazyapply DPL [DPL_addr] - Apply DPL file on exit\n"
2023 "fsl_mc apply spb [spb_addr] - Apply SPB Soft Parser Blob\n"
2024 "fsl_mc start aiop [FW_addr] - Start AIOP\n"
2025 "fsl_mc dump_log - Dump MC Log\n"
2026);
2027
2028void mc_env_boot(void)
2029{
2030#if defined(CONFIG_FSL_MC_ENET)
2031 char *mc_boot_env_var;
2032
2033
2034
2035
2036
2037 mc_boot_env_var = env_get(MC_BOOT_ENV_VAR);
2038 if (mc_boot_env_var)
2039 run_command_list(mc_boot_env_var, -1, 0);
2040#endif
2041}
2042