xref: /rk3399_rockchip-uboot/drivers/net/fsl-mc/mc.c (revision a2a55e518f81900ab1538656e5df8d2759ccb1fb)
17b3bd9a7SJ. German Rivera /*
27b3bd9a7SJ. German Rivera  * Copyright (C) 2014 Freescale Semiconductor
37b3bd9a7SJ. German Rivera  *
47b3bd9a7SJ. German Rivera  * SPDX-License-Identifier:	GPL-2.0+
57b3bd9a7SJ. German Rivera  */
67b3bd9a7SJ. German Rivera 
77b3bd9a7SJ. German Rivera #include <errno.h>
87b3bd9a7SJ. German Rivera #include <asm/io.h>
97b3bd9a7SJ. German Rivera #include <fsl-mc/fsl_mc.h>
107b3bd9a7SJ. German Rivera #include <fsl-mc/fsl_mc_sys.h>
11*a2a55e51SPrabhakar Kushwaha #include <fsl-mc/fsl_mc_private.h>
127b3bd9a7SJ. German Rivera #include <fsl-mc/fsl_dpmng.h>
13422cb08aSBhupesh Sharma #include <fsl_debug_server.h>
14*a2a55e51SPrabhakar Kushwaha #include <fsl-mc/fsl_dprc.h>
15*a2a55e51SPrabhakar Kushwaha #include <fsl-mc/fsl_dpio.h>
16*a2a55e51SPrabhakar Kushwaha #include <fsl-mc/fsl_qbman_portal.h>
177b3bd9a7SJ. German Rivera 
187b3bd9a7SJ. German Rivera DECLARE_GLOBAL_DATA_PTR;
197b3bd9a7SJ. German Rivera static int mc_boot_status;
20*a2a55e51SPrabhakar Kushwaha struct fsl_mc_io *dflt_mc_io = NULL;
21*a2a55e51SPrabhakar Kushwaha uint16_t dflt_dprc_handle = 0;
22*a2a55e51SPrabhakar Kushwaha struct fsl_dpbp_obj *dflt_dpbp = NULL;
23*a2a55e51SPrabhakar Kushwaha struct fsl_dpio_obj *dflt_dpio = NULL;
24*a2a55e51SPrabhakar Kushwaha uint16_t dflt_dpio_handle = NULL;
257b3bd9a7SJ. German Rivera 
267b3bd9a7SJ. German Rivera /**
277b3bd9a7SJ. German Rivera  * Copying MC firmware or DPL image to DDR
287b3bd9a7SJ. German Rivera  */
297b3bd9a7SJ. German Rivera static int mc_copy_image(const char *title,
307b3bd9a7SJ. German Rivera 			 u64 image_addr, u32 image_size, u64 mc_ram_addr)
317b3bd9a7SJ. German Rivera {
327b3bd9a7SJ. German Rivera 	debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
337b3bd9a7SJ. German Rivera 	memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
347b3bd9a7SJ. German Rivera 	return 0;
357b3bd9a7SJ. German Rivera }
367b3bd9a7SJ. German Rivera 
377b3bd9a7SJ. German Rivera /**
387b3bd9a7SJ. German Rivera  * MC firmware FIT image parser checks if the image is in FIT
397b3bd9a7SJ. German Rivera  * format, verifies integrity of the image and calculates
407b3bd9a7SJ. German Rivera  * raw image address and size values.
417b3bd9a7SJ. German Rivera  * Returns 0 on success and a negative errno on error.
427b3bd9a7SJ. German Rivera  * task fail.
437b3bd9a7SJ. German Rivera  **/
447b3bd9a7SJ. German Rivera int parse_mc_firmware_fit_image(const void **raw_image_addr,
457b3bd9a7SJ. German Rivera 				size_t *raw_image_size)
467b3bd9a7SJ. German Rivera {
477b3bd9a7SJ. German Rivera 	int format;
487b3bd9a7SJ. German Rivera 	void *fit_hdr;
497b3bd9a7SJ. German Rivera 	int node_offset;
507b3bd9a7SJ. German Rivera 	const void *data;
517b3bd9a7SJ. German Rivera 	size_t size;
527b3bd9a7SJ. German Rivera 	const char *uname = "firmware";
537b3bd9a7SJ. German Rivera 
547b3bd9a7SJ. German Rivera 	/* Check if the image is in NOR flash */
557b3bd9a7SJ. German Rivera #ifdef CONFIG_SYS_LS_MC_FW_IN_NOR
567b3bd9a7SJ. German Rivera 	fit_hdr = (void *)CONFIG_SYS_LS_MC_FW_ADDR;
577b3bd9a7SJ. German Rivera #else
587b3bd9a7SJ. German Rivera #error "No CONFIG_SYS_LS_MC_FW_IN_xxx defined"
597b3bd9a7SJ. German Rivera #endif
607b3bd9a7SJ. German Rivera 
617b3bd9a7SJ. German Rivera 	/* Check if Image is in FIT format */
627b3bd9a7SJ. German Rivera 	format = genimg_get_format(fit_hdr);
637b3bd9a7SJ. German Rivera 
647b3bd9a7SJ. German Rivera 	if (format != IMAGE_FORMAT_FIT) {
657b3bd9a7SJ. German Rivera 		printf("fsl-mc: ERROR: Bad firmware image (not a FIT image)\n");
667b3bd9a7SJ. German Rivera 		return -EINVAL;
677b3bd9a7SJ. German Rivera 	}
687b3bd9a7SJ. German Rivera 
697b3bd9a7SJ. German Rivera 	if (!fit_check_format(fit_hdr)) {
707b3bd9a7SJ. German Rivera 		printf("fsl-mc: ERROR: Bad firmware image (bad FIT header)\n");
717b3bd9a7SJ. German Rivera 		return -EINVAL;
727b3bd9a7SJ. German Rivera 	}
737b3bd9a7SJ. German Rivera 
747b3bd9a7SJ. German Rivera 	node_offset = fit_image_get_node(fit_hdr, uname);
757b3bd9a7SJ. German Rivera 
767b3bd9a7SJ. German Rivera 	if (node_offset < 0) {
777b3bd9a7SJ. German Rivera 		printf("fsl-mc: ERROR: Bad firmware image (missing subimage)\n");
787b3bd9a7SJ. German Rivera 		return -ENOENT;
797b3bd9a7SJ. German Rivera 	}
807b3bd9a7SJ. German Rivera 
817b3bd9a7SJ. German Rivera 	/* Verify MC firmware image */
827b3bd9a7SJ. German Rivera 	if (!(fit_image_verify(fit_hdr, node_offset))) {
837b3bd9a7SJ. German Rivera 		printf("fsl-mc: ERROR: Bad firmware image (bad CRC)\n");
847b3bd9a7SJ. German Rivera 		return -EINVAL;
857b3bd9a7SJ. German Rivera 	}
867b3bd9a7SJ. German Rivera 
877b3bd9a7SJ. German Rivera 	/* Get address and size of raw image */
887b3bd9a7SJ. German Rivera 	fit_image_get_data(fit_hdr, node_offset, &data, &size);
897b3bd9a7SJ. German Rivera 
907b3bd9a7SJ. German Rivera 	*raw_image_addr = data;
917b3bd9a7SJ. German Rivera 	*raw_image_size = size;
927b3bd9a7SJ. German Rivera 
937b3bd9a7SJ. German Rivera 	return 0;
947b3bd9a7SJ. German Rivera }
957b3bd9a7SJ. German Rivera 
96*a2a55e51SPrabhakar Kushwaha int mc_init(void)
977b3bd9a7SJ. German Rivera {
987b3bd9a7SJ. German Rivera 	int error = 0;
997b3bd9a7SJ. German Rivera 	int timeout = 200000;
100*a2a55e51SPrabhakar Kushwaha 	int portal_id = 0;
1017b3bd9a7SJ. German Rivera 	struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
1027b3bd9a7SJ. German Rivera 	u64 mc_ram_addr;
1037b3bd9a7SJ. German Rivera 	u64 mc_dpl_offset;
1047b3bd9a7SJ. German Rivera 	u32 reg_gsr;
1057b3bd9a7SJ. German Rivera 	u32 mc_fw_boot_status;
1067b3bd9a7SJ. German Rivera 	void *dpl_fdt_hdr;
1077b3bd9a7SJ. German Rivera 	int dpl_size;
1087b3bd9a7SJ. German Rivera 	const void *raw_image_addr;
1097b3bd9a7SJ. German Rivera 	size_t raw_image_size = 0;
1107b3bd9a7SJ. German Rivera 	struct mc_version mc_ver_info;
1117b3bd9a7SJ. German Rivera 
1127b3bd9a7SJ. German Rivera 	/*
1137b3bd9a7SJ. German Rivera 	 * The MC private DRAM block was already carved at the end of DRAM
1147b3bd9a7SJ. German Rivera 	 * by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE:
1157b3bd9a7SJ. German Rivera 	 */
1167b3bd9a7SJ. German Rivera 	if (gd->bd->bi_dram[1].start) {
1177b3bd9a7SJ. German Rivera 		mc_ram_addr =
1187b3bd9a7SJ. German Rivera 			gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size;
1197b3bd9a7SJ. German Rivera 	} else {
1207b3bd9a7SJ. German Rivera 		mc_ram_addr =
1217b3bd9a7SJ. German Rivera 			gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
1227b3bd9a7SJ. German Rivera 	}
1237b3bd9a7SJ. German Rivera 
124422cb08aSBhupesh Sharma #ifdef CONFIG_FSL_DEBUG_SERVER
125422cb08aSBhupesh Sharma 		mc_ram_addr -= debug_server_get_dram_block_size();
126422cb08aSBhupesh Sharma #endif
1277b3bd9a7SJ. German Rivera 	/*
1287b3bd9a7SJ. German Rivera 	 * Management Complex cores should be held at reset out of POR.
1297b3bd9a7SJ. German Rivera 	 * U-boot should be the first software to touch MC. To be safe,
1307b3bd9a7SJ. German Rivera 	 * we reset all cores again by setting GCR1 to 0. It doesn't do
1317b3bd9a7SJ. German Rivera 	 * anything if they are held at reset. After we setup the firmware
1327b3bd9a7SJ. German Rivera 	 * we kick off MC by deasserting the reset bit for core 0, and
1337b3bd9a7SJ. German Rivera 	 * deasserting the reset bits for Command Portal Managers.
1347b3bd9a7SJ. German Rivera 	 * The stop bits are not touched here. They are used to stop the
1357b3bd9a7SJ. German Rivera 	 * cores when they are active. Setting stop bits doesn't stop the
1367b3bd9a7SJ. German Rivera 	 * cores from fetching instructions when they are released from
1377b3bd9a7SJ. German Rivera 	 * reset.
1387b3bd9a7SJ. German Rivera 	 */
1397b3bd9a7SJ. German Rivera 	out_le32(&mc_ccsr_regs->reg_gcr1, 0);
1407b3bd9a7SJ. German Rivera 	dmb();
1417b3bd9a7SJ. German Rivera 
1427b3bd9a7SJ. German Rivera 	error = parse_mc_firmware_fit_image(&raw_image_addr, &raw_image_size);
1437b3bd9a7SJ. German Rivera 	if (error != 0)
1447b3bd9a7SJ. German Rivera 		goto out;
1457b3bd9a7SJ. German Rivera 	/*
1467b3bd9a7SJ. German Rivera 	 * Load the MC FW at the beginning of the MC private DRAM block:
1477b3bd9a7SJ. German Rivera 	 */
1487b3bd9a7SJ. German Rivera 	mc_copy_image("MC Firmware",
1497b3bd9a7SJ. German Rivera 		      (u64)raw_image_addr, raw_image_size, mc_ram_addr);
1507b3bd9a7SJ. German Rivera 
1517b3bd9a7SJ. German Rivera 	/*
1527b3bd9a7SJ. German Rivera 	 * Get address and size of the DPL blob stored in flash:
1537b3bd9a7SJ. German Rivera 	 */
1547b3bd9a7SJ. German Rivera #ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR
1557b3bd9a7SJ. German Rivera 	dpl_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR;
1567b3bd9a7SJ. German Rivera #else
1577b3bd9a7SJ. German Rivera #error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined"
1587b3bd9a7SJ. German Rivera #endif
1597b3bd9a7SJ. German Rivera 
1607b3bd9a7SJ. German Rivera 	error = fdt_check_header(dpl_fdt_hdr);
1617b3bd9a7SJ. German Rivera 	if (error != 0) {
1627b3bd9a7SJ. German Rivera 		printf("fsl-mc: ERROR: Bad DPL image (bad header)\n");
1637b3bd9a7SJ. German Rivera 		goto out;
1647b3bd9a7SJ. German Rivera 	}
1657b3bd9a7SJ. German Rivera 
1667b3bd9a7SJ. German Rivera 	dpl_size = fdt_totalsize(dpl_fdt_hdr);
1677b3bd9a7SJ. German Rivera 	if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
1687b3bd9a7SJ. German Rivera 		printf("fsl-mc: ERROR: Bad DPL image (too large: %d)\n",
1697b3bd9a7SJ. German Rivera 		       dpl_size);
1707b3bd9a7SJ. German Rivera 		error = -EINVAL;
1717b3bd9a7SJ. German Rivera 		goto out;
1727b3bd9a7SJ. German Rivera 	}
1737b3bd9a7SJ. German Rivera 
1747b3bd9a7SJ. German Rivera 	/*
1757b3bd9a7SJ. German Rivera 	 * Calculate offset in the MC private DRAM block at which the MC DPL
1767b3bd9a7SJ. German Rivera 	 * blob is to be placed:
1777b3bd9a7SJ. German Rivera 	 */
1787b3bd9a7SJ. German Rivera #ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
1797b3bd9a7SJ. German Rivera 	BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
1807b3bd9a7SJ. German Rivera 		     CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
1817b3bd9a7SJ. German Rivera 
1827b3bd9a7SJ. German Rivera 	mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
1837b3bd9a7SJ. German Rivera #else
1847b3bd9a7SJ. German Rivera 	mc_dpl_offset = mc_get_dram_block_size() -
1857b3bd9a7SJ. German Rivera 			roundup(CONFIG_SYS_LS_MC_DPL_MAX_LENGTH, 4096);
1867b3bd9a7SJ. German Rivera 
1877b3bd9a7SJ. German Rivera 	if ((mc_dpl_offset & 0x3) != 0 || mc_dpl_offset > 0xffffffff) {
1887b3bd9a7SJ. German Rivera 		printf("%s: Invalid MC DPL offset: %llu\n",
1897b3bd9a7SJ. German Rivera 		       __func__, mc_dpl_offset);
1907b3bd9a7SJ. German Rivera 		error = -EINVAL;
1917b3bd9a7SJ. German Rivera 		goto out;
1927b3bd9a7SJ. German Rivera 	}
1937b3bd9a7SJ. German Rivera #endif
1947b3bd9a7SJ. German Rivera 
1957b3bd9a7SJ. German Rivera 	/*
1967b3bd9a7SJ. German Rivera 	 * Load the MC DPL blob at the far end of the MC private DRAM block:
1977b3bd9a7SJ. German Rivera 	 *
1987b3bd9a7SJ. German Rivera 	 * TODO: Should we place the DPL at a different location to match
1997b3bd9a7SJ. German Rivera 	 * assumptions of MC firmware about its memory layout?
2007b3bd9a7SJ. German Rivera 	 */
2017b3bd9a7SJ. German Rivera 	mc_copy_image("MC DPL blob",
2027b3bd9a7SJ. German Rivera 		      (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
2037b3bd9a7SJ. German Rivera 
2047b3bd9a7SJ. German Rivera 	debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
2057b3bd9a7SJ. German Rivera 
2067b3bd9a7SJ. German Rivera 	/*
2077b3bd9a7SJ. German Rivera 	 * Tell MC where the MC Firmware image was loaded in DDR:
2087b3bd9a7SJ. German Rivera 	 */
2097b3bd9a7SJ. German Rivera 	out_le32(&mc_ccsr_regs->reg_mcfbalr, (u32)mc_ram_addr);
2107b3bd9a7SJ. German Rivera 	out_le32(&mc_ccsr_regs->reg_mcfbahr, (u32)((u64)mc_ram_addr >> 32));
2117b3bd9a7SJ. German Rivera 	out_le32(&mc_ccsr_regs->reg_mcfapr, MCFAPR_BYPASS_ICID_MASK);
2127b3bd9a7SJ. German Rivera 
2137b3bd9a7SJ. German Rivera 	/*
2147b3bd9a7SJ. German Rivera 	 * Tell MC where the DPL blob was loaded in DDR, by indicating
2157b3bd9a7SJ. German Rivera 	 * its offset relative to the beginning of the DDR block
2167b3bd9a7SJ. German Rivera 	 * allocated to the MC firmware. The MC firmware is responsible
2177b3bd9a7SJ. German Rivera 	 * for checking that there is no overlap between the DPL blob
2187b3bd9a7SJ. German Rivera 	 * and the runtime heap and stack of the MC firmware itself.
2197b3bd9a7SJ. German Rivera 	 *
2207b3bd9a7SJ. German Rivera 	 * NOTE: bits [31:2] of this offset need to be stored in bits [29:0] of
2217b3bd9a7SJ. German Rivera 	 * the GSR MC CCSR register. So, this offset is assumed to be 4-byte
2227b3bd9a7SJ. German Rivera 	 * aligned.
2237b3bd9a7SJ. German Rivera 	 * Care must be taken not to write 1s into bits 31 and 30 of the GSR in
2247b3bd9a7SJ. German Rivera 	 * this case as the SoC COP or PIC will be signaled.
2257b3bd9a7SJ. German Rivera 	 */
2267b3bd9a7SJ. German Rivera 	out_le32(&mc_ccsr_regs->reg_gsr, (u32)(mc_dpl_offset >> 2));
2277b3bd9a7SJ. German Rivera 
2287b3bd9a7SJ. German Rivera 	printf("\nfsl-mc: Booting Management Complex ...\n");
2297b3bd9a7SJ. German Rivera 
2307b3bd9a7SJ. German Rivera 	/*
2317b3bd9a7SJ. German Rivera 	 * Deassert reset and release MC core 0 to run
2327b3bd9a7SJ. German Rivera 	 */
2337b3bd9a7SJ. German Rivera 	out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
2347b3bd9a7SJ. German Rivera 	dmb();
2357b3bd9a7SJ. German Rivera 	debug("Polling mc_ccsr_regs->reg_gsr ...\n");
2367b3bd9a7SJ. German Rivera 
2377b3bd9a7SJ. German Rivera 	for (;;) {
2387b3bd9a7SJ. German Rivera 		reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
2397b3bd9a7SJ. German Rivera 		mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
2407b3bd9a7SJ. German Rivera 		if (mc_fw_boot_status & 0x1)
2417b3bd9a7SJ. German Rivera 			break;
2427b3bd9a7SJ. German Rivera 
2437b3bd9a7SJ. German Rivera 		udelay(1000);	/* throttle polling */
2447b3bd9a7SJ. German Rivera 		if (timeout-- <= 0)
2457b3bd9a7SJ. German Rivera 			break;
2467b3bd9a7SJ. German Rivera 	}
2477b3bd9a7SJ. German Rivera 
2487b3bd9a7SJ. German Rivera 	if (timeout <= 0) {
2497b3bd9a7SJ. German Rivera 		printf("fsl-mc: timeout booting management complex firmware\n");
2507b3bd9a7SJ. German Rivera 
2517b3bd9a7SJ. German Rivera 		/* TODO: Get an error status from an MC CCSR register */
2527b3bd9a7SJ. German Rivera 		error = -ETIMEDOUT;
2537b3bd9a7SJ. German Rivera 		goto out;
2547b3bd9a7SJ. German Rivera 	}
2557b3bd9a7SJ. German Rivera 
2567b3bd9a7SJ. German Rivera 	if (mc_fw_boot_status != 0x1) {
2577b3bd9a7SJ. German Rivera 		/*
2587b3bd9a7SJ. German Rivera 		 * TODO: Identify critical errors from the GSR register's FS
2597b3bd9a7SJ. German Rivera 		 * field and for those errors, set error to -ENODEV or other
2607b3bd9a7SJ. German Rivera 		 * appropriate errno, so that the status property is set to
2617b3bd9a7SJ. German Rivera 		 * failure in the fsl,dprc device tree node.
2627b3bd9a7SJ. German Rivera 		 */
2637b3bd9a7SJ. German Rivera 		printf("fsl-mc: WARNING: Firmware booted with error (GSR: %#x)\n",
2647b3bd9a7SJ. German Rivera 		       reg_gsr);
2657b3bd9a7SJ. German Rivera 	}
2667b3bd9a7SJ. German Rivera 
2677b3bd9a7SJ. German Rivera 	/*
2687b3bd9a7SJ. German Rivera 	 * TODO: need to obtain the portal_id for the root container from the
2697b3bd9a7SJ. German Rivera 	 * DPL
2707b3bd9a7SJ. German Rivera 	 */
2717b3bd9a7SJ. German Rivera 	portal_id = 0;
2727b3bd9a7SJ. German Rivera 
2737b3bd9a7SJ. German Rivera 	/*
274*a2a55e51SPrabhakar Kushwaha 	 * Initialize the global default MC portal
275*a2a55e51SPrabhakar Kushwaha 	 * And check that the MC firmware is responding portal commands:
2767b3bd9a7SJ. German Rivera 	 */
277*a2a55e51SPrabhakar Kushwaha 	dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
278*a2a55e51SPrabhakar Kushwaha 	if (!dflt_mc_io) {
279*a2a55e51SPrabhakar Kushwaha 		printf(" No memory: malloc() failed\n");
280*a2a55e51SPrabhakar Kushwaha 		return -ENOMEM;
281*a2a55e51SPrabhakar Kushwaha 	}
2827b3bd9a7SJ. German Rivera 
283*a2a55e51SPrabhakar Kushwaha 	dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
284*a2a55e51SPrabhakar Kushwaha 	debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
285*a2a55e51SPrabhakar Kushwaha 	      portal_id, dflt_mc_io->mmio_regs);
286*a2a55e51SPrabhakar Kushwaha 
287*a2a55e51SPrabhakar Kushwaha 	error = mc_get_version(dflt_mc_io, &mc_ver_info);
2887b3bd9a7SJ. German Rivera 	if (error != 0) {
2897b3bd9a7SJ. German Rivera 		printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n",
2907b3bd9a7SJ. German Rivera 		       error);
2917b3bd9a7SJ. German Rivera 		goto out;
2927b3bd9a7SJ. German Rivera 	}
2937b3bd9a7SJ. German Rivera 
2947b3bd9a7SJ. German Rivera 	if (MC_VER_MAJOR != mc_ver_info.major)
2957b3bd9a7SJ. German Rivera 		printf("fsl-mc: ERROR: Firmware major version mismatch (found: %d, expected: %d)\n",
2967b3bd9a7SJ. German Rivera 		       mc_ver_info.major, MC_VER_MAJOR);
2977b3bd9a7SJ. German Rivera 
2987b3bd9a7SJ. German Rivera 	if (MC_VER_MINOR != mc_ver_info.minor)
2997b3bd9a7SJ. German Rivera 		printf("fsl-mc: WARNING: Firmware minor version mismatch (found: %d, expected: %d)\n",
3007b3bd9a7SJ. German Rivera 		       mc_ver_info.minor, MC_VER_MINOR);
3017b3bd9a7SJ. German Rivera 
3027b3bd9a7SJ. German Rivera 	printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n",
3037b3bd9a7SJ. German Rivera 	       mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision,
3047b3bd9a7SJ. German Rivera 	       mc_fw_boot_status);
3057b3bd9a7SJ. German Rivera out:
3067b3bd9a7SJ. German Rivera 	if (error != 0)
3077b3bd9a7SJ. German Rivera 		mc_boot_status = -error;
3087b3bd9a7SJ. German Rivera 	else
3097b3bd9a7SJ. German Rivera 		mc_boot_status = 0;
3107b3bd9a7SJ. German Rivera 
3117b3bd9a7SJ. German Rivera 	return error;
3127b3bd9a7SJ. German Rivera }
3137b3bd9a7SJ. German Rivera 
3147b3bd9a7SJ. German Rivera int get_mc_boot_status(void)
3157b3bd9a7SJ. German Rivera {
3167b3bd9a7SJ. German Rivera 	return mc_boot_status;
3177b3bd9a7SJ. German Rivera }
3187b3bd9a7SJ. German Rivera 
3197b3bd9a7SJ. German Rivera /**
3207b3bd9a7SJ. German Rivera  * Return the actual size of the MC private DRAM block.
3217b3bd9a7SJ. German Rivera  *
3227b3bd9a7SJ. German Rivera  * NOTE: For now this function always returns the minimum required size,
3237b3bd9a7SJ. German Rivera  * However, in the future, the actual size may be obtained from an environment
3247b3bd9a7SJ. German Rivera  * variable.
3257b3bd9a7SJ. German Rivera  */
3267b3bd9a7SJ. German Rivera unsigned long mc_get_dram_block_size(void)
3277b3bd9a7SJ. German Rivera {
3287b3bd9a7SJ. German Rivera 	return CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
3297b3bd9a7SJ. German Rivera }
330*a2a55e51SPrabhakar Kushwaha 
331*a2a55e51SPrabhakar Kushwaha int dpio_init(struct dprc_obj_desc obj_desc)
332*a2a55e51SPrabhakar Kushwaha {
333*a2a55e51SPrabhakar Kushwaha 	struct qbman_swp_desc p_des;
334*a2a55e51SPrabhakar Kushwaha 	struct dpio_attr attr;
335*a2a55e51SPrabhakar Kushwaha 	int err = 0;
336*a2a55e51SPrabhakar Kushwaha 
337*a2a55e51SPrabhakar Kushwaha 	dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj));
338*a2a55e51SPrabhakar Kushwaha 	if (!dflt_dpio) {
339*a2a55e51SPrabhakar Kushwaha 		printf(" No memory: malloc() failed\n");
340*a2a55e51SPrabhakar Kushwaha 		return -ENOMEM;
341*a2a55e51SPrabhakar Kushwaha 	}
342*a2a55e51SPrabhakar Kushwaha 
343*a2a55e51SPrabhakar Kushwaha 	dflt_dpio->dpio_id = obj_desc.id;
344*a2a55e51SPrabhakar Kushwaha 
345*a2a55e51SPrabhakar Kushwaha 	err = dpio_open(dflt_mc_io, obj_desc.id, &dflt_dpio_handle);
346*a2a55e51SPrabhakar Kushwaha 	if (err) {
347*a2a55e51SPrabhakar Kushwaha 		printf("dpio_open() failed\n");
348*a2a55e51SPrabhakar Kushwaha 		goto err_open;
349*a2a55e51SPrabhakar Kushwaha 	}
350*a2a55e51SPrabhakar Kushwaha 
351*a2a55e51SPrabhakar Kushwaha 	err = dpio_get_attributes(dflt_mc_io, dflt_dpio_handle, &attr);
352*a2a55e51SPrabhakar Kushwaha 	if (err) {
353*a2a55e51SPrabhakar Kushwaha 		printf("dpio_get_attributes() failed %d\n", err);
354*a2a55e51SPrabhakar Kushwaha 		goto err_get_attr;
355*a2a55e51SPrabhakar Kushwaha 	}
356*a2a55e51SPrabhakar Kushwaha 
357*a2a55e51SPrabhakar Kushwaha 	err = dpio_enable(dflt_mc_io, dflt_dpio_handle);
358*a2a55e51SPrabhakar Kushwaha 	if (err) {
359*a2a55e51SPrabhakar Kushwaha 		printf("dpio_enable() failed %d\n", err);
360*a2a55e51SPrabhakar Kushwaha 		goto err_get_enable;
361*a2a55e51SPrabhakar Kushwaha 	}
362*a2a55e51SPrabhakar Kushwaha 	debug("ce_paddr=0x%llx, ci_paddr=0x%llx, portalid=%d, prios=%d\n",
363*a2a55e51SPrabhakar Kushwaha 	      attr.qbman_portal_ce_paddr,
364*a2a55e51SPrabhakar Kushwaha 	      attr.qbman_portal_ci_paddr,
365*a2a55e51SPrabhakar Kushwaha 	      attr.qbman_portal_id,
366*a2a55e51SPrabhakar Kushwaha 	      attr.num_priorities);
367*a2a55e51SPrabhakar Kushwaha 
368*a2a55e51SPrabhakar Kushwaha 	p_des.cena_bar = (void *)attr.qbman_portal_ce_paddr;
369*a2a55e51SPrabhakar Kushwaha 	p_des.cinh_bar = (void *)attr.qbman_portal_ci_paddr;
370*a2a55e51SPrabhakar Kushwaha 
371*a2a55e51SPrabhakar Kushwaha 	dflt_dpio->sw_portal = qbman_swp_init(&p_des);
372*a2a55e51SPrabhakar Kushwaha 	if (dflt_dpio->sw_portal == NULL) {
373*a2a55e51SPrabhakar Kushwaha 		printf("qbman_swp_init() failed\n");
374*a2a55e51SPrabhakar Kushwaha 		goto err_get_swp_init;
375*a2a55e51SPrabhakar Kushwaha 	}
376*a2a55e51SPrabhakar Kushwaha 	return 0;
377*a2a55e51SPrabhakar Kushwaha 
378*a2a55e51SPrabhakar Kushwaha err_get_swp_init:
379*a2a55e51SPrabhakar Kushwaha err_get_enable:
380*a2a55e51SPrabhakar Kushwaha 	dpio_disable(dflt_mc_io, dflt_dpio_handle);
381*a2a55e51SPrabhakar Kushwaha err_get_attr:
382*a2a55e51SPrabhakar Kushwaha 	dpio_close(dflt_mc_io, dflt_dpio_handle);
383*a2a55e51SPrabhakar Kushwaha err_open:
384*a2a55e51SPrabhakar Kushwaha 	free(dflt_dpio);
385*a2a55e51SPrabhakar Kushwaha 	return err;
386*a2a55e51SPrabhakar Kushwaha }
387*a2a55e51SPrabhakar Kushwaha 
388*a2a55e51SPrabhakar Kushwaha int dpbp_init(struct dprc_obj_desc obj_desc)
389*a2a55e51SPrabhakar Kushwaha {
390*a2a55e51SPrabhakar Kushwaha 	dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj));
391*a2a55e51SPrabhakar Kushwaha 	if (!dflt_dpbp) {
392*a2a55e51SPrabhakar Kushwaha 		printf(" No memory: malloc() failed\n");
393*a2a55e51SPrabhakar Kushwaha 		return -ENOMEM;
394*a2a55e51SPrabhakar Kushwaha 	}
395*a2a55e51SPrabhakar Kushwaha 	dflt_dpbp->dpbp_attr.id = obj_desc.id;
396*a2a55e51SPrabhakar Kushwaha 
397*a2a55e51SPrabhakar Kushwaha 	return 0;
398*a2a55e51SPrabhakar Kushwaha }
399*a2a55e51SPrabhakar Kushwaha 
400*a2a55e51SPrabhakar Kushwaha int dprc_init_container_obj(struct dprc_obj_desc obj_desc)
401*a2a55e51SPrabhakar Kushwaha {
402*a2a55e51SPrabhakar Kushwaha 	int error = 0;
403*a2a55e51SPrabhakar Kushwaha 	if (!strcmp(obj_desc.type, "dpbp")) {
404*a2a55e51SPrabhakar Kushwaha 		if (!dflt_dpbp) {
405*a2a55e51SPrabhakar Kushwaha 			error = dpbp_init(obj_desc);
406*a2a55e51SPrabhakar Kushwaha 			if (error < 0)
407*a2a55e51SPrabhakar Kushwaha 				printf("dpbp_init failed\n");
408*a2a55e51SPrabhakar Kushwaha 		}
409*a2a55e51SPrabhakar Kushwaha 	} else if (!strcmp(obj_desc.type, "dpio")) {
410*a2a55e51SPrabhakar Kushwaha 		if (!dflt_dpio) {
411*a2a55e51SPrabhakar Kushwaha 			error = dpio_init(obj_desc);
412*a2a55e51SPrabhakar Kushwaha 			if (error < 0)
413*a2a55e51SPrabhakar Kushwaha 				printf("dpio_init failed\n");
414*a2a55e51SPrabhakar Kushwaha 		}
415*a2a55e51SPrabhakar Kushwaha 	}
416*a2a55e51SPrabhakar Kushwaha 
417*a2a55e51SPrabhakar Kushwaha 	return error;
418*a2a55e51SPrabhakar Kushwaha }
419*a2a55e51SPrabhakar Kushwaha 
420*a2a55e51SPrabhakar Kushwaha int dprc_scan_container_obj(uint16_t dprc_handle, char *obj_type, int i)
421*a2a55e51SPrabhakar Kushwaha {
422*a2a55e51SPrabhakar Kushwaha 	int error = 0;
423*a2a55e51SPrabhakar Kushwaha 	struct dprc_obj_desc obj_desc;
424*a2a55e51SPrabhakar Kushwaha 
425*a2a55e51SPrabhakar Kushwaha 	memset((void *)&obj_desc, 0x00, sizeof(struct dprc_obj_desc));
426*a2a55e51SPrabhakar Kushwaha 
427*a2a55e51SPrabhakar Kushwaha 	error = dprc_get_obj(dflt_mc_io, dprc_handle,
428*a2a55e51SPrabhakar Kushwaha 			     i, &obj_desc);
429*a2a55e51SPrabhakar Kushwaha 	if (error < 0) {
430*a2a55e51SPrabhakar Kushwaha 		printf("dprc_get_obj(i=%d) failed: %d\n",
431*a2a55e51SPrabhakar Kushwaha 		       i, error);
432*a2a55e51SPrabhakar Kushwaha 		return error;
433*a2a55e51SPrabhakar Kushwaha 	}
434*a2a55e51SPrabhakar Kushwaha 
435*a2a55e51SPrabhakar Kushwaha 	if (!strcmp(obj_desc.type, obj_type)) {
436*a2a55e51SPrabhakar Kushwaha 		debug("Discovered object: type %s, id %d, req %s\n",
437*a2a55e51SPrabhakar Kushwaha 		      obj_desc.type, obj_desc.id, obj_type);
438*a2a55e51SPrabhakar Kushwaha 
439*a2a55e51SPrabhakar Kushwaha 		error = dprc_init_container_obj(obj_desc);
440*a2a55e51SPrabhakar Kushwaha 		if (error < 0) {
441*a2a55e51SPrabhakar Kushwaha 			printf("dprc_init_container_obj(i=%d) failed: %d\n",
442*a2a55e51SPrabhakar Kushwaha 			       i, error);
443*a2a55e51SPrabhakar Kushwaha 			return error;
444*a2a55e51SPrabhakar Kushwaha 		}
445*a2a55e51SPrabhakar Kushwaha 	}
446*a2a55e51SPrabhakar Kushwaha 
447*a2a55e51SPrabhakar Kushwaha 	return error;
448*a2a55e51SPrabhakar Kushwaha }
449*a2a55e51SPrabhakar Kushwaha 
450*a2a55e51SPrabhakar Kushwaha int fsl_mc_ldpaa_init(bd_t *bis)
451*a2a55e51SPrabhakar Kushwaha {
452*a2a55e51SPrabhakar Kushwaha 	int i, error = 0;
453*a2a55e51SPrabhakar Kushwaha 	int dprc_opened = 0, container_id;
454*a2a55e51SPrabhakar Kushwaha 	int num_child_objects = 0;
455*a2a55e51SPrabhakar Kushwaha 
456*a2a55e51SPrabhakar Kushwaha 	error = mc_init();
457*a2a55e51SPrabhakar Kushwaha 
458*a2a55e51SPrabhakar Kushwaha 	error = dprc_get_container_id(dflt_mc_io, &container_id);
459*a2a55e51SPrabhakar Kushwaha 	if (error < 0) {
460*a2a55e51SPrabhakar Kushwaha 		printf("dprc_get_container_id() failed: %d\n", error);
461*a2a55e51SPrabhakar Kushwaha 		goto error;
462*a2a55e51SPrabhakar Kushwaha 	}
463*a2a55e51SPrabhakar Kushwaha 
464*a2a55e51SPrabhakar Kushwaha 	debug("fsl-mc: Container id=0x%x\n", container_id);
465*a2a55e51SPrabhakar Kushwaha 
466*a2a55e51SPrabhakar Kushwaha 	error = dprc_open(dflt_mc_io, container_id, &dflt_dprc_handle);
467*a2a55e51SPrabhakar Kushwaha 	if (error < 0) {
468*a2a55e51SPrabhakar Kushwaha 		printf("dprc_open() failed: %d\n", error);
469*a2a55e51SPrabhakar Kushwaha 		goto error;
470*a2a55e51SPrabhakar Kushwaha 	}
471*a2a55e51SPrabhakar Kushwaha 	dprc_opened = true;
472*a2a55e51SPrabhakar Kushwaha 
473*a2a55e51SPrabhakar Kushwaha 	error = dprc_get_obj_count(dflt_mc_io,
474*a2a55e51SPrabhakar Kushwaha 				   dflt_dprc_handle,
475*a2a55e51SPrabhakar Kushwaha 				   &num_child_objects);
476*a2a55e51SPrabhakar Kushwaha 	if (error < 0) {
477*a2a55e51SPrabhakar Kushwaha 		printf("dprc_get_obj_count() failed: %d\n", error);
478*a2a55e51SPrabhakar Kushwaha 		goto error;
479*a2a55e51SPrabhakar Kushwaha 	}
480*a2a55e51SPrabhakar Kushwaha 	debug("Total child in container %d = %d\n", container_id,
481*a2a55e51SPrabhakar Kushwaha 	      num_child_objects);
482*a2a55e51SPrabhakar Kushwaha 
483*a2a55e51SPrabhakar Kushwaha 	if (num_child_objects != 0) {
484*a2a55e51SPrabhakar Kushwaha 		/*
485*a2a55e51SPrabhakar Kushwaha 		 * Discover objects currently in the DPRC container in the MC:
486*a2a55e51SPrabhakar Kushwaha 		 */
487*a2a55e51SPrabhakar Kushwaha 		for (i = 0; i < num_child_objects; i++)
488*a2a55e51SPrabhakar Kushwaha 			error = dprc_scan_container_obj(dflt_dprc_handle,
489*a2a55e51SPrabhakar Kushwaha 							"dpbp", i);
490*a2a55e51SPrabhakar Kushwaha 
491*a2a55e51SPrabhakar Kushwaha 		for (i = 0; i < num_child_objects; i++)
492*a2a55e51SPrabhakar Kushwaha 			error = dprc_scan_container_obj(dflt_dprc_handle,
493*a2a55e51SPrabhakar Kushwaha 							"dpio", i);
494*a2a55e51SPrabhakar Kushwaha 
495*a2a55e51SPrabhakar Kushwaha 		for (i = 0; i < num_child_objects; i++)
496*a2a55e51SPrabhakar Kushwaha 			error = dprc_scan_container_obj(dflt_dprc_handle,
497*a2a55e51SPrabhakar Kushwaha 							"dpni", i);
498*a2a55e51SPrabhakar Kushwaha 	}
499*a2a55e51SPrabhakar Kushwaha error:
500*a2a55e51SPrabhakar Kushwaha 	if (dprc_opened)
501*a2a55e51SPrabhakar Kushwaha 		dprc_close(dflt_mc_io, dflt_dprc_handle);
502*a2a55e51SPrabhakar Kushwaha 
503*a2a55e51SPrabhakar Kushwaha 	return error;
504*a2a55e51SPrabhakar Kushwaha }
505*a2a55e51SPrabhakar Kushwaha 
506*a2a55e51SPrabhakar Kushwaha void fsl_mc_ldpaa_exit(bd_t *bis)
507*a2a55e51SPrabhakar Kushwaha {
508*a2a55e51SPrabhakar Kushwaha 	int err;
509*a2a55e51SPrabhakar Kushwaha 
510*a2a55e51SPrabhakar Kushwaha 
511*a2a55e51SPrabhakar Kushwaha 	err = dpio_disable(dflt_mc_io, dflt_dpio_handle);
512*a2a55e51SPrabhakar Kushwaha 	if (err < 0) {
513*a2a55e51SPrabhakar Kushwaha 		printf("dpio_disable() failed: %d\n", err);
514*a2a55e51SPrabhakar Kushwaha 		return;
515*a2a55e51SPrabhakar Kushwaha 	}
516*a2a55e51SPrabhakar Kushwaha 	err = dpio_reset(dflt_mc_io, dflt_dpio_handle);
517*a2a55e51SPrabhakar Kushwaha 	if (err < 0) {
518*a2a55e51SPrabhakar Kushwaha 		printf("dpio_reset() failed: %d\n", err);
519*a2a55e51SPrabhakar Kushwaha 		return;
520*a2a55e51SPrabhakar Kushwaha 	}
521*a2a55e51SPrabhakar Kushwaha 	err = dpio_close(dflt_mc_io, dflt_dpio_handle);
522*a2a55e51SPrabhakar Kushwaha 	if (err < 0) {
523*a2a55e51SPrabhakar Kushwaha 		printf("dpio_close() failed: %d\n", err);
524*a2a55e51SPrabhakar Kushwaha 		return;
525*a2a55e51SPrabhakar Kushwaha 	}
526*a2a55e51SPrabhakar Kushwaha 
527*a2a55e51SPrabhakar Kushwaha 	free(dflt_dpio);
528*a2a55e51SPrabhakar Kushwaha 	free(dflt_dpbp);
529*a2a55e51SPrabhakar Kushwaha 	free(dflt_mc_io);
530*a2a55e51SPrabhakar Kushwaha }
531