blob: bc1c31d4675b8200e5ad065e56c85141fddce460 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
J. German Rivera8ff14b72014-06-23 15:15:55 -07002/*
Yogesh Gaur1a0c4ae2018-05-09 10:52:17 +05303 * Copyright 2014 Freescale Semiconductor, Inc.
Cosmin-Florin Aluchenesei971dfd32021-07-21 19:13:33 +03004 * Copyright 2017-2018, 2020-2021 NXP
J. German Rivera8ff14b72014-06-23 15:15:55 -07005 */
Stuart Yodera2bdb772015-07-02 11:29:03 +05306#include <common.h>
Simon Glassadaaa482019-11-14 12:57:43 -07007#include <command.h>
Simon Glass63334482019-11-14 12:57:39 -07008#include <cpu_func.h>
Simon Glass0af6e2d2019-08-01 09:46:52 -06009#include <env.h>
J. German Rivera8ff14b72014-06-23 15:15:55 -070010#include <errno.h>
Simon Glass2dc9c342020-05-10 11:40:01 -060011#include <image.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070013#include <malloc.h>
Cosmin-Florin Alucheneseiaa280142021-10-07 13:07:44 +030014#include <mapmem.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060015#include <asm/global_data.h>
Masahiro Yamada78eeb912016-01-24 23:27:48 +090016#include <linux/bug.h>
J. German Rivera8ff14b72014-06-23 15:15:55 -070017#include <asm/io.h>
Simon Glassdbd79542020-05-10 11:40:11 -060018#include <linux/delay.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090019#include <linux/libfdt.h>
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +000020#include <net.h>
Stuart Yodera2bdb772015-07-02 11:29:03 +053021#include <fdt_support.h>
J. German Rivera43e4ae32015-01-06 13:19:02 -080022#include <fsl-mc/fsl_mc.h>
23#include <fsl-mc/fsl_mc_sys.h>
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -070024#include <fsl-mc/fsl_mc_private.h>
J. German Rivera43e4ae32015-01-06 13:19:02 -080025#include <fsl-mc/fsl_dpmng.h>
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -070026#include <fsl-mc/fsl_dprc.h>
27#include <fsl-mc/fsl_dpio.h>
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +053028#include <fsl-mc/fsl_dpni.h>
Florinel Iordacheae6d8522019-11-19 10:28:17 +000029#include <fsl-mc/fsl_dpsparser.h>
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -070030#include <fsl-mc/fsl_qbman_portal.h>
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +053031#include <fsl-mc/ldpaa_wriop.h>
J. German Rivera8ff14b72014-06-23 15:15:55 -070032
J. German Riveraf4fed4b2015-03-20 19:28:18 -070033#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"
Bogdan Purcareata08bc0142017-05-24 16:40:21 +000039#define MC_BOOT_ENV_VAR "mcinitcmd"
Meenakshi Aggarwal67f195c2019-02-27 14:41:02 +053040#define MC_DRAM_BLOCK_DEFAULT_SIZE (512UL * 1024 * 1024)
J. German Riveraf4fed4b2015-03-20 19:28:18 -070041
Cosmin-Florin Alucheneseiaa280142021-10-07 13:07:44 +030042#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
J. German Rivera8ff14b72014-06-23 15:15:55 -070052DECLARE_GLOBAL_DATA_PTR;
Prabhakar Kushwaha145e4cd2018-08-27 12:58:52 +053053static int mc_memset_resv_ram;
Florinel Iordacheae6d8522019-11-19 10:28:17 +000054static struct mc_version mc_ver_info;
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +053055static 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
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +053060struct fsl_mc_io *root_mc_io = NULL;
61struct fsl_mc_io *dflt_mc_io = NULL; /* child container */
62uint16_t root_dprc_handle = 0;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -070063uint16_t dflt_dprc_handle = 0;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +053064int child_dprc_id;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -070065struct fsl_dpbp_obj *dflt_dpbp = NULL;
66struct fsl_dpio_obj *dflt_dpio = NULL;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +053067struct fsl_dpni_obj *dflt_dpni = NULL;
Alexander Graf2ebeb442016-11-17 01:02:57 +010068static u64 mc_lazy_dpl_addr;
Florinel Iordacheae6d8522019-11-19 10:28:17 +000069static u32 dpsparser_obj_id;
70static u16 dpsparser_handle;
71static char *mc_err_msg_apply_spb[] = MC_ERROR_MSG_APPLY_SPB;
J. German Riveraf4fed4b2015-03-20 19:28:18 -070072
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}
J. German Rivera8ff14b72014-06-23 15:15:55 -070085
J. German Riveraf4fed4b2015-03-20 19:28:18 -070086void 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 /* DEBUG */
114
J. German Rivera8ff14b72014-06-23 15:15:55 -0700115/**
116 * Copying MC firmware or DPL image to DDR
117 */
118static int mc_copy_image(const char *title,
J. German Rivera43e4ae32015-01-06 13:19:02 -0800119 u64 image_addr, u32 image_size, u64 mc_ram_addr)
J. German Rivera8ff14b72014-06-23 15:15:55 -0700120{
121 debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
122 memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700123 flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size);
J. German Rivera8ff14b72014-06-23 15:15:55 -0700124 return 0;
125}
126
Florinel Iordacheae6d8522019-11-19 10:28:17 +0000127#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
J. German Rivera8ff14b72014-06-23 15:15:55 -0700128/**
129 * MC firmware FIT image parser checks if the image is in FIT
130 * format, verifies integrity of the image and calculates
131 * raw image address and size values.
J. German Rivera43e4ae32015-01-06 13:19:02 -0800132 * Returns 0 on success and a negative errno on error.
J. German Rivera8ff14b72014-06-23 15:15:55 -0700133 * task fail.
134 **/
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530135int parse_mc_firmware_fit_image(u64 mc_fw_addr,
136 const void **raw_image_addr,
J. German Rivera8ff14b72014-06-23 15:15:55 -0700137 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
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530146 fit_hdr = (void *)mc_fw_addr;
J. German Rivera8ff14b72014-06-23 15:15:55 -0700147
148 /* Check if Image is in FIT format */
149 format = genimg_get_format(fit_hdr);
150
151 if (format != IMAGE_FORMAT_FIT) {
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530152 printf("fsl-mc: ERR: Bad firmware image (not a FIT image)\n");
J. German Rivera43e4ae32015-01-06 13:19:02 -0800153 return -EINVAL;
J. German Rivera8ff14b72014-06-23 15:15:55 -0700154 }
155
Simon Glassd563c252021-02-15 17:08:09 -0700156 if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530157 printf("fsl-mc: ERR: Bad firmware image (bad FIT header)\n");
J. German Rivera43e4ae32015-01-06 13:19:02 -0800158 return -EINVAL;
J. German Rivera8ff14b72014-06-23 15:15:55 -0700159 }
160
161 node_offset = fit_image_get_node(fit_hdr, uname);
162
163 if (node_offset < 0) {
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530164 printf("fsl-mc: ERR: Bad firmware image (missing subimage)\n");
J. German Rivera43e4ae32015-01-06 13:19:02 -0800165 return -ENOENT;
J. German Rivera8ff14b72014-06-23 15:15:55 -0700166 }
167
168 /* Verify MC firmware image */
169 if (!(fit_image_verify(fit_hdr, node_offset))) {
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530170 printf("fsl-mc: ERR: Bad firmware image (bad CRC)\n");
J. German Rivera43e4ae32015-01-06 13:19:02 -0800171 return -EINVAL;
J. German Rivera8ff14b72014-06-23 15:15:55 -0700172 }
173
174 /* Get address and size of raw image */
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}
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700182#endif
183
Bogdan Purcareata72669142017-05-24 16:40:22 +0000184#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,
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200192#ifdef CONFIG_DM_ETH
193 const char *propname, struct udevice *eth_dev,
194#else
Bogdan Purcareata72669142017-05-24 16:40:22 +0000195 const char *propname, struct eth_device *eth_dev,
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200196#endif
Bogdan Purcareata72669142017-05-24 16:40:22 +0000197 enum mc_fixup_type type)
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000198{
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200199#ifdef CONFIG_DM_ETH
Simon Glassfa20e932020-12-03 16:55:20 -0700200 struct eth_pdata *plat = dev_get_plat(eth_dev);
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200201 unsigned char *enetaddr = plat->enetaddr;
Simon Glass75e534b2020-12-16 21:20:07 -0700202 int eth_index = dev_seq(eth_dev);
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200203#else
204 unsigned char *enetaddr = eth_dev->enetaddr;
205 int eth_index = eth_dev->index;
206#endif
Bogdan Purcareata72669142017-05-24 16:40:22 +0000207 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:
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200214 /* DPL likes its addresses on 32 * ARP_HLEN bits */
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;
Bogdan Purcareata72669142017-05-24 16:40:22 +0000220 case MC_FIXUP_DPC:
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200221 val = enetaddr;
222 len = ARP_HLEN;
223 break;
Bogdan Purcareata72669142017-05-24 16:40:22 +0000224 }
225
226 /* MAC address property present */
227 if (fdt_get_property(blob, nodeoffset, propname, NULL)) {
228 /* u-boot MAC addr randomly assigned - leave the present one */
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200229 if (!eth_env_get_enetaddr_by_index("eth", eth_index,
Simon Glass399a9ce2017-08-03 12:22:14 -0600230 env_enetaddr))
Bogdan Purcareata72669142017-05-24 16:40:22 +0000231 return err;
232 } else {
233 size = MC_DT_INCREASE_SIZE + strlen(propname) + len;
234 /* make room for mac address property */
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,
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200279#ifdef CONFIG_DM_ETH
280 struct udevice *eth_dev)
281#else
Bogdan Purcareata72669142017-05-24 16:40:22 +0000282 struct eth_device *eth_dev)
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200283#endif
Bogdan Purcareata72669142017-05-24 16:40:22 +0000284{
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 /* dpmac not defined in DPL, so skip it. */
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 /* now we need to figure out if there is any
305 * DPNI connected to this MAC, so we walk the
306 * connection list
307 */
308 endpoint = dpl_get_connection_endpoint(blob, mac_name);
309 if (!is_dpni(endpoint))
310 return 0;
311
312 /* let's see if we can fixup the DPNI as well */
313 dpnioff = fdt_subnode_offset(blob, objoff, endpoint);
314 if (dpnioff < 0)
315 /* DPNI not defined in DPL in the objects area */
316 return 0;
317
318 return mc_fixup_mac_addr(blob, dpnioff, "mac_addr", eth_dev,
319 MC_FIXUP_DPL);
320}
321
Meenakshi Aggarwald67ae482019-05-23 15:13:43 +0530322void 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
Nipun Guptad6912642018-08-20 16:01:14 +0530332void fdt_fsl_mc_fixup_iommu_map_entry(void *blob)
333{
334 u32 *prop;
Laurentiu Tudor9e352592020-05-04 14:47:11 +0300335 u32 iommu_map[4], phandle;
Nipun Guptad6912642018-08-20 16:01:14 +0530336 int offset;
337 int lenp;
338
339 /* find fsl-mc node */
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));
Laurentiu Tudor9e352592020-05-04 14:47:11 +0300364
365 /* get phandle to MSI controller */
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 /* also set msi-map property */
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);
Nipun Guptad6912642018-08-20 16:01:14 +0530379}
380
Bogdan Purcareata72669142017-05-24 16:40:22 +0000381static int mc_fixup_dpc_mac_addr(void *blob, int dpmac_id,
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200382#ifdef CONFIG_DM_ETH
383 struct udevice *eth_dev)
384#else
Bogdan Purcareata72669142017-05-24 16:40:22 +0000385 struct eth_device *eth_dev)
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200386#endif
Bogdan Purcareata72669142017-05-24 16:40:22 +0000387{
388 int nodeoffset = fdt_path_offset(blob, "/board_info/ports"), noff;
389 int err = 0;
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000390 char mac_name[10];
Bogdan Purcareata72669142017-05-24 16:40:22 +0000391 const char link_type_mode[] = "MAC_LINK_TYPE_FIXED";
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000392
393 sprintf(mac_name, "mac@%d", dpmac_id);
394
395 /* node not found - create it */
Bogdan Purcareata72669142017-05-24 16:40:22 +0000396 noff = fdt_subnode_offset(blob, nodeoffset, (const char *)mac_name);
397 if (noff < 0) {
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000398 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
Bogdan Purcareata72669142017-05-24 16:40:22 +0000405 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 }
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000411
412 /* add default property of fixed link */
Bogdan Purcareata72669142017-05-24 16:40:22 +0000413 err = fdt_appendprop_string(blob, noff,
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000414 "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
Bogdan Purcareata72669142017-05-24 16:40:22 +0000422 return mc_fixup_mac_addr(blob, noff, "port_mac_address", eth_dev,
423 MC_FIXUP_DPC);
424}
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000425
Bogdan Purcareata72669142017-05-24 16:40:22 +0000426static int mc_fixup_mac_addrs(void *blob, enum mc_fixup_type type)
427{
428 int i, err = 0, ret = 0;
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200429#ifdef CONFIG_DM_ETH
430#define ETH_NAME_LEN 20
431 struct udevice *eth_dev;
432#else
Bogdan Purcareata72669142017-05-24 16:40:22 +0000433 struct eth_device *eth_dev;
Ioana Ciornei25f7cf72020-03-18 16:47:38 +0200434#endif
435 char ethname[ETH_NAME_LEN];
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000436
Bogdan Purcareata72669142017-05-24 16:40:22 +0000437 for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
438 /* port not enabled */
Pankaj Bansal7987ab72018-10-10 14:08:33 +0530439 if (wriop_is_enabled_dpmac(i) != 1)
Bogdan Purcareata72669142017-05-24 16:40:22 +0000440 continue;
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000441
Pankaj Bansal8a921702018-08-02 16:31:28 +0530442 snprintf(ethname, ETH_NAME_LEN, "DPMAC%d@%s", i,
443 phy_interface_strings[wriop_get_enet_if(i)]);
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000444
Bogdan Purcareata72669142017-05-24 16:40:22 +0000445 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;
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000464 }
465
Bogdan Purcareata72669142017-05-24 16:40:22 +0000466 return ret;
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000467}
468
Stuart Yodera2bdb772015-07-02 11:29:03 +0530469static int mc_fixup_dpc(u64 dpc_addr)
470{
471 void *blob = (void *)dpc_addr;
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000472 int nodeoffset, err = 0;
Stuart Yodera2bdb772015-07-02 11:29:03 +0530473
474 /* delete any existing ICID pools */
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 /* add a new pool */
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
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000494 /* fixup MAC addresses for dpmac ports */
495 nodeoffset = fdt_path_offset(blob, "/board_info/ports");
Razvan Ionut Cirjana3bbc3b2020-04-28 16:09:59 +0300496 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 }
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000509
Bogdan Purcareata72669142017-05-24 16:40:22 +0000510 err = mc_fixup_mac_addrs(blob, MC_FIXUP_DPC);
Ioana Ciocoi Radulescud7697f42019-02-26 15:50:07 +0000511
512out:
Stuart Yodera2bdb772015-07-02 11:29:03 +0530513 flush_dcache_range(dpc_addr, dpc_addr + fdt_totalsize(blob));
514
Bogdan Purcareatabea8abd2017-01-11 15:58:36 +0000515 return err;
Stuart Yodera2bdb772015-07-02 11:29:03 +0530516}
517
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530518static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpc_addr)
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700519{
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 * Load the MC DPC blob in the MC private DRAM block:
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 * Get address and size of the DPC blob stored in flash:
544 */
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530545 dpc_fdt_hdr = (void *)mc_dpc_addr;
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700546
547 error = fdt_check_header(dpc_fdt_hdr);
548 if (error != 0) {
549 /*
550 * Don't return with error here, since the MC firmware can
551 * still boot without a DPC
552 */
J. German Rivera75d7ace2015-07-02 11:28:56 +0530553 printf("\nfsl-mc: WARNING: No DPC image found");
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700554 return 0;
555 }
556
557 dpc_size = fdt_totalsize(dpc_fdt_hdr);
558 if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) {
J. German Rivera75d7ace2015-07-02 11:28:56 +0530559 printf("\nfsl-mc: ERROR: Bad DPC image (too large: %d)\n",
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700560 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 /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */
567
Stuart Yodera2bdb772015-07-02 11:29:03 +0530568 if (mc_fixup_dpc(mc_ram_addr + mc_dpc_offset))
569 return -EINVAL;
570
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700571 dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset));
572 return 0;
573}
574
Bogdan Purcareata72669142017-05-24 16:40:22 +0000575
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 /* The DPL fixup for mac addresses is only relevant
583 * for old-style DPLs
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
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530594static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size, u64 mc_dpl_addr)
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700595{
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 * Load the MC DPL blob in the MC private DRAM block:
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 * Get address and size of the DPL blob stored in flash:
620 */
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530621 dpl_fdt_hdr = (void *)mc_dpl_addr;
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700622
623 error = fdt_check_header(dpl_fdt_hdr);
624 if (error != 0) {
J. German Rivera75d7ace2015-07-02 11:28:56 +0530625 printf("\nfsl-mc: ERROR: Bad DPL image (bad header)\n");
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700626 return error;
627 }
628
629 dpl_size = fdt_totalsize(dpl_fdt_hdr);
630 if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
J. German Rivera75d7ace2015-07-02 11:28:56 +0530631 printf("\nfsl-mc: ERROR: Bad DPL image (too large: %d)\n",
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700632 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 /* not defined CONFIG_SYS_LS_MC_DPL_IN_DDR */
639
Bogdan Purcareata72669142017-05-24 16:40:22 +0000640 if (mc_fixup_dpl(mc_ram_addr + mc_dpl_offset))
641 return -EINVAL;
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700642 dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset));
643 return 0;
644}
645
646/**
647 * Return the MC boot timeout value in milliseconds
648 */
649static unsigned long get_mc_boot_timeout_ms(void)
650{
651 unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
652
Simon Glass64b723f2017-08-03 12:22:12 -0600653 char *timeout_ms_env_var = env_get(MC_BOOT_TIMEOUT_ENV_VAR);
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700654
655 if (timeout_ms_env_var) {
Simon Glassff9b9032021-07-24 09:03:30 -0600656 timeout_ms = dectoul(timeout_ms_env_var, NULL);
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700657 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
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530670#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
York Suncbe8e1c2016-04-04 11:41:26 -0700671
672__weak bool soc_has_aiop(void)
673{
674 return false;
675}
676
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530677static int load_mc_aiop_img(u64 aiop_fw_addr)
J. German Riverac3b505f2015-07-02 11:28:58 +0530678{
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530679 u64 mc_ram_addr = mc_get_dram_addr();
680#ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
J. German Riverac3b505f2015-07-02 11:28:58 +0530681 void *aiop_img;
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530682#endif
J. German Riverac3b505f2015-07-02 11:28:58 +0530683
York Suncbe8e1c2016-04-04 11:41:26 -0700684 /* Check if AIOP is available */
685 if (!soc_has_aiop())
686 return -ENODEV;
J. German Riverac3b505f2015-07-02 11:28:58 +0530687 /*
688 * Load the MC AIOP image in the MC private DRAM block:
689 */
690
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530691#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;
J. German Riverac3b505f2015-07-02 11:28:58 +0530696 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);
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530699#endif
700 mc_aiop_applied = 0;
J. German Riverac3b505f2015-07-02 11:28:58 +0530701
702 return 0;
703}
704#endif
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530705
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700706static 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();
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700714 assert(timeout_ms > 0);
715 for (;;) {
716 udelay(1000); /* throttle polling */
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) {
J. German Rivera75d7ace2015-07-02 11:28:56 +0530728 printf("ERROR: timeout\n");
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700729
730 /* TODO: Get an error status from an MC CCSR register */
731 return -ETIMEDOUT;
732 }
733
734 if (mc_fw_boot_status != 0x1) {
735 /*
736 * TODO: Identify critical errors from the GSR register's FS
737 * field and for those errors, set error to -ENODEV or other
738 * appropriate errno, so that the status property is set to
739 * failure in the fsl,dprc device tree node.
740 */
J. German Rivera75d7ace2015-07-02 11:28:56 +0530741 printf("WARNING: Firmware returned an error (GSR: %#x)\n",
742 reg_gsr);
743 } else {
744 printf("SUCCESS\n");
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700745 }
746
J. German Rivera75d7ace2015-07-02 11:28:56 +0530747
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700748 *final_reg_gsr = reg_gsr;
749 return 0;
750}
J. German Rivera8ff14b72014-06-23 15:15:55 -0700751
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530752int mc_init(u64 mc_fw_addr, u64 mc_dpc_addr)
J. German Rivera8ff14b72014-06-23 15:15:55 -0700753{
754 int error = 0;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -0700755 int portal_id = 0;
J. German Rivera8ff14b72014-06-23 15:15:55 -0700756 struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530757 u64 mc_ram_addr = mc_get_dram_addr();
J. German Rivera8ff14b72014-06-23 15:15:55 -0700758 u32 reg_gsr;
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700759 u32 reg_mcfbalr;
760#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
J. German Rivera8ff14b72014-06-23 15:15:55 -0700761 const void *raw_image_addr;
762 size_t raw_image_size = 0;
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700763#endif
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700764 u8 mc_ram_num_256mb_blocks;
765 size_t mc_ram_size = mc_get_dram_block_size();
J. German Rivera8ff14b72014-06-23 15:15:55 -0700766
York Sunc55d7312017-03-06 09:02:29 -0800767 mc_ram_num_256mb_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT;
Meenakshi Aggarwal67f195c2019-02-27 14:41:02 +0530768
769 if (mc_ram_num_256mb_blocks >= 0xff) {
York Sunc55d7312017-03-06 09:02:29 -0800770 error = -EINVAL;
771 printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
772 mc_ram_size);
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700773 goto out;
York Sunc55d7312017-03-06 09:02:29 -0800774 }
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700775
J. German Rivera8ff14b72014-06-23 15:15:55 -0700776 /*
Meenakshi Aggarwal67f195c2019-02-27 14:41:02 +0530777 * To support 128 MB DDR Size for MC
778 */
779 if (mc_ram_num_256mb_blocks == 0)
780 mc_ram_num_256mb_blocks = 0xFF;
781
782 /*
J. German Rivera8ff14b72014-06-23 15:15:55 -0700783 * Management Complex cores should be held at reset out of POR.
Bin Meng75574052016-02-05 19:30:11 -0800784 * U-Boot should be the first software to touch MC. To be safe,
J. German Rivera8ff14b72014-06-23 15:15:55 -0700785 * we reset all cores again by setting GCR1 to 0. It doesn't do
786 * anything if they are held at reset. After we setup the firmware
787 * we kick off MC by deasserting the reset bit for core 0, and
788 * deasserting the reset bits for Command Portal Managers.
789 * The stop bits are not touched here. They are used to stop the
790 * cores when they are active. Setting stop bits doesn't stop the
791 * cores from fetching instructions when they are released from
792 * reset.
793 */
794 out_le32(&mc_ccsr_regs->reg_gcr1, 0);
795 dmb();
796
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700797#ifdef CONFIG_SYS_LS_MC_FW_IN_DDR
798 printf("MC firmware is preloaded to %#llx\n", mc_ram_addr);
799#else
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530800 error = parse_mc_firmware_fit_image(mc_fw_addr, &raw_image_addr,
801 &raw_image_size);
J. German Rivera8ff14b72014-06-23 15:15:55 -0700802 if (error != 0)
803 goto out;
804 /*
805 * Load the MC FW at the beginning of the MC private DRAM block:
806 */
J. German Rivera43e4ae32015-01-06 13:19:02 -0800807 mc_copy_image("MC Firmware",
808 (u64)raw_image_addr, raw_image_size, mc_ram_addr);
J. German Rivera43e4ae32015-01-06 13:19:02 -0800809#endif
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700810 dump_ram_words("firmware", (void *)mc_ram_addr);
J. German Rivera43e4ae32015-01-06 13:19:02 -0800811
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530812 error = load_mc_dpc(mc_ram_addr, mc_ram_size, mc_dpc_addr);
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700813 if (error != 0)
J. German Rivera8ff14b72014-06-23 15:15:55 -0700814 goto out;
J. German Riverac3b505f2015-07-02 11:28:58 +0530815
J. German Rivera8ff14b72014-06-23 15:15:55 -0700816 debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700817 dump_mc_ccsr_regs(mc_ccsr_regs);
J. German Rivera8ff14b72014-06-23 15:15:55 -0700818
819 /*
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700820 * Tell MC what is the address range of the DRAM block assigned to it:
J. German Rivera8ff14b72014-06-23 15:15:55 -0700821 */
Meenakshi Aggarwal67f195c2019-02-27 14:41:02 +0530822 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
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700830 out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr);
831 out_le32(&mc_ccsr_regs->reg_mcfbahr,
York Sunc55d7312017-03-06 09:02:29 -0800832 (u32)(mc_ram_addr >> 32));
Stuart Yoderd1970352015-07-02 11:29:02 +0530833 out_le32(&mc_ccsr_regs->reg_mcfapr, FSL_BYPASS_AMQ);
J. German Rivera8ff14b72014-06-23 15:15:55 -0700834
835 /*
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700836 * Tell the MC that we want delayed DPL deployment.
J. German Rivera8ff14b72014-06-23 15:15:55 -0700837 */
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700838 out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00);
J. German Rivera8ff14b72014-06-23 15:15:55 -0700839
J. German Rivera75d7ace2015-07-02 11:28:56 +0530840 printf("\nfsl-mc: Booting Management Complex ... ");
J. German Rivera43e4ae32015-01-06 13:19:02 -0800841
J. German Rivera8ff14b72014-06-23 15:15:55 -0700842 /*
843 * Deassert reset and release MC core 0 to run
844 */
845 out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700846 error = wait_for_mc(true, &reg_gsr);
847 if (error != 0)
J. German Rivera8ff14b72014-06-23 15:15:55 -0700848 goto out;
J. German Rivera8ff14b72014-06-23 15:15:55 -0700849
J. German Rivera43e4ae32015-01-06 13:19:02 -0800850 /*
851 * TODO: need to obtain the portal_id for the root container from the
852 * DPL
853 */
854 portal_id = 0;
855
856 /*
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -0700857 * Initialize the global default MC portal
858 * And check that the MC firmware is responding portal commands:
J. German Rivera43e4ae32015-01-06 13:19:02 -0800859 */
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +0530860 root_mc_io = (struct fsl_mc_io *)calloc(sizeof(struct fsl_mc_io), 1);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +0530861 if (!root_mc_io) {
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +0530862 printf(" No memory: calloc() failed\n");
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -0700863 return -ENOMEM;
864 }
865
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +0530866 root_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
J. German Rivera43e4ae32015-01-06 13:19:02 -0800867 debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +0530868 portal_id, root_mc_io->mmio_regs);
J. German Rivera43e4ae32015-01-06 13:19:02 -0800869
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +0530870 error = mc_get_version(root_mc_io, MC_CMD_NO_FLAGS, &mc_ver_info);
J. German Rivera43e4ae32015-01-06 13:19:02 -0800871 if (error != 0) {
872 printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n",
873 error);
874 goto out;
875 }
876
J. German Rivera43e4ae32015-01-06 13:19:02 -0800877 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,
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700879 reg_gsr & GSR_FS_MASK);
880
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530881out:
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
Alexander Graf2ebeb442016-11-17 01:02:57 +0100898 if (!mc_dpl_addr)
899 return -1;
900
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530901 error = load_mc_dpl(mc_ram_addr, mc_ram_size, mc_dpl_addr);
902 if (error != 0)
903 return error;
904
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700905 /*
906 * Tell the MC to deploy the DPL:
907 */
908 out_le32(&mc_ccsr_regs->reg_gsr, 0x0);
J. German Rivera75d7ace2015-07-02 11:28:56 +0530909 printf("fsl-mc: Deploying data path layout ... ");
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700910 error = wait_for_mc(false, &reg_gsr);
J. German Rivera75d7ace2015-07-02 11:28:56 +0530911
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530912 if (!error)
913 mc_dpl_applied = 0;
J. German Rivera8ff14b72014-06-23 15:15:55 -0700914
915 return error;
916}
917
918int get_mc_boot_status(void)
919{
920 return mc_boot_status;
921}
922
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530923#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
Mian Yousaf Kaukab97124652018-12-18 14:01:17 +0100935int is_lazy_dpl_addr_valid(void)
936{
937 return !!mc_lazy_dpl_addr;
938}
939
Priyanka Jaine0e0be52017-08-24 16:42:43 +0530940/*
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530941 * Return the MC address of private DRAM block.
Priyanka Jaine0e0be52017-08-24 16:42:43 +0530942 * As per MC design document, MC initial base address
943 * should be least significant 512MB address of MC private
944 * memory, i.e. address should point to end address masked
945 * with 512MB offset in private DRAM block.
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530946 */
947u64 mc_get_dram_addr(void)
948{
Priyanka Jaine0e0be52017-08-24 16:42:43 +0530949 size_t mc_ram_size = mc_get_dram_block_size();
950
Prabhakar Kushwaha145e4cd2018-08-27 12:58:52 +0530951 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
Priyanka Jaine0e0be52017-08-24 16:42:43 +0530956 return (gd->arch.resv_ram + mc_ram_size - 1) &
957 MC_RAM_BASE_ADDR_ALIGNMENT_MASK;
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +0530958}
959
960/**
J. German Rivera8ff14b72014-06-23 15:15:55 -0700961 * Return the actual size of the MC private DRAM block.
J. German Rivera8ff14b72014-06-23 15:15:55 -0700962 */
963unsigned long mc_get_dram_block_size(void)
964{
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700965 unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
966
Simon Glass64b723f2017-08-03 12:22:12 -0600967 char *dram_block_size_env_var = env_get(MC_MEM_SIZE_ENV_VAR);
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700968
969 if (dram_block_size_env_var) {
Simon Glass3ff49ec2021-07-24 09:03:29 -0600970 dram_block_size = hextoul(dram_block_size_env_var, NULL);
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700971
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
Meenakshi Aggarwal67f195c2019-02-27 14:41:02 +0530978 dram_block_size = MC_DRAM_BLOCK_DEFAULT_SIZE;
J. German Riveraf4fed4b2015-03-20 19:28:18 -0700979 }
980 }
981
982 return dram_block_size;
J. German Rivera8ff14b72014-06-23 15:15:55 -0700983}
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -0700984
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900985int fsl_mc_ldpaa_init(struct bd_info *bis)
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +0530986{
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530987 int i;
988
989 for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++)
Pankaj Bansal7987ab72018-10-10 14:08:33 +0530990 if (wriop_is_enabled_dpmac(i) == 1)
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530991 ldpaa_eth_init(i, wriop_get_enet_if(i));
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +0530992 return 0;
993}
994
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530995static int dprc_version_check(struct fsl_mc_io *mc_io, uint16_t handle)
996{
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530997 int error;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530998 uint16_t major_ver, minor_ver;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530999
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301000 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;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +05301006 }
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301007
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
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +05301016 return error;
1017}
1018
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301019static int dpio_init(void)
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001020{
1021 struct qbman_swp_desc p_des;
1022 struct dpio_attr attr;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301023 struct dpio_cfg dpio_cfg;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001024 int err = 0;
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301025 uint16_t major_ver, minor_ver;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001026
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301027 dflt_dpio = (struct fsl_dpio_obj *)calloc(
1028 sizeof(struct fsl_dpio_obj), 1);
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001029 if (!dflt_dpio) {
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301030 printf("No memory: calloc() failed\n");
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301031 err = -ENOMEM;
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301032 goto err_calloc;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001033 }
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301034 dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL;
1035 dpio_cfg.num_priorities = 8;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001036
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301037 err = dpio_create(dflt_mc_io,
1038 dflt_dprc_handle,
1039 MC_CMD_NO_FLAGS,
1040 &dpio_cfg,
1041 &dflt_dpio->dpio_id);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301042 if (err < 0) {
1043 printf("dpio_create() failed: %d\n", err);
1044 err = -ENODEV;
1045 goto err_create;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001046 }
1047
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301048 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
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301072 memset(&attr, 0, sizeof(struct dpio_attr));
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +05301073 err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301074 dflt_dpio->dpio_handle, &attr);
1075 if (err < 0) {
1076 printf("dpio_get_attributes() failed: %d\n", err);
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001077 goto err_get_attr;
1078 }
1079
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301080 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;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +05301083 }
1084
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301085#ifdef DEBUG
1086 printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id);
1087#endif
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301088 err = dpio_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
1089 if (err < 0) {
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001090 printf("dpio_enable() failed %d\n", err);
1091 goto err_get_enable;
1092 }
Prabhakar Kushwahafd5d1272015-07-02 11:28:59 +05301093 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,
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001096 attr.qbman_portal_id,
1097 attr.num_priorities);
1098
Prabhakar Kushwahafd5d1272015-07-02 11:28:59 +05301099 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);
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001103
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:
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301112 dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001113err_get_enable:
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301114err_get_attr:
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301115err_attr_not_same:
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301116 dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301117err_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);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301123err_create:
Prabhakar Kushwahac6018bd2016-03-18 16:15:29 +05301124 free(dflt_dpio);
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301125err_calloc:
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001126 return err;
1127}
1128
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301129static int dpio_exit(void)
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001130{
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301131 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
Cosmin-Florin Aluchenesei971dfd32021-07-21 19:13:33 +03001139 err = dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301140 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);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301149 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 /* Open root container */
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
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +05301194 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
Prabhakar Kushwaha901a88e2016-01-20 12:04:19 +05301200 memset(&cfg, 0, sizeof(struct dprc_cfg));
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301201 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;
Prabhakar Kushwaha7fd59d92015-12-24 15:33:49 +05301205 cfg.portal_id = DPRC_GET_PORTAL_ID_FROM_POOL;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301206 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
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301216 dflt_mc_io = (struct fsl_mc_io *)calloc(sizeof(struct fsl_mc_io), 1);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301217 if (!dflt_mc_io) {
1218 err = -ENOMEM;
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301219 printf(" No memory: calloc() failed\n");
1220 goto err_calloc;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301221 }
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);
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301225
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301226#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);
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301246err_calloc:
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301247 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;
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301296 uint16_t major_ver, minor_ver;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301297
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301298 dflt_dpbp = (struct fsl_dpbp_obj *)calloc(
1299 sizeof(struct fsl_dpbp_obj), 1);
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001300 if (!dflt_dpbp) {
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301301 printf("No memory: calloc() failed\n");
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301302 err = -ENOMEM;
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301303 goto err_calloc;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301304 }
1305
1306 dpbp_cfg.options = 512;
1307
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301308 err = dpbp_create(dflt_mc_io,
1309 dflt_dprc_handle,
1310 MC_CMD_NO_FLAGS,
1311 &dpbp_cfg,
1312 &dflt_dpbp->dpbp_id);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301313
1314 if (err < 0) {
1315 err = -ENODEV;
1316 printf("dpbp_create() failed: %d\n", err);
1317 goto err_create;
1318 }
1319
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301320 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
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301345 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
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301354 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;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +05301357 }
1358
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301359#ifdef DEBUG
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301360 printf("Init: DPBP id=0x%x\n", dflt_dpbp->dpbp_attr.id);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301361#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;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001367 }
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001368
1369 return 0;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301370
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301371err_get_attr:
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301372err_attr_not_same:
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301373 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301374 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:
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301381err_create:
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301382 free(dflt_dpbp);
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301383err_calloc:
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301384 return err;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001385}
1386
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301387static int dpbp_exit(void)
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001388{
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301389 int err;
1390
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301391 err = dpbp_destroy(dflt_mc_io, dflt_dprc_handle, MC_CMD_NO_FLAGS,
1392 dflt_dpbp->dpbp_id);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301393 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
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001401
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301402 if (dflt_dpbp)
1403 free(dflt_dpbp);
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301404 return 0;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301405
1406err:
1407 return err;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001408}
1409
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301410static int dpni_init(void)
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001411{
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301412 int err;
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301413 uint8_t cfg_buf[256] = {0};
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301414 struct dpni_cfg dpni_cfg;
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301415 uint16_t major_ver, minor_ver;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301416
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301417 dflt_dpni = (struct fsl_dpni_obj *)calloc(
1418 sizeof(struct fsl_dpni_obj), 1);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301419 if (!dflt_dpni) {
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301420 printf("No memory: calloc() failed\n");
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301421 err = -ENOMEM;
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301422 goto err_calloc;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301423 }
1424
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301425 memset(&dpni_cfg, 0, sizeof(dpni_cfg));
1426 err = dpni_prepare_cfg(&dpni_cfg, &cfg_buf[0]);
Prabhakar Kushwahae26e2852015-12-24 15:33:01 +05301427 if (err < 0) {
1428 err = -ENODEV;
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301429 printf("dpni_prepare_cfg() failed: %d\n", err);
1430 goto err_prepare_cfg;
Prabhakar Kushwahae26e2852015-12-24 15:33:01 +05301431 }
1432
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301433 err = dpni_create(dflt_mc_io,
1434 dflt_dprc_handle,
1435 MC_CMD_NO_FLAGS,
1436 &dpni_cfg,
1437 &dflt_dpni->dpni_id);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301438 if (err < 0) {
1439 err = -ENODEV;
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301440 printf("dpni create() failed: %d\n", err);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301441 goto err_create;
1442 }
1443
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301444 err = dpni_get_api_version(dflt_mc_io, 0,
1445 &major_ver,
1446 &minor_ver);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301447 if (err < 0) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301448 printf("dpni_get_api_version() failed: %d\n", err);
1449 goto err_get_version;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301450 }
1451
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301452 if (major_ver < DPNI_VER_MAJOR || (major_ver == DPNI_VER_MAJOR &&
1453 minor_ver < DPNI_VER_MINOR)) {
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +05301454 printf("DPNI version mismatch found %u.%u,",
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301455 major_ver, minor_ver);
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +05301456 printf("supported version is %u.%u\n",
1457 DPNI_VER_MAJOR, DPNI_VER_MINOR);
1458 }
1459
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301460 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
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301469#ifdef DEBUG
1470 printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id);
1471#endif
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301472 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:
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301481 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301482err_open:
1483err_get_version:
1484 dpni_destroy(dflt_mc_io,
1485 dflt_dprc_handle,
1486 MC_CMD_NO_FLAGS,
1487 dflt_dpni->dpni_id);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301488err_create:
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301489err_prepare_cfg:
Prabhakar Kushwahae26e2852015-12-24 15:33:01 +05301490 free(dflt_dpni);
Prabhakar Kushwaha790c1a42017-10-11 08:51:18 +05301491err_calloc:
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301492 return err;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001493}
1494
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301495static int dpni_exit(void)
1496{
1497 int err;
1498
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301499 err = dpni_destroy(dflt_mc_io, dflt_dprc_handle, MC_CMD_NO_FLAGS,
1500 dflt_dpni->dpni_id);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301501 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}
Florinel Iordacheae6d8522019-11-19 10:28:17 +00001517
1518static bool is_dpsparser_supported(void)
1519{
1520 /* dpsparser support was first introduced in MC version: 10.12.0 */
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/* TODO: refactoring needed in the future to allow DPSPARSER object destroy
1596 * Workaround: DO NOT destroy DPSPARSER object because it needs to be available
1597 * on Apply DPL
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 // Read blob header and get size of SPB blob
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 //Invoke MC command to apply SPB blob
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}
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301681
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
Florinel Iordacheae6d8522019-11-19 10:28:17 +00001710 err = dpsparser_init();
1711 if (err < 0) {
1712 printf("dpsparser_init() failed: %d\n", err);
1713 goto err;
1714 }
1715
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301716 return 0;
1717err:
1718 return err;
1719}
1720
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09001721int fsl_mc_ldpaa_exit(struct bd_info *bd)
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301722{
1723 int err = 0;
Yogesh Gaur4a81bbe2017-04-27 10:14:16 +05301724 bool is_dpl_apply_status = false;
Santan Kumar0a6e5ba2017-06-29 11:19:34 +05301725 bool mc_boot_status = false;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301726
Alexander Graf2ebeb442016-11-17 01:02:57 +01001727 if (bd && mc_lazy_dpl_addr && !fsl_mc_ldpaa_exit(NULL)) {
Yogesh Gaur8dadfb42018-01-16 10:08:24 +05301728 err = mc_apply_dpl(mc_lazy_dpl_addr);
1729 if (!err)
1730 fdt_fixup_board_enet(working_fdt);
Alexander Graf2ebeb442016-11-17 01:02:57 +01001731 mc_lazy_dpl_addr = 0;
1732 }
1733
Santan Kumar0a6e5ba2017-06-29 11:19:34 +05301734 if (!get_mc_boot_status())
1735 mc_boot_status = true;
1736
Prabhakar Kushwaha878d3ec2016-03-21 14:19:39 +05301737 /* MC is not loaded intentionally, So return success. */
Santan Kumar0a6e5ba2017-06-29 11:19:34 +05301738 if (bd && !mc_boot_status)
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301739 return 0;
1740
Yogesh Gaur4a81bbe2017-04-27 10:14:16 +05301741 /* If DPL is deployed, set is_dpl_apply_status as TRUE. */
1742 if (!get_dpl_apply_status())
1743 is_dpl_apply_status = true;
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301744
Yogesh Gaur4a81bbe2017-04-27 10:14:16 +05301745 /*
1746 * For case MC is loaded but DPL is not deployed, return success and
1747 * print message on console. Else FDT fix-up code execution hanged.
1748 */
Santan Kumar0a6e5ba2017-06-29 11:19:34 +05301749 if (bd && mc_boot_status && !is_dpl_apply_status) {
Yogesh Gaur4a81bbe2017-04-27 10:14:16 +05301750 printf("fsl-mc: DPL not deployed, DPAA2 ethernet not work\n");
Yogesh Gaur82709e52017-11-28 10:11:14 +05301751 goto mc_obj_cleanup;
Yogesh Gaur4a81bbe2017-04-27 10:14:16 +05301752 }
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301753
Santan Kumar0a6e5ba2017-06-29 11:19:34 +05301754 if (bd && mc_boot_status && is_dpl_apply_status)
1755 return 0;
1756
Yogesh Gaur82709e52017-11-28 10:11:14 +05301757mc_obj_cleanup:
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301758 err = dpbp_exit();
1759 if (err < 0) {
Prabhakar Kushwaha88ba4d62016-01-20 12:04:37 +05301760 printf("dpbp_exit() failed: %d\n", err);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301761 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
Cosmin-Florin Alucheneseiaa280142021-10-07 13:07:44 +03001787static 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
Simon Glassed38aef2020-05-10 11:40:03 -06001854static int do_fsl_mc(struct cmd_tbl *cmdtp, int flag, int argc,
1855 char *const argv[])
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001856{
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301857 int err = 0;
Cosmin-Florin Alucheneseiaa280142021-10-07 13:07:44 +03001858 if (argc < 2)
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301859 goto usage;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001860
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301861 switch (argv[1][0]) {
1862 case 's': {
1863 char sub_cmd;
Prabhakar Kushwaha122bcfd2015-11-09 16:42:07 +05301864 u64 mc_fw_addr, mc_dpc_addr;
1865#ifdef CONFIG_SYS_LS_MC_DRAM_AIOP_IMG_OFFSET
1866 u64 aiop_fw_addr;
1867#endif
Cosmin-Florin Alucheneseiaa280142021-10-07 13:07:44 +03001868 if (argc < 3)
1869 goto usage;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001870
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301871 sub_cmd = argv[2][0];
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301872
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301873 switch (sub_cmd) {
1874 case 'm':
1875 if (argc < 5)
1876 goto usage;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001877
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301878 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);
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301886
1887 if (!mc_init(mc_fw_addr, mc_dpc_addr))
1888 err = mc_init_object();
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301889 break;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001890
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301891#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 }
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001900
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301901 aiop_fw_addr = simple_strtoull(argv[3], NULL,
1902 16);
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001903
York Suncbe8e1c2016-04-04 11:41:26 -07001904 /* if SoC doesn't have AIOP, err = -ENODEV */
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301905 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;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001913
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301914 break;
1915 }
1916 }
Florinel Iordacheae6d8522019-11-19 10:28:17 +00001917 break;
1918
1919 case 'l': {
1920 /* lazyapply */
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 * We will do the actual dpaa exit and dpl apply
1941 * later from announce_and_cleanup().
1942 */
1943 mc_lazy_dpl_addr = mc_dpl_addr;
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301944 break;
Florinel Iordacheae6d8522019-11-19 10:28:17 +00001945 }
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001946
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301947 case 'a': {
Florinel Iordacheae6d8522019-11-19 10:28:17 +00001948 /* apply */
1949 char sub_cmd;
1950 u64 mc_apply_addr;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001951
Florinel Iordacheae6d8522019-11-19 10:28:17 +00001952 if (argc < 4)
1953 goto usage;
1954
1955 sub_cmd = argv[2][0];
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07001956
Florinel Iordacheae6d8522019-11-19 10:28:17 +00001957 switch (sub_cmd) {
1958 case 'd':
1959 case 'D':
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301960 if (get_dpl_apply_status() == 0) {
1961 printf("fsl-mc: DPL already applied\n");
1962 return err;
1963 }
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301964 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 }
Prabhakar Kushwaha316b71c2015-11-04 12:25:59 +05301969
Florinel Iordacheae6d8522019-11-19 10:28:17 +00001970 mc_apply_addr = simple_strtoull(argv[3], NULL, 16);
1971
1972 /* The user wants DPL applied now */
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;
Alexander Graf2ebeb442016-11-17 01:02:57 +01001982 }
Florinel Iordacheae6d8522019-11-19 10:28:17 +00001983 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 /* Apply spb (Soft Parser Blob) */
1992 err = mc_apply_spb(mc_apply_addr);
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05301993 break;
Florinel Iordacheae6d8522019-11-19 10:28:17 +00001994
1995 default:
1996 printf("Invalid option: %s\n", argv[2]);
1997 goto usage;
1998 }
1999 break;
J. German Riveraf4fed4b2015-03-20 19:28:18 -07002000 }
Cosmin-Florin Alucheneseiaa280142021-10-07 13:07:44 +03002001 case 'd':
2002 if (argc > 2)
2003 goto usage;
2004
2005 mc_dump_log();
2006 break;
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05302007 default:
2008 printf("Invalid option: %s\n", argv[1]);
2009 goto usage;
2010 break;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07002011 }
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05302012 return err;
2013 usage:
2014 return CMD_RET_USAGE;
Prabhakar Kushwahacfd9fbf2015-03-19 09:20:45 -07002015}
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05302016
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"
Alexander Graf2ebeb442016-11-17 01:02:57 +01002022 "fsl_mc lazyapply DPL [DPL_addr] - Apply DPL file on exit\n"
Florinel Iordacheae6d8522019-11-19 10:28:17 +00002023 "fsl_mc apply spb [spb_addr] - Apply SPB Soft Parser Blob\n"
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05302024 "fsl_mc start aiop [FW_addr] - Start AIOP\n"
Cosmin-Florin Alucheneseiaa280142021-10-07 13:07:44 +03002025 "fsl_mc dump_log - Dump MC Log\n"
Prabhakar Kushwaha29a63e42015-11-04 12:25:58 +05302026);
Bogdan Purcareata08bc0142017-05-24 16:40:21 +00002027
2028void mc_env_boot(void)
2029{
2030#if defined(CONFIG_FSL_MC_ENET)
2031 char *mc_boot_env_var;
2032 /* The MC may only be initialized in the reset PHY function
2033 * because otherwise U-Boot has not yet set up all the MAC
2034 * address info properly. Without MAC addresses, the MC code
2035 * can not properly initialize the DPC.
2036 */
Simon Glass64b723f2017-08-03 12:22:12 -06002037 mc_boot_env_var = env_get(MC_BOOT_ENV_VAR);
Bogdan Purcareata08bc0142017-05-24 16:40:21 +00002038 if (mc_boot_env_var)
2039 run_command_list(mc_boot_env_var, -1, 0);
2040#endif /* CONFIG_FSL_MC_ENET */
2041}