]> Git Repo - J-u-boot.git/blame - drivers/net/fsl-mc/mc.c
driver: net: fsl-mc: Fix DPC MAC address fixup
[J-u-boot.git] / drivers / net / fsl-mc / mc.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
b940ca64 2/*
a6f2a6ea
YG
3 * Copyright 2014 Freescale Semiconductor, Inc.
4 * Copyright 2017 NXP
87519a9e 5 * Copyright 2017-2018 NXP
b940ca64 6 */
21c69870 7#include <common.h>
b940ca64 8#include <errno.h>
84b8bf6d 9#include <linux/bug.h>
b940ca64 10#include <asm/io.h>
b08c8c48 11#include <linux/libfdt.h>
5707dfb0 12#include <net.h>
21c69870 13#include <fdt_support.h>
7b3bd9a7
GR
14#include <fsl-mc/fsl_mc.h>
15#include <fsl-mc/fsl_mc_sys.h>
a2a55e51 16#include <fsl-mc/fsl_mc_private.h>
7b3bd9a7 17#include <fsl-mc/fsl_dpmng.h>
a2a55e51
PK
18#include <fsl-mc/fsl_dprc.h>
19#include <fsl-mc/fsl_dpio.h>
fb4a87a7 20#include <fsl-mc/fsl_dpni.h>
a2a55e51 21#include <fsl-mc/fsl_qbman_portal.h>
fb4a87a7 22#include <fsl-mc/ldpaa_wriop.h>
b940ca64 23
125e2bc1
GR
24#define MC_RAM_BASE_ADDR_ALIGNMENT (512UL * 1024 * 1024)
25#define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1))
26#define MC_RAM_SIZE_ALIGNMENT (256UL * 1024 * 1024)
27
28#define MC_MEM_SIZE_ENV_VAR "mcmemsize"
29#define MC_BOOT_TIMEOUT_ENV_VAR "mcboottimeout"
33a8991a 30#define MC_BOOT_ENV_VAR "mcinitcmd"
125e2bc1 31
b940ca64 32DECLARE_GLOBAL_DATA_PTR;
87519a9e 33static int mc_memset_resv_ram;
fb4a87a7
PK
34static int mc_boot_status = -1;
35static int mc_dpl_applied = -1;
36#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
37static int mc_aiop_applied = -1;
38#endif
1730a17d
PK
39struct fsl_mc_io *root_mc_io = NULL;
40struct fsl_mc_io *dflt_mc_io = NULL; /* child container */
41uint16_t root_dprc_handle = 0;
a2a55e51 42uint16_t dflt_dprc_handle = 0;
1730a17d 43int child_dprc_id;
a2a55e51
PK
44struct fsl_dpbp_obj *dflt_dpbp = NULL;
45struct fsl_dpio_obj *dflt_dpio = NULL;
1730a17d 46struct fsl_dpni_obj *dflt_dpni = NULL;
b7b8410a 47static u64 mc_lazy_dpl_addr;
125e2bc1
GR
48
49#ifdef DEBUG
50void dump_ram_words(const char *title, void *addr)
51{
52 int i;
53 uint32_t *words = addr;
54
55 printf("Dumping beginning of %s (%p):\n", title, addr);
56 for (i = 0; i < 16; i++)
57 printf("%#x ", words[i]);
58
59 printf("\n");
60}
b940ca64 61
125e2bc1
GR
62void dump_mc_ccsr_regs(struct mc_ccsr_registers __iomem *mc_ccsr_regs)
63{
64 printf("MC CCSR registers:\n"
65 "reg_gcr1 %#x\n"
66 "reg_gsr %#x\n"
67 "reg_sicbalr %#x\n"
68 "reg_sicbahr %#x\n"
69 "reg_sicapr %#x\n"
70 "reg_mcfbalr %#x\n"
71 "reg_mcfbahr %#x\n"
72 "reg_mcfapr %#x\n"
73 "reg_psr %#x\n",
74 mc_ccsr_regs->reg_gcr1,
75 mc_ccsr_regs->reg_gsr,
76 mc_ccsr_regs->reg_sicbalr,
77 mc_ccsr_regs->reg_sicbahr,
78 mc_ccsr_regs->reg_sicapr,
79 mc_ccsr_regs->reg_mcfbalr,
80 mc_ccsr_regs->reg_mcfbahr,
81 mc_ccsr_regs->reg_mcfapr,
82 mc_ccsr_regs->reg_psr);
83}
84#else
85
86#define dump_ram_words(title, addr)
87#define dump_mc_ccsr_regs(mc_ccsr_regs)
88
89#endif /* DEBUG */
90
91#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
b940ca64
GR
92/**
93 * Copying MC firmware or DPL image to DDR
94 */
95static int mc_copy_image(const char *title,
7b3bd9a7 96 u64 image_addr, u32 image_size, u64 mc_ram_addr)
b940ca64
GR
97{
98 debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
99 memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
125e2bc1 100 flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size);
b940ca64
GR
101 return 0;
102}
103
104/**
105 * MC firmware FIT image parser checks if the image is in FIT
106 * format, verifies integrity of the image and calculates
107 * raw image address and size values.
7b3bd9a7 108 * Returns 0 on success and a negative errno on error.
b940ca64
GR
109 * task fail.
110 **/
fb4a87a7
PK
111int parse_mc_firmware_fit_image(u64 mc_fw_addr,
112 const void **raw_image_addr,
b940ca64
GR
113 size_t *raw_image_size)
114{
115 int format;
116 void *fit_hdr;
117 int node_offset;
118 const void *data;
119 size_t size;
120 const char *uname = "firmware";
121
fb4a87a7 122 fit_hdr = (void *)mc_fw_addr;
b940ca64
GR
123
124 /* Check if Image is in FIT format */
125 format = genimg_get_format(fit_hdr);
126
127 if (format != IMAGE_FORMAT_FIT) {
fb4a87a7 128 printf("fsl-mc: ERR: Bad firmware image (not a FIT image)\n");
7b3bd9a7 129 return -EINVAL;
b940ca64
GR
130 }
131
132 if (!fit_check_format(fit_hdr)) {
fb4a87a7 133 printf("fsl-mc: ERR: Bad firmware image (bad FIT header)\n");
7b3bd9a7 134 return -EINVAL;
b940ca64
GR
135 }
136
137 node_offset = fit_image_get_node(fit_hdr, uname);
138
139 if (node_offset < 0) {
fb4a87a7 140 printf("fsl-mc: ERR: Bad firmware image (missing subimage)\n");
7b3bd9a7 141 return -ENOENT;
b940ca64
GR
142 }
143
144 /* Verify MC firmware image */
145 if (!(fit_image_verify(fit_hdr, node_offset))) {
fb4a87a7 146 printf("fsl-mc: ERR: Bad firmware image (bad CRC)\n");
7b3bd9a7 147 return -EINVAL;
b940ca64
GR
148 }
149
150 /* Get address and size of raw image */
151 fit_image_get_data(fit_hdr, node_offset, &data, &size);
152
153 *raw_image_addr = data;
154 *raw_image_size = size;
155
156 return 0;
157}
125e2bc1
GR
158#endif
159
1161dbcc
BP
160#define MC_DT_INCREASE_SIZE 64
161
162enum mc_fixup_type {
163 MC_FIXUP_DPL,
164 MC_FIXUP_DPC
165};
166
167static int mc_fixup_mac_addr(void *blob, int nodeoffset,
168 const char *propname, struct eth_device *eth_dev,
169 enum mc_fixup_type type)
5707dfb0 170{
1161dbcc
BP
171 int err = 0, len = 0, size, i;
172 unsigned char env_enetaddr[ARP_HLEN];
173 unsigned int enetaddr_32[ARP_HLEN];
174 void *val = NULL;
175
176 switch (type) {
177 case MC_FIXUP_DPL:
178 /* DPL likes its addresses on 32 * ARP_HLEN bits */
179 for (i = 0; i < ARP_HLEN; i++)
180 enetaddr_32[i] = cpu_to_fdt32(eth_dev->enetaddr[i]);
181 val = enetaddr_32;
182 len = sizeof(enetaddr_32);
183 break;
184
185 case MC_FIXUP_DPC:
186 val = eth_dev->enetaddr;
187 len = ARP_HLEN;
188 break;
189 }
190
191 /* MAC address property present */
192 if (fdt_get_property(blob, nodeoffset, propname, NULL)) {
193 /* u-boot MAC addr randomly assigned - leave the present one */
35affd7a
SG
194 if (!eth_env_get_enetaddr_by_index("eth", eth_dev->index,
195 env_enetaddr))
1161dbcc
BP
196 return err;
197 } else {
198 size = MC_DT_INCREASE_SIZE + strlen(propname) + len;
199 /* make room for mac address property */
200 err = fdt_increase_size(blob, size);
201 if (err) {
202 printf("fdt_increase_size: err=%s\n",
203 fdt_strerror(err));
204 return err;
205 }
206 }
207
208 err = fdt_setprop(blob, nodeoffset, propname, val, len);
209 if (err) {
210 printf("fdt_setprop: err=%s\n", fdt_strerror(err));
211 return err;
212 }
213
214 return err;
215}
216
217#define is_dpni(s) (s != NULL ? !strncmp(s, "dpni@", 5) : 0)
218
219const char *dpl_get_connection_endpoint(void *blob, char *endpoint)
220{
221 int connoffset = fdt_path_offset(blob, "/connections"), off;
222 const char *s1, *s2;
223
224 for (off = fdt_first_subnode(blob, connoffset);
225 off >= 0;
226 off = fdt_next_subnode(blob, off)) {
227 s1 = fdt_stringlist_get(blob, off, "endpoint1", 0, NULL);
228 s2 = fdt_stringlist_get(blob, off, "endpoint2", 0, NULL);
229
230 if (!s1 || !s2)
231 continue;
232
233 if (strcmp(endpoint, s1) == 0)
234 return s2;
235
236 if (strcmp(endpoint, s2) == 0)
237 return s1;
238 }
239
240 return NULL;
241}
242
243static int mc_fixup_dpl_mac_addr(void *blob, int dpmac_id,
244 struct eth_device *eth_dev)
245{
246 int objoff = fdt_path_offset(blob, "/objects");
247 int dpmacoff = -1, dpnioff = -1;
248 const char *endpoint;
249 char mac_name[10];
250 int err;
251
252 sprintf(mac_name, "dpmac@%d", dpmac_id);
253 dpmacoff = fdt_subnode_offset(blob, objoff, mac_name);
254 if (dpmacoff < 0)
255 /* dpmac not defined in DPL, so skip it. */
256 return 0;
257
258 err = mc_fixup_mac_addr(blob, dpmacoff, "mac_addr", eth_dev,
259 MC_FIXUP_DPL);
260 if (err) {
261 printf("Error fixing up dpmac mac_addr in DPL\n");
262 return err;
263 }
264
265 /* now we need to figure out if there is any
266 * DPNI connected to this MAC, so we walk the
267 * connection list
268 */
269 endpoint = dpl_get_connection_endpoint(blob, mac_name);
270 if (!is_dpni(endpoint))
271 return 0;
272
273 /* let's see if we can fixup the DPNI as well */
274 dpnioff = fdt_subnode_offset(blob, objoff, endpoint);
275 if (dpnioff < 0)
276 /* DPNI not defined in DPL in the objects area */
277 return 0;
278
279 return mc_fixup_mac_addr(blob, dpnioff, "mac_addr", eth_dev,
280 MC_FIXUP_DPL);
281}
282
a78df40c
NG
283void fdt_fsl_mc_fixup_iommu_map_entry(void *blob)
284{
285 u32 *prop;
286 u32 iommu_map[4];
287 int offset;
288 int lenp;
289
290 /* find fsl-mc node */
291 offset = fdt_path_offset(blob, "/soc/fsl-mc");
292 if (offset < 0)
293 offset = fdt_path_offset(blob, "/fsl-mc");
294 if (offset < 0) {
295 printf("%s: fsl-mc: ERR: fsl-mc node not found in DT, err %d\n",
296 __func__, offset);
297 return;
298 }
299
300 prop = fdt_getprop_w(blob, offset, "iommu-map", &lenp);
301 if (!prop) {
302 debug("%s: fsl-mc: ERR: missing iommu-map in fsl-mc bus node\n",
303 __func__);
304 return;
305 }
306
307 iommu_map[0] = cpu_to_fdt32(FSL_DPAA2_STREAM_ID_START);
308 iommu_map[1] = *++prop;
309 iommu_map[2] = cpu_to_fdt32(FSL_DPAA2_STREAM_ID_START);
310 iommu_map[3] = cpu_to_fdt32(FSL_DPAA2_STREAM_ID_END -
311 FSL_DPAA2_STREAM_ID_START + 1);
312
313 fdt_setprop_inplace(blob, offset, "iommu-map",
314 iommu_map, sizeof(iommu_map));
315}
316
1161dbcc
BP
317static int mc_fixup_dpc_mac_addr(void *blob, int dpmac_id,
318 struct eth_device *eth_dev)
319{
320 int nodeoffset = fdt_path_offset(blob, "/board_info/ports"), noff;
321 int err = 0;
5707dfb0 322 char mac_name[10];
1161dbcc 323 const char link_type_mode[] = "MAC_LINK_TYPE_FIXED";
5707dfb0
BP
324
325 sprintf(mac_name, "mac@%d", dpmac_id);
326
327 /* node not found - create it */
1161dbcc
BP
328 noff = fdt_subnode_offset(blob, nodeoffset, (const char *)mac_name);
329 if (noff < 0) {
5707dfb0
BP
330 err = fdt_increase_size(blob, 200);
331 if (err) {
332 printf("fdt_increase_size: err=%s\n",
333 fdt_strerror(err));
334 return err;
335 }
336
1161dbcc
BP
337 noff = fdt_add_subnode(blob, nodeoffset, mac_name);
338 if (noff < 0) {
339 printf("fdt_add_subnode: err=%s\n",
340 fdt_strerror(err));
341 return err;
342 }
5707dfb0
BP
343
344 /* add default property of fixed link */
1161dbcc 345 err = fdt_appendprop_string(blob, noff,
5707dfb0
BP
346 "link_type", link_type_mode);
347 if (err) {
348 printf("fdt_appendprop_string: err=%s\n",
349 fdt_strerror(err));
350 return err;
351 }
352 }
353
1161dbcc
BP
354 return mc_fixup_mac_addr(blob, noff, "port_mac_address", eth_dev,
355 MC_FIXUP_DPC);
356}
5707dfb0 357
1161dbcc
BP
358static int mc_fixup_mac_addrs(void *blob, enum mc_fixup_type type)
359{
360 int i, err = 0, ret = 0;
c022ec03 361 char ethname[ETH_NAME_LEN];
1161dbcc 362 struct eth_device *eth_dev;
5707dfb0 363
1161dbcc
BP
364 for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
365 /* port not enabled */
1ed19a14 366 if (wriop_is_enabled_dpmac(i) != 1)
1161dbcc 367 continue;
5707dfb0 368
c022ec03
PB
369 snprintf(ethname, ETH_NAME_LEN, "DPMAC%d@%s", i,
370 phy_interface_strings[wriop_get_enet_if(i)]);
5707dfb0 371
1161dbcc
BP
372 eth_dev = eth_get_dev_by_name(ethname);
373 if (eth_dev == NULL)
374 continue;
375
376 switch (type) {
377 case MC_FIXUP_DPL:
378 err = mc_fixup_dpl_mac_addr(blob, i, eth_dev);
379 break;
380 case MC_FIXUP_DPC:
381 err = mc_fixup_dpc_mac_addr(blob, i, eth_dev);
382 break;
383 default:
384 break;
385 }
386
387 if (err)
388 printf("fsl-mc: ERROR fixing mac address for %s\n",
389 ethname);
390 ret |= err;
5707dfb0
BP
391 }
392
1161dbcc 393 return ret;
5707dfb0
BP
394}
395
21c69870
SY
396static int mc_fixup_dpc(u64 dpc_addr)
397{
398 void *blob = (void *)dpc_addr;
5707dfb0 399 int nodeoffset, err = 0;
21c69870
SY
400
401 /* delete any existing ICID pools */
402 nodeoffset = fdt_path_offset(blob, "/resources/icid_pools");
403 if (fdt_del_node(blob, nodeoffset) < 0)
404 printf("\nfsl-mc: WARNING: could not delete ICID pool\n");
405
406 /* add a new pool */
407 nodeoffset = fdt_path_offset(blob, "/resources");
408 if (nodeoffset < 0) {
409 printf("\nfsl-mc: ERROR: DPC is missing /resources\n");
410 return -EINVAL;
411 }
412 nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pools");
413 nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pool@0");
414 do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
415 "base_icid", FSL_DPAA2_STREAM_ID_START, 1);
416 do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0",
417 "num",
418 FSL_DPAA2_STREAM_ID_END -
419 FSL_DPAA2_STREAM_ID_START + 1, 1);
420
5707dfb0
BP
421 /* fixup MAC addresses for dpmac ports */
422 nodeoffset = fdt_path_offset(blob, "/board_info/ports");
423 if (nodeoffset < 0)
2e9f1bf5 424 goto out;
5707dfb0 425
1161dbcc 426 err = mc_fixup_mac_addrs(blob, MC_FIXUP_DPC);
2e9f1bf5
ICR
427
428out:
21c69870
SY
429 flush_dcache_range(dpc_addr, dpc_addr + fdt_totalsize(blob));
430
5707dfb0 431 return err;
21c69870
SY
432}
433
fb4a87a7 434static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpc_addr)
125e2bc1
GR
435{
436 u64 mc_dpc_offset;
437#ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
438 int error;
439 void *dpc_fdt_hdr;
440 int dpc_size;
441#endif
442
443#ifdef CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET
444 BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET & 0x3) != 0 ||
445 CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET > 0xffffffff);
446
447 mc_dpc_offset = CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET;
448#else
449#error "CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET not defined"
450#endif
451
452 /*
453 * Load the MC DPC blob in the MC private DRAM block:
454 */
455#ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
456 printf("MC DPC is preloaded to %#llx\n", mc_ram_addr + mc_dpc_offset);
457#else
458 /*
459 * Get address and size of the DPC blob stored in flash:
460 */
fb4a87a7 461 dpc_fdt_hdr = (void *)mc_dpc_addr;
125e2bc1
GR
462
463 error = fdt_check_header(dpc_fdt_hdr);
464 if (error != 0) {
465 /*
466 * Don't return with error here, since the MC firmware can
467 * still boot without a DPC
468 */
cc088c3a 469 printf("\nfsl-mc: WARNING: No DPC image found");
125e2bc1
GR
470 return 0;
471 }
472
473 dpc_size = fdt_totalsize(dpc_fdt_hdr);
474 if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) {
cc088c3a 475 printf("\nfsl-mc: ERROR: Bad DPC image (too large: %d)\n",
125e2bc1
GR
476 dpc_size);
477 return -EINVAL;
478 }
479
480 mc_copy_image("MC DPC blob",
481 (u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset);
482#endif /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */
483
21c69870
SY
484 if (mc_fixup_dpc(mc_ram_addr + mc_dpc_offset))
485 return -EINVAL;
486
125e2bc1
GR
487 dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset));
488 return 0;
489}
490
1161dbcc
BP
491
492static int mc_fixup_dpl(u64 dpl_addr)
493{
494 void *blob = (void *)dpl_addr;
495 u32 ver = fdt_getprop_u32_default(blob, "/", "dpl-version", 0);
496 int err = 0;
497
498 /* The DPL fixup for mac addresses is only relevant
499 * for old-style DPLs
500 */
501 if (ver >= 10)
502 return 0;
503
504 err = mc_fixup_mac_addrs(blob, MC_FIXUP_DPL);
505 flush_dcache_range(dpl_addr, dpl_addr + fdt_totalsize(blob));
506
507 return err;
508}
509
fb4a87a7 510static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpl_addr)
125e2bc1
GR
511{
512 u64 mc_dpl_offset;
513#ifndef CONFIG_SYS_LS_MC_DPL_IN_DDR
514 int error;
515 void *dpl_fdt_hdr;
516 int dpl_size;
517#endif
518
519#ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
520 BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
521 CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
522
523 mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
524#else
525#error "CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET not defined"
526#endif
527
528 /*
529 * Load the MC DPL blob in the MC private DRAM block:
530 */
531#ifdef CONFIG_SYS_LS_MC_DPL_IN_DDR
532 printf("MC DPL is preloaded to %#llx\n", mc_ram_addr + mc_dpl_offset);
533#else
534 /*
535 * Get address and size of the DPL blob stored in flash:
536 */
fb4a87a7 537 dpl_fdt_hdr = (void *)mc_dpl_addr;
125e2bc1
GR
538
539 error = fdt_check_header(dpl_fdt_hdr);
540 if (error != 0) {
cc088c3a 541 printf("\nfsl-mc: ERROR: Bad DPL image (bad header)\n");
125e2bc1
GR
542 return error;
543 }
544
545 dpl_size = fdt_totalsize(dpl_fdt_hdr);
546 if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
cc088c3a 547 printf("\nfsl-mc: ERROR: Bad DPL image (too large: %d)\n",
125e2bc1
GR
548 dpl_size);
549 return -EINVAL;
550 }
551
552 mc_copy_image("MC DPL blob",
553 (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
554#endif /* not defined CONFIG_SYS_LS_MC_DPL_IN_DDR */
555
1161dbcc
BP
556 if (mc_fixup_dpl(mc_ram_addr + mc_dpl_offset))
557 return -EINVAL;
125e2bc1
GR
558 dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset));
559 return 0;
560}
561
562/**
563 * Return the MC boot timeout value in milliseconds
564 */
565static unsigned long get_mc_boot_timeout_ms(void)
566{
567 unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
568
00caae6d 569 char *timeout_ms_env_var = env_get(MC_BOOT_TIMEOUT_ENV_VAR);
125e2bc1
GR
570
571 if (timeout_ms_env_var) {
572 timeout_ms = simple_strtoul(timeout_ms_env_var, NULL, 10);
573 if (timeout_ms == 0) {
574 printf("fsl-mc: WARNING: Invalid value for \'"
575 MC_BOOT_TIMEOUT_ENV_VAR
576 "\' environment variable: %lu\n",
577 timeout_ms);
578
579 timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
580 }
581 }
582
583 return timeout_ms;
584}
585
fb4a87a7 586#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
3c1d218a
YS
587
588__weak bool soc_has_aiop(void)
589{
590 return false;
591}
592
fb4a87a7 593static int load_mc_aiop_img(u64 aiop_fw_addr)
c1000c12 594{
fb4a87a7
PK
595 u64 mc_ram_addr = mc_get_dram_addr();
596#ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
c1000c12 597 void *aiop_img;
fb4a87a7 598#endif
c1000c12 599
3c1d218a
YS
600 /* Check if AIOP is available */
601 if (!soc_has_aiop())
602 return -ENODEV;
c1000c12
GR
603 /*
604 * Load the MC AIOP image in the MC private DRAM block:
605 */
606
fb4a87a7
PK
607#ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
608 printf("MC AIOP is preloaded to %#llx\n", mc_ram_addr +
609 CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
610#else
611 aiop_img = (void *)aiop_fw_addr;
c1000c12
GR
612 mc_copy_image("MC AIOP image",
613 (u64)aiop_img, CONFIG_SYS_LS_MC_AIOP_IMG_MAX_LENGTH,
614 mc_ram_addr + CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET);
fb4a87a7
PK
615#endif
616 mc_aiop_applied = 0;
c1000c12
GR
617
618 return 0;
619}
620#endif
fb4a87a7 621
125e2bc1
GR
622static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr)
623{
624 u32 reg_gsr;
625 u32 mc_fw_boot_status;
626 unsigned long timeout_ms = get_mc_boot_timeout_ms();
627 struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
628
629 dmb();
125e2bc1
GR
630 assert(timeout_ms > 0);
631 for (;;) {
632 udelay(1000); /* throttle polling */
633 reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
634 mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
635 if (mc_fw_boot_status & 0x1)
636 break;
637
638 timeout_ms--;
639 if (timeout_ms == 0)
640 break;
641 }
642
643 if (timeout_ms == 0) {
cc088c3a 644 printf("ERROR: timeout\n");
125e2bc1
GR
645
646 /* TODO: Get an error status from an MC CCSR register */
647 return -ETIMEDOUT;
648 }
649
650 if (mc_fw_boot_status != 0x1) {
651 /*
652 * TODO: Identify critical errors from the GSR register's FS
653 * field and for those errors, set error to -ENODEV or other
654 * appropriate errno, so that the status property is set to
655 * failure in the fsl,dprc device tree node.
656 */
cc088c3a
GR
657 printf("WARNING: Firmware returned an error (GSR: %#x)\n",
658 reg_gsr);
659 } else {
660 printf("SUCCESS\n");
125e2bc1
GR
661 }
662
cc088c3a 663
125e2bc1
GR
664 *final_reg_gsr = reg_gsr;
665 return 0;
666}
b940ca64 667
fb4a87a7 668int mc_init(u64 mc_fw_addr, u64 mc_dpc_addr)
b940ca64
GR
669{
670 int error = 0;
a2a55e51 671 int portal_id = 0;
b940ca64 672 struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
fb4a87a7 673 u64 mc_ram_addr = mc_get_dram_addr();
b940ca64 674 u32 reg_gsr;
125e2bc1
GR
675 u32 reg_mcfbalr;
676#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
b940ca64
GR
677 const void *raw_image_addr;
678 size_t raw_image_size = 0;
125e2bc1 679#endif
7b3bd9a7 680 struct mc_version mc_ver_info;
125e2bc1
GR
681 u8 mc_ram_num_256mb_blocks;
682 size_t mc_ram_size = mc_get_dram_block_size();
b940ca64 683
437858b6
YS
684 mc_ram_num_256mb_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT;
685 if (mc_ram_num_256mb_blocks < 1 || mc_ram_num_256mb_blocks > 0xff) {
686 error = -EINVAL;
687 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
688 mc_ram_size);
125e2bc1 689 goto out;
437858b6 690 }
125e2bc1 691
b940ca64
GR
692 /*
693 * Management Complex cores should be held at reset out of POR.
a187559e 694 * U-Boot should be the first software to touch MC. To be safe,
b940ca64
GR
695 * we reset all cores again by setting GCR1 to 0. It doesn't do
696 * anything if they are held at reset. After we setup the firmware
697 * we kick off MC by deasserting the reset bit for core 0, and
698 * deasserting the reset bits for Command Portal Managers.
699 * The stop bits are not touched here. They are used to stop the
700 * cores when they are active. Setting stop bits doesn't stop the
701 * cores from fetching instructions when they are released from
702 * reset.
703 */
704 out_le32(&mc_ccsr_regs->reg_gcr1, 0);
705 dmb();
706
125e2bc1
GR
707#ifdef CONFIG_SYS_LS_MC_FW_IN_DDR
708 printf("MC firmware is preloaded to %#llx\n", mc_ram_addr);
709#else
fb4a87a7
PK
710 error = parse_mc_firmware_fit_image(mc_fw_addr, &raw_image_addr,
711 &raw_image_size);
b940ca64
GR
712 if (error != 0)
713 goto out;
714 /*
715 * Load the MC FW at the beginning of the MC private DRAM block:
716 */
7b3bd9a7
GR
717 mc_copy_image("MC Firmware",
718 (u64)raw_image_addr, raw_image_size, mc_ram_addr);
7b3bd9a7 719#endif
125e2bc1 720 dump_ram_words("firmware", (void *)mc_ram_addr);
7b3bd9a7 721
fb4a87a7 722 error = load_mc_dpc(mc_ram_addr, mc_ram_size, mc_dpc_addr);
125e2bc1 723 if (error != 0)
b940ca64 724 goto out;
b940ca64
GR
725
726 debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
125e2bc1 727 dump_mc_ccsr_regs(mc_ccsr_regs);
b940ca64
GR
728
729 /*
125e2bc1 730 * Tell MC what is the address range of the DRAM block assigned to it:
b940ca64 731 */
437858b6 732 reg_mcfbalr = (u32)mc_ram_addr |
125e2bc1
GR
733 (mc_ram_num_256mb_blocks - 1);
734 out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr);
735 out_le32(&mc_ccsr_regs->reg_mcfbahr,
437858b6 736 (u32)(mc_ram_addr >> 32));
39da644e 737 out_le32(&mc_ccsr_regs->reg_mcfapr, FSL_BYPASS_AMQ);
b940ca64
GR
738
739 /*
125e2bc1 740 * Tell the MC that we want delayed DPL deployment.
b940ca64 741 */
125e2bc1 742 out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00);
b940ca64 743
cc088c3a 744 printf("\nfsl-mc: Booting Management Complex ... ");
7b3bd9a7 745
b940ca64
GR
746 /*
747 * Deassert reset and release MC core 0 to run
748 */
749 out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
125e2bc1
GR
750 error = wait_for_mc(true, &reg_gsr);
751 if (error != 0)
b940ca64 752 goto out;
b940ca64 753
7b3bd9a7
GR
754 /*
755 * TODO: need to obtain the portal_id for the root container from the
756 * DPL
757 */
758 portal_id = 0;
759
760 /*
a2a55e51
PK
761 * Initialize the global default MC portal
762 * And check that the MC firmware is responding portal commands:
7b3bd9a7 763 */
a572fb6b 764 root_mc_io = (struct fsl_mc_io *)calloc(sizeof(struct fsl_mc_io), 1);
1730a17d 765 if (!root_mc_io) {
a572fb6b 766 printf(" No memory: calloc() failed\n");
a2a55e51
PK
767 return -ENOMEM;
768 }
769
1730a17d 770 root_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
7b3bd9a7 771 debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
1730a17d 772 portal_id, root_mc_io->mmio_regs);
7b3bd9a7 773
1730a17d 774 error = mc_get_version(root_mc_io, MC_CMD_NO_FLAGS, &mc_ver_info);
7b3bd9a7
GR
775 if (error != 0) {
776 printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n",
777 error);
778 goto out;
779 }
780
7b3bd9a7
GR
781 printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n",
782 mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision,
125e2bc1
GR
783 reg_gsr & GSR_FS_MASK);
784
fb4a87a7
PK
785out:
786 if (error != 0)
787 mc_boot_status = error;
788 else
789 mc_boot_status = 0;
790
791 return error;
792}
793
794int mc_apply_dpl(u64 mc_dpl_addr)
795{
796 struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
797 int error = 0;
798 u32 reg_gsr;
799 u64 mc_ram_addr = mc_get_dram_addr();
800 size_t mc_ram_size = mc_get_dram_block_size();
801
b7b8410a
AG
802 if (!mc_dpl_addr)
803 return -1;
804
fb4a87a7
PK
805 error = load_mc_dpl(mc_ram_addr, mc_ram_size, mc_dpl_addr);
806 if (error != 0)
807 return error;
808
125e2bc1
GR
809 /*
810 * Tell the MC to deploy the DPL:
811 */
812 out_le32(&mc_ccsr_regs->reg_gsr, 0x0);
cc088c3a 813 printf("fsl-mc: Deploying data path layout ... ");
125e2bc1 814 error = wait_for_mc(false, &reg_gsr);
cc088c3a 815
fb4a87a7
PK
816 if (!error)
817 mc_dpl_applied = 0;
b940ca64
GR
818
819 return error;
820}
821
822int get_mc_boot_status(void)
823{
824 return mc_boot_status;
825}
826
fb4a87a7
PK
827#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
828int get_aiop_apply_status(void)
829{
830 return mc_aiop_applied;
831}
832#endif
833
834int get_dpl_apply_status(void)
835{
836 return mc_dpl_applied;
837}
838
7e968049
MYK
839int is_lazy_dpl_addr_valid(void)
840{
841 return !!mc_lazy_dpl_addr;
842}
843
033c538e 844/*
fb4a87a7 845 * Return the MC address of private DRAM block.
033c538e
PJ
846 * As per MC design document, MC initial base address
847 * should be least significant 512MB address of MC private
848 * memory, i.e. address should point to end address masked
849 * with 512MB offset in private DRAM block.
fb4a87a7
PK
850 */
851u64 mc_get_dram_addr(void)
852{
033c538e
PJ
853 size_t mc_ram_size = mc_get_dram_block_size();
854
87519a9e
PK
855 if (!mc_memset_resv_ram || (get_mc_boot_status() < 0)) {
856 mc_memset_resv_ram = 1;
857 memset((void *)gd->arch.resv_ram, 0, mc_ram_size);
858 }
859
033c538e
PJ
860 return (gd->arch.resv_ram + mc_ram_size - 1) &
861 MC_RAM_BASE_ADDR_ALIGNMENT_MASK;
fb4a87a7
PK
862}
863
b940ca64
GR
864/**
865 * Return the actual size of the MC private DRAM block.
b940ca64
GR
866 */
867unsigned long mc_get_dram_block_size(void)
868{
125e2bc1
GR
869 unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
870
00caae6d 871 char *dram_block_size_env_var = env_get(MC_MEM_SIZE_ENV_VAR);
125e2bc1
GR
872
873 if (dram_block_size_env_var) {
874 dram_block_size = simple_strtoul(dram_block_size_env_var, NULL,
f53e12d8 875 16);
125e2bc1
GR
876
877 if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
878 printf("fsl-mc: WARNING: Invalid value for \'"
879 MC_MEM_SIZE_ENV_VAR
880 "\' environment variable: %lu\n",
881 dram_block_size);
882
883 dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
884 }
885 }
886
887 return dram_block_size;
b940ca64 888}
a2a55e51 889
1730a17d
PK
890int fsl_mc_ldpaa_init(bd_t *bis)
891{
c919ab9e
PK
892 int i;
893
894 for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++)
1ed19a14 895 if (wriop_is_enabled_dpmac(i) == 1)
c919ab9e 896 ldpaa_eth_init(i, wriop_get_enet_if(i));
1730a17d
PK
897 return 0;
898}
899
9a696f56
PK
900static int dprc_version_check(struct fsl_mc_io *mc_io, uint16_t handle)
901{
9a696f56 902 int error;
2557c5a9 903 uint16_t major_ver, minor_ver;
9a696f56 904
2557c5a9
YG
905 error = dprc_get_api_version(mc_io, 0,
906 &major_ver,
907 &minor_ver);
908 if (error < 0) {
909 printf("dprc_get_api_version() failed: %d\n", error);
910 return error;
911 }
912
913 if (major_ver < DPRC_VER_MAJOR || (major_ver == DPRC_VER_MAJOR &&
914 minor_ver < DPRC_VER_MINOR)) {
915 printf("DPRC version mismatch found %u.%u,",
916 major_ver, minor_ver);
917 printf("supported version is %u.%u\n",
918 DPRC_VER_MAJOR, DPRC_VER_MINOR);
9a696f56 919 }
2557c5a9 920
9a696f56
PK
921 return error;
922}
923
1730a17d 924static int dpio_init(void)
a2a55e51
PK
925{
926 struct qbman_swp_desc p_des;
927 struct dpio_attr attr;
1730a17d 928 struct dpio_cfg dpio_cfg;
a2a55e51 929 int err = 0;
2557c5a9 930 uint16_t major_ver, minor_ver;
a2a55e51 931
a572fb6b
PK
932 dflt_dpio = (struct fsl_dpio_obj *)calloc(
933 sizeof(struct fsl_dpio_obj), 1);
a2a55e51 934 if (!dflt_dpio) {
a572fb6b 935 printf("No memory: calloc() failed\n");
1730a17d 936 err = -ENOMEM;
a572fb6b 937 goto err_calloc;
a2a55e51 938 }
1730a17d
PK
939 dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL;
940 dpio_cfg.num_priorities = 8;
a2a55e51 941
2557c5a9
YG
942 err = dpio_create(dflt_mc_io,
943 dflt_dprc_handle,
944 MC_CMD_NO_FLAGS,
945 &dpio_cfg,
946 &dflt_dpio->dpio_id);
1730a17d
PK
947 if (err < 0) {
948 printf("dpio_create() failed: %d\n", err);
949 err = -ENODEV;
950 goto err_create;
a2a55e51
PK
951 }
952
2557c5a9
YG
953 err = dpio_get_api_version(dflt_mc_io, 0,
954 &major_ver,
955 &minor_ver);
956 if (err < 0) {
957 printf("dpio_get_api_version() failed: %d\n", err);
958 goto err_get_api_ver;
959 }
960
961 if (major_ver < DPIO_VER_MAJOR || (major_ver == DPIO_VER_MAJOR &&
962 minor_ver < DPIO_VER_MINOR)) {
963 printf("DPRC version mismatch found %u.%u,",
964 major_ver,
965 minor_ver);
966 }
967
968 err = dpio_open(dflt_mc_io,
969 MC_CMD_NO_FLAGS,
970 dflt_dpio->dpio_id,
971 &dflt_dpio->dpio_handle);
972 if (err) {
973 printf("dpio_open() failed\n");
974 goto err_open;
975 }
976
1730a17d 977 memset(&attr, 0, sizeof(struct dpio_attr));
87457d11 978 err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1730a17d
PK
979 dflt_dpio->dpio_handle, &attr);
980 if (err < 0) {
981 printf("dpio_get_attributes() failed: %d\n", err);
a2a55e51
PK
982 goto err_get_attr;
983 }
984
2557c5a9
YG
985 if (dflt_dpio->dpio_id != attr.id) {
986 printf("dnpi object id and attribute id are not same\n");
987 goto err_attr_not_same;
9a696f56
PK
988 }
989
1730a17d
PK
990#ifdef DEBUG
991 printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id);
992#endif
1730a17d
PK
993 err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
994 if (err < 0) {
a2a55e51
PK
995 printf("dpio_enable() failed %d\n", err);
996 goto err_get_enable;
997 }
1f1c25c7
PK
998 debug("ce_offset=0x%llx, ci_offset=0x%llx, portalid=%d, prios=%d\n",
999 attr.qbman_portal_ce_offset,
1000 attr.qbman_portal_ci_offset,
a2a55e51
PK
1001 attr.qbman_portal_id,
1002 attr.num_priorities);
1003
1f1c25c7
PK
1004 p_des.cena_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
1005 + attr.qbman_portal_ce_offset);
1006 p_des.cinh_bar = (void *)(SOC_QBMAN_PORTALS_BASE_ADDR
1007 + attr.qbman_portal_ci_offset);
a2a55e51
PK
1008
1009 dflt_dpio->sw_portal = qbman_swp_init(&p_des);
1010 if (dflt_dpio->sw_portal == NULL) {
1011 printf("qbman_swp_init() failed\n");
1012 goto err_get_swp_init;
1013 }
1014 return 0;
1015
1016err_get_swp_init:
1730a17d 1017 dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
a2a55e51 1018err_get_enable:
1730a17d 1019err_get_attr:
2557c5a9 1020err_attr_not_same:
1730a17d 1021 dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
2557c5a9
YG
1022err_open:
1023err_get_api_ver:
1024 dpio_destroy(dflt_mc_io,
1025 dflt_dprc_handle,
1026 MC_CMD_NO_FLAGS,
1027 dflt_dpio->dpio_id);
1730a17d 1028err_create:
cd7b3fbc 1029 free(dflt_dpio);
a572fb6b 1030err_calloc:
1730a17d
PK
1031 return err;
1032}
1033
1034static int dpio_exit(void)
1035{
1036 int err;
1037
1038 err = dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1039 if (err < 0) {
1040 printf("dpio_disable() failed: %d\n", err);
1041 goto err;
1042 }
1043
2557c5a9
YG
1044 dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1045 if (err < 0) {
1046 printf("dpio_close() failed: %d\n", err);
1047 goto err;
1048 }
1049
1050 err = dpio_destroy(dflt_mc_io,
1051 dflt_dprc_handle,
1052 MC_CMD_NO_FLAGS,
1053 dflt_dpio->dpio_id);
1730a17d
PK
1054 if (err < 0) {
1055 printf("dpio_destroy() failed: %d\n", err);
1056 goto err;
1057 }
1058
1059#ifdef DEBUG
1060 printf("Exit: DPIO id=0x%d\n", dflt_dpio->dpio_id);
1061#endif
1062
1063 if (dflt_dpio)
1064 free(dflt_dpio);
1065
1066 return 0;
1067err:
1068 return err;
1069}
1070
1071static int dprc_init(void)
1072{
1073 int err, child_portal_id, container_id;
1074 struct dprc_cfg cfg;
1075 uint64_t mc_portal_offset;
1076
1077 /* Open root container */
1078 err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id);
1079 if (err < 0) {
1080 printf("dprc_get_container_id(): Root failed: %d\n", err);
1081 goto err_root_container_id;
1082 }
1083
1084#ifdef DEBUG
1085 printf("Root container id = %d\n", container_id);
1086#endif
1087 err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id,
1088 &root_dprc_handle);
1089 if (err < 0) {
1090 printf("dprc_open(): Root Container failed: %d\n", err);
1091 goto err_root_open;
1092 }
1093
1094 if (!root_dprc_handle) {
1095 printf("dprc_open(): Root Container Handle is not valid\n");
1096 goto err_root_open;
1097 }
1098
9a696f56
PK
1099 err = dprc_version_check(root_mc_io, root_dprc_handle);
1100 if (err < 0) {
1101 printf("dprc_version_check() failed: %d\n", err);
1102 goto err_root_open;
1103 }
1104
5373b204 1105 memset(&cfg, 0, sizeof(struct dprc_cfg));
1730a17d
PK
1106 cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED |
1107 DPRC_CFG_OPT_OBJ_CREATE_ALLOWED |
1108 DPRC_CFG_OPT_ALLOC_ALLOWED;
1109 cfg.icid = DPRC_GET_ICID_FROM_POOL;
335b1936 1110 cfg.portal_id = DPRC_GET_PORTAL_ID_FROM_POOL;
1730a17d
PK
1111 err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS,
1112 root_dprc_handle,
1113 &cfg,
1114 &child_dprc_id,
1115 &mc_portal_offset);
1116 if (err < 0) {
1117 printf("dprc_create_container() failed: %d\n", err);
1118 goto err_create;
1119 }
1120
a572fb6b 1121 dflt_mc_io = (struct fsl_mc_io *)calloc(sizeof(struct fsl_mc_io), 1);
1730a17d
PK
1122 if (!dflt_mc_io) {
1123 err = -ENOMEM;
a572fb6b
PK
1124 printf(" No memory: calloc() failed\n");
1125 goto err_calloc;
1730a17d
PK
1126 }
1127
1128 child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset);
1129 dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id);
2557c5a9 1130
1730a17d
PK
1131#ifdef DEBUG
1132 printf("MC portal of child DPRC container: %d, physical addr %p)\n",
1133 child_dprc_id, dflt_mc_io->mmio_regs);
1134#endif
1135
1136 err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id,
1137 &dflt_dprc_handle);
1138 if (err < 0) {
1139 printf("dprc_open(): Child container failed: %d\n", err);
1140 goto err_child_open;
1141 }
1142
1143 if (!dflt_dprc_handle) {
1144 printf("dprc_open(): Child container Handle is not valid\n");
1145 goto err_child_open;
1146 }
1147
1148 return 0;
1149err_child_open:
1150 free(dflt_mc_io);
a572fb6b 1151err_calloc:
1730a17d
PK
1152 dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
1153 root_dprc_handle, child_dprc_id);
1154err_create:
1155 dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
1156err_root_open:
1157err_root_container_id:
1158 return err;
1159}
1160
1161static int dprc_exit(void)
1162{
1163 int err;
1164
1165 err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle);
1166 if (err < 0) {
1167 printf("dprc_close(): Child failed: %d\n", err);
1168 goto err;
1169 }
1170
1171 err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS,
1172 root_dprc_handle, child_dprc_id);
1173 if (err < 0) {
1174 printf("dprc_destroy_container() failed: %d\n", err);
1175 goto err;
1176 }
1177
1178 err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle);
1179 if (err < 0) {
1180 printf("dprc_close(): Root failed: %d\n", err);
1181 goto err;
1182 }
1183
1184 if (dflt_mc_io)
1185 free(dflt_mc_io);
1186
1187 if (root_mc_io)
1188 free(root_mc_io);
1189
1190 return 0;
1191
1192err:
a2a55e51
PK
1193 return err;
1194}
1195
1730a17d 1196static int dpbp_init(void)
a2a55e51 1197{
1730a17d
PK
1198 int err;
1199 struct dpbp_attr dpbp_attr;
1200 struct dpbp_cfg dpbp_cfg;
2557c5a9 1201 uint16_t major_ver, minor_ver;
1730a17d 1202
a572fb6b
PK
1203 dflt_dpbp = (struct fsl_dpbp_obj *)calloc(
1204 sizeof(struct fsl_dpbp_obj), 1);
a2a55e51 1205 if (!dflt_dpbp) {
a572fb6b 1206 printf("No memory: calloc() failed\n");
1730a17d 1207 err = -ENOMEM;
a572fb6b 1208 goto err_calloc;
1730a17d
PK
1209 }
1210
1211 dpbp_cfg.options = 512;
1212
2557c5a9
YG
1213 err = dpbp_create(dflt_mc_io,
1214 dflt_dprc_handle,
1215 MC_CMD_NO_FLAGS,
1216 &dpbp_cfg,
1217 &dflt_dpbp->dpbp_id);
1730a17d
PK
1218
1219 if (err < 0) {
1220 err = -ENODEV;
1221 printf("dpbp_create() failed: %d\n", err);
1222 goto err_create;
1223 }
1224
2557c5a9
YG
1225 err = dpbp_get_api_version(dflt_mc_io, 0,
1226 &major_ver,
1227 &minor_ver);
1228 if (err < 0) {
1229 printf("dpbp_get_api_version() failed: %d\n", err);
1230 goto err_get_api_ver;
1231 }
1232
1233 if (major_ver < DPBP_VER_MAJOR || (major_ver == DPBP_VER_MAJOR &&
1234 minor_ver < DPBP_VER_MINOR)) {
1235 printf("DPBP version mismatch found %u.%u,",
1236 major_ver, minor_ver);
1237 printf("supported version is %u.%u\n",
1238 DPBP_VER_MAJOR, DPBP_VER_MINOR);
1239 }
1240
1241 err = dpbp_open(dflt_mc_io,
1242 MC_CMD_NO_FLAGS,
1243 dflt_dpbp->dpbp_id,
1244 &dflt_dpbp->dpbp_handle);
1245 if (err) {
1246 printf("dpbp_open() failed\n");
1247 goto err_open;
1248 }
1249
1730a17d
PK
1250 memset(&dpbp_attr, 0, sizeof(struct dpbp_attr));
1251 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
1252 dflt_dpbp->dpbp_handle,
1253 &dpbp_attr);
1254 if (err < 0) {
1255 printf("dpbp_get_attributes() failed: %d\n", err);
1256 goto err_get_attr;
1257 }
1258
2557c5a9
YG
1259 if (dflt_dpbp->dpbp_id != dpbp_attr.id) {
1260 printf("dpbp object id and attribute id are not same\n");
1261 goto err_attr_not_same;
9a696f56
PK
1262 }
1263
1730a17d 1264#ifdef DEBUG
2557c5a9 1265 printf("Init: DPBP id=0x%x\n", dflt_dpbp->dpbp_attr.id);
1730a17d
PK
1266#endif
1267
1268 err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
1269 if (err < 0) {
1270 printf("dpbp_close() failed: %d\n", err);
1271 goto err_close;
a2a55e51 1272 }
a2a55e51
PK
1273
1274 return 0;
1730a17d 1275
1730a17d 1276err_get_attr:
2557c5a9 1277err_attr_not_same:
1730a17d 1278 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
2557c5a9
YG
1279 dpbp_destroy(dflt_mc_io,
1280 dflt_dprc_handle,
1281 MC_CMD_NO_FLAGS,
1282 dflt_dpbp->dpbp_id);
1283err_get_api_ver:
1284err_close:
1285err_open:
1730a17d 1286err_create:
2557c5a9 1287 free(dflt_dpbp);
a572fb6b 1288err_calloc:
1730a17d 1289 return err;
a2a55e51
PK
1290}
1291
1730a17d
PK
1292static int dpbp_exit(void)
1293{
1294 int err;
1295
2557c5a9
YG
1296 err = dpbp_destroy(dflt_mc_io, dflt_dprc_handle, MC_CMD_NO_FLAGS,
1297 dflt_dpbp->dpbp_id);
1730a17d
PK
1298 if (err < 0) {
1299 printf("dpbp_destroy() failed: %d\n", err);
1300 goto err;
1301 }
1302
1303#ifdef DEBUG
1304 printf("Exit: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id);
1305#endif
1306
1307 if (dflt_dpbp)
1308 free(dflt_dpbp);
1309 return 0;
1310
1311err:
1312 return err;
1313}
1314
1315static int dpni_init(void)
1316{
1317 int err;
2557c5a9 1318 uint8_t cfg_buf[256] = {0};
1730a17d 1319 struct dpni_cfg dpni_cfg;
2557c5a9 1320 uint16_t major_ver, minor_ver;
1730a17d 1321
a572fb6b
PK
1322 dflt_dpni = (struct fsl_dpni_obj *)calloc(
1323 sizeof(struct fsl_dpni_obj), 1);
1730a17d 1324 if (!dflt_dpni) {
a572fb6b 1325 printf("No memory: calloc() failed\n");
1730a17d 1326 err = -ENOMEM;
a572fb6b 1327 goto err_calloc;
1730a17d
PK
1328 }
1329
2557c5a9
YG
1330 memset(&dpni_cfg, 0, sizeof(dpni_cfg));
1331 err = dpni_prepare_cfg(&dpni_cfg, &cfg_buf[0]);
879a59ac
PK
1332 if (err < 0) {
1333 err = -ENODEV;
2557c5a9
YG
1334 printf("dpni_prepare_cfg() failed: %d\n", err);
1335 goto err_prepare_cfg;
879a59ac
PK
1336 }
1337
2557c5a9
YG
1338 err = dpni_create(dflt_mc_io,
1339 dflt_dprc_handle,
1340 MC_CMD_NO_FLAGS,
1341 &dpni_cfg,
1342 &dflt_dpni->dpni_id);
1730a17d
PK
1343 if (err < 0) {
1344 err = -ENODEV;
2557c5a9 1345 printf("dpni create() failed: %d\n", err);
1730a17d
PK
1346 goto err_create;
1347 }
1348
2557c5a9
YG
1349 err = dpni_get_api_version(dflt_mc_io, 0,
1350 &major_ver,
1351 &minor_ver);
1730a17d 1352 if (err < 0) {
2557c5a9
YG
1353 printf("dpni_get_api_version() failed: %d\n", err);
1354 goto err_get_version;
1730a17d
PK
1355 }
1356
2557c5a9
YG
1357 if (major_ver < DPNI_VER_MAJOR || (major_ver == DPNI_VER_MAJOR &&
1358 minor_ver < DPNI_VER_MINOR)) {
9a696f56 1359 printf("DPNI version mismatch found %u.%u,",
2557c5a9 1360 major_ver, minor_ver);
9a696f56
PK
1361 printf("supported version is %u.%u\n",
1362 DPNI_VER_MAJOR, DPNI_VER_MINOR);
1363 }
1364
2557c5a9
YG
1365 err = dpni_open(dflt_mc_io,
1366 MC_CMD_NO_FLAGS,
1367 dflt_dpni->dpni_id,
1368 &dflt_dpni->dpni_handle);
1369 if (err) {
1370 printf("dpni_open() failed\n");
1371 goto err_open;
1372 }
1373
1730a17d
PK
1374#ifdef DEBUG
1375 printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1376#endif
1730a17d
PK
1377 err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
1378 if (err < 0) {
1379 printf("dpni_close() failed: %d\n", err);
1380 goto err_close;
1381 }
1382
1383 return 0;
1384
1385err_close:
1730a17d 1386 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
2557c5a9
YG
1387err_open:
1388err_get_version:
1389 dpni_destroy(dflt_mc_io,
1390 dflt_dprc_handle,
1391 MC_CMD_NO_FLAGS,
1392 dflt_dpni->dpni_id);
1730a17d 1393err_create:
2557c5a9 1394err_prepare_cfg:
879a59ac 1395 free(dflt_dpni);
a572fb6b 1396err_calloc:
1730a17d
PK
1397 return err;
1398}
1399
1400static int dpni_exit(void)
1401{
1402 int err;
1403
2557c5a9
YG
1404 err = dpni_destroy(dflt_mc_io, dflt_dprc_handle, MC_CMD_NO_FLAGS,
1405 dflt_dpni->dpni_id);
1730a17d
PK
1406 if (err < 0) {
1407 printf("dpni_destroy() failed: %d\n", err);
1408 goto err;
1409 }
1410
1411#ifdef DEBUG
1412 printf("Exit: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1413#endif
1414
1415 if (dflt_dpni)
1416 free(dflt_dpni);
1417 return 0;
1418
1419err:
1420 return err;
1421}
1422
1423static int mc_init_object(void)
a2a55e51 1424{
1730a17d
PK
1425 int err = 0;
1426
1427 err = dprc_init();
1428 if (err < 0) {
1429 printf("dprc_init() failed: %d\n", err);
1430 goto err;
1431 }
1432
1433 err = dpbp_init();
1434 if (err < 0) {
1435 printf("dpbp_init() failed: %d\n", err);
1436 goto err;
1437 }
1438
1439 err = dpio_init();
1440 if (err < 0) {
1441 printf("dpio_init() failed: %d\n", err);
1442 goto err;
1443 }
1444
1445 err = dpni_init();
1446 if (err < 0) {
1447 printf("dpni_init() failed: %d\n", err);
1448 goto err;
1449 }
a2a55e51 1450
fb4a87a7 1451 return 0;
1730a17d
PK
1452err:
1453 return err;
a2a55e51
PK
1454}
1455
1730a17d 1456int fsl_mc_ldpaa_exit(bd_t *bd)
a2a55e51 1457{
1730a17d 1458 int err = 0;
42e81790 1459 bool is_dpl_apply_status = false;
06651b94 1460 bool mc_boot_status = false;
1730a17d 1461
b7b8410a 1462 if (bd && mc_lazy_dpl_addr && !fsl_mc_ldpaa_exit(NULL)) {
f9747a5a
YG
1463 err = mc_apply_dpl(mc_lazy_dpl_addr);
1464 if (!err)
1465 fdt_fixup_board_enet(working_fdt);
b7b8410a
AG
1466 mc_lazy_dpl_addr = 0;
1467 }
1468
06651b94
SK
1469 if (!get_mc_boot_status())
1470 mc_boot_status = true;
1471
6dedcedd 1472 /* MC is not loaded intentionally, So return success. */
06651b94 1473 if (bd && !mc_boot_status)
1730a17d
PK
1474 return 0;
1475
42e81790
YG
1476 /* If DPL is deployed, set is_dpl_apply_status as TRUE. */
1477 if (!get_dpl_apply_status())
1478 is_dpl_apply_status = true;
1730a17d 1479
42e81790
YG
1480 /*
1481 * For case MC is loaded but DPL is not deployed, return success and
1482 * print message on console. Else FDT fix-up code execution hanged.
1483 */
06651b94 1484 if (bd && mc_boot_status && !is_dpl_apply_status) {
42e81790 1485 printf("fsl-mc: DPL not deployed, DPAA2 ethernet not work\n");
73fa206a 1486 goto mc_obj_cleanup;
42e81790 1487 }
1730a17d 1488
06651b94
SK
1489 if (bd && mc_boot_status && is_dpl_apply_status)
1490 return 0;
1491
73fa206a 1492mc_obj_cleanup:
1730a17d
PK
1493 err = dpbp_exit();
1494 if (err < 0) {
a2a4dc56 1495 printf("dpbp_exit() failed: %d\n", err);
1730a17d
PK
1496 goto err;
1497 }
1498
1499 err = dpio_exit();
1500 if (err < 0) {
1501 printf("dpio_exit() failed: %d\n", err);
1502 goto err;
1503 }
1504
1505 err = dpni_exit();
1506 if (err < 0) {
1507 printf("dpni_exit() failed: %d\n", err);
1508 goto err;
1509 }
1510
1511 err = dprc_exit();
1512 if (err < 0) {
1513 printf("dprc_exit() failed: %d\n", err);
1514 goto err;
1515 }
1516
1517 return 0;
1518err:
1519 return err;
a2a55e51
PK
1520}
1521
fb4a87a7 1522static int do_fsl_mc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
a2a55e51 1523{
fb4a87a7
PK
1524 int err = 0;
1525 if (argc < 3)
1526 goto usage;
1527
1528 switch (argv[1][0]) {
1529 case 's': {
1530 char sub_cmd;
44937214
PK
1531 u64 mc_fw_addr, mc_dpc_addr;
1532#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1533 u64 aiop_fw_addr;
1534#endif
fb4a87a7
PK
1535
1536 sub_cmd = argv[2][0];
2557c5a9 1537
fb4a87a7
PK
1538 switch (sub_cmd) {
1539 case 'm':
1540 if (argc < 5)
1541 goto usage;
1542
1543 if (get_mc_boot_status() == 0) {
1544 printf("fsl-mc: MC is already booted");
1545 printf("\n");
1546 return err;
1547 }
1548 mc_fw_addr = simple_strtoull(argv[3], NULL, 16);
1549 mc_dpc_addr = simple_strtoull(argv[4], NULL,
1550 16);
1730a17d
PK
1551
1552 if (!mc_init(mc_fw_addr, mc_dpc_addr))
1553 err = mc_init_object();
fb4a87a7
PK
1554 break;
1555
1556#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1557 case 'a':
1558 if (argc < 4)
1559 goto usage;
1560 if (get_aiop_apply_status() == 0) {
1561 printf("fsl-mc: AIOP FW is already");
1562 printf(" applied\n");
1563 return err;
1564 }
1565
1566 aiop_fw_addr = simple_strtoull(argv[3], NULL,
1567 16);
1568
3c1d218a 1569 /* if SoC doesn't have AIOP, err = -ENODEV */
fb4a87a7
PK
1570 err = load_mc_aiop_img(aiop_fw_addr);
1571 if (!err)
1572 printf("fsl-mc: AIOP FW applied\n");
1573 break;
1574#endif
1575 default:
1576 printf("Invalid option: %s\n", argv[2]);
1577 goto usage;
a2a55e51 1578
fb4a87a7
PK
1579 break;
1580 }
125e2bc1 1581 }
fb4a87a7
PK
1582 break;
1583
b7b8410a 1584 case 'l':
fb4a87a7
PK
1585 case 'a': {
1586 u64 mc_dpl_addr;
1587
1588 if (argc < 4)
1589 goto usage;
1590
1591 if (get_dpl_apply_status() == 0) {
1592 printf("fsl-mc: DPL already applied\n");
1593 return err;
1594 }
1595
1596 mc_dpl_addr = simple_strtoull(argv[3], NULL,
1597 16);
1730a17d 1598
fb4a87a7
PK
1599 if (get_mc_boot_status() != 0) {
1600 printf("fsl-mc: Deploying data path layout ..");
1601 printf("ERROR (MC is not booted)\n");
1602 return -ENODEV;
1603 }
1730a17d 1604
b7b8410a
AG
1605 if (argv[1][0] == 'l') {
1606 /*
1607 * We will do the actual dpaa exit and dpl apply
1608 * later from announce_and_cleanup().
1609 */
1610 mc_lazy_dpl_addr = mc_dpl_addr;
1611 } else {
1612 /* The user wants it applied now */
1613 if (!fsl_mc_ldpaa_exit(NULL))
1614 err = mc_apply_dpl(mc_dpl_addr);
1615 }
fb4a87a7 1616 break;
125e2bc1 1617 }
fb4a87a7
PK
1618 default:
1619 printf("Invalid option: %s\n", argv[1]);
1620 goto usage;
1621 break;
a2a55e51 1622 }
fb4a87a7
PK
1623 return err;
1624 usage:
1625 return CMD_RET_USAGE;
a2a55e51 1626}
fb4a87a7
PK
1627
1628U_BOOT_CMD(
1629 fsl_mc, CONFIG_SYS_MAXARGS, 1, do_fsl_mc,
1630 "DPAA2 command to manage Management Complex (MC)",
1631 "start mc [FW_addr] [DPC_addr] - Start Management Complex\n"
1632 "fsl_mc apply DPL [DPL_addr] - Apply DPL file\n"
b7b8410a 1633 "fsl_mc lazyapply DPL [DPL_addr] - Apply DPL file on exit\n"
fb4a87a7
PK
1634 "fsl_mc start aiop [FW_addr] - Start AIOP\n"
1635);
33a8991a
BP
1636
1637void mc_env_boot(void)
1638{
1639#if defined(CONFIG_FSL_MC_ENET)
1640 char *mc_boot_env_var;
1641 /* The MC may only be initialized in the reset PHY function
1642 * because otherwise U-Boot has not yet set up all the MAC
1643 * address info properly. Without MAC addresses, the MC code
1644 * can not properly initialize the DPC.
1645 */
00caae6d 1646 mc_boot_env_var = env_get(MC_BOOT_ENV_VAR);
33a8991a
BP
1647 if (mc_boot_env_var)
1648 run_command_list(mc_boot_env_var, -1, 0);
1649#endif /* CONFIG_FSL_MC_ENET */
1650}
This page took 0.536283 seconds and 4 git commands to generate.