xref: /rk3399_rockchip-uboot/drivers/net/fsl-mc/mc.c (revision c517771ae745dbba59112b8d311e41d37c0fc032)
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>
11a2a55e51SPrabhakar Kushwaha #include <fsl-mc/fsl_mc_private.h>
127b3bd9a7SJ. German Rivera #include <fsl-mc/fsl_dpmng.h>
13422cb08aSBhupesh Sharma #include <fsl_debug_server.h>
14a2a55e51SPrabhakar Kushwaha #include <fsl-mc/fsl_dprc.h>
15a2a55e51SPrabhakar Kushwaha #include <fsl-mc/fsl_dpio.h>
16a2a55e51SPrabhakar 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;
20a2a55e51SPrabhakar Kushwaha struct fsl_mc_io *dflt_mc_io = NULL;
21a2a55e51SPrabhakar Kushwaha uint16_t dflt_dprc_handle = 0;
22a2a55e51SPrabhakar Kushwaha struct fsl_dpbp_obj *dflt_dpbp = NULL;
23a2a55e51SPrabhakar Kushwaha struct fsl_dpio_obj *dflt_dpio = NULL;
24a2a55e51SPrabhakar 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 
96a2a55e51SPrabhakar Kushwaha int mc_init(void)
977b3bd9a7SJ. German Rivera {
987b3bd9a7SJ. German Rivera 	int error = 0;
997b3bd9a7SJ. German Rivera 	int timeout = 200000;
100a2a55e51SPrabhakar 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 	/*
274a2a55e51SPrabhakar Kushwaha 	 * Initialize the global default MC portal
275a2a55e51SPrabhakar Kushwaha 	 * And check that the MC firmware is responding portal commands:
2767b3bd9a7SJ. German Rivera 	 */
277a2a55e51SPrabhakar Kushwaha 	dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
278a2a55e51SPrabhakar Kushwaha 	if (!dflt_mc_io) {
279a2a55e51SPrabhakar Kushwaha 		printf(" No memory: malloc() failed\n");
280a2a55e51SPrabhakar Kushwaha 		return -ENOMEM;
281a2a55e51SPrabhakar Kushwaha 	}
2827b3bd9a7SJ. German Rivera 
283a2a55e51SPrabhakar Kushwaha 	dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
284a2a55e51SPrabhakar Kushwaha 	debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
285a2a55e51SPrabhakar Kushwaha 	      portal_id, dflt_mc_io->mmio_regs);
286a2a55e51SPrabhakar Kushwaha 
287a2a55e51SPrabhakar 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 }
330a2a55e51SPrabhakar Kushwaha 
331a2a55e51SPrabhakar Kushwaha int dpio_init(struct dprc_obj_desc obj_desc)
332a2a55e51SPrabhakar Kushwaha {
333a2a55e51SPrabhakar Kushwaha 	struct qbman_swp_desc p_des;
334a2a55e51SPrabhakar Kushwaha 	struct dpio_attr attr;
335a2a55e51SPrabhakar Kushwaha 	int err = 0;
336a2a55e51SPrabhakar Kushwaha 
337a2a55e51SPrabhakar Kushwaha 	dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj));
338a2a55e51SPrabhakar Kushwaha 	if (!dflt_dpio) {
339a2a55e51SPrabhakar Kushwaha 		printf(" No memory: malloc() failed\n");
340a2a55e51SPrabhakar Kushwaha 		return -ENOMEM;
341a2a55e51SPrabhakar Kushwaha 	}
342a2a55e51SPrabhakar Kushwaha 
343a2a55e51SPrabhakar Kushwaha 	dflt_dpio->dpio_id = obj_desc.id;
344a2a55e51SPrabhakar Kushwaha 
345a2a55e51SPrabhakar Kushwaha 	err = dpio_open(dflt_mc_io, obj_desc.id, &dflt_dpio_handle);
346a2a55e51SPrabhakar Kushwaha 	if (err) {
347a2a55e51SPrabhakar Kushwaha 		printf("dpio_open() failed\n");
348a2a55e51SPrabhakar Kushwaha 		goto err_open;
349a2a55e51SPrabhakar Kushwaha 	}
350a2a55e51SPrabhakar Kushwaha 
351a2a55e51SPrabhakar Kushwaha 	err = dpio_get_attributes(dflt_mc_io, dflt_dpio_handle, &attr);
352a2a55e51SPrabhakar Kushwaha 	if (err) {
353a2a55e51SPrabhakar Kushwaha 		printf("dpio_get_attributes() failed %d\n", err);
354a2a55e51SPrabhakar Kushwaha 		goto err_get_attr;
355a2a55e51SPrabhakar Kushwaha 	}
356a2a55e51SPrabhakar Kushwaha 
357a2a55e51SPrabhakar Kushwaha 	err = dpio_enable(dflt_mc_io, dflt_dpio_handle);
358a2a55e51SPrabhakar Kushwaha 	if (err) {
359a2a55e51SPrabhakar Kushwaha 		printf("dpio_enable() failed %d\n", err);
360a2a55e51SPrabhakar Kushwaha 		goto err_get_enable;
361a2a55e51SPrabhakar Kushwaha 	}
362a2a55e51SPrabhakar Kushwaha 	debug("ce_paddr=0x%llx, ci_paddr=0x%llx, portalid=%d, prios=%d\n",
363a2a55e51SPrabhakar Kushwaha 	      attr.qbman_portal_ce_paddr,
364a2a55e51SPrabhakar Kushwaha 	      attr.qbman_portal_ci_paddr,
365a2a55e51SPrabhakar Kushwaha 	      attr.qbman_portal_id,
366a2a55e51SPrabhakar Kushwaha 	      attr.num_priorities);
367a2a55e51SPrabhakar Kushwaha 
368a2a55e51SPrabhakar Kushwaha 	p_des.cena_bar = (void *)attr.qbman_portal_ce_paddr;
369a2a55e51SPrabhakar Kushwaha 	p_des.cinh_bar = (void *)attr.qbman_portal_ci_paddr;
370a2a55e51SPrabhakar Kushwaha 
371a2a55e51SPrabhakar Kushwaha 	dflt_dpio->sw_portal = qbman_swp_init(&p_des);
372a2a55e51SPrabhakar Kushwaha 	if (dflt_dpio->sw_portal == NULL) {
373a2a55e51SPrabhakar Kushwaha 		printf("qbman_swp_init() failed\n");
374a2a55e51SPrabhakar Kushwaha 		goto err_get_swp_init;
375a2a55e51SPrabhakar Kushwaha 	}
376a2a55e51SPrabhakar Kushwaha 	return 0;
377a2a55e51SPrabhakar Kushwaha 
378a2a55e51SPrabhakar Kushwaha err_get_swp_init:
379a2a55e51SPrabhakar Kushwaha err_get_enable:
380a2a55e51SPrabhakar Kushwaha 	dpio_disable(dflt_mc_io, dflt_dpio_handle);
381a2a55e51SPrabhakar Kushwaha err_get_attr:
382a2a55e51SPrabhakar Kushwaha 	dpio_close(dflt_mc_io, dflt_dpio_handle);
383a2a55e51SPrabhakar Kushwaha err_open:
384a2a55e51SPrabhakar Kushwaha 	free(dflt_dpio);
385a2a55e51SPrabhakar Kushwaha 	return err;
386a2a55e51SPrabhakar Kushwaha }
387a2a55e51SPrabhakar Kushwaha 
388a2a55e51SPrabhakar Kushwaha int dpbp_init(struct dprc_obj_desc obj_desc)
389a2a55e51SPrabhakar Kushwaha {
390a2a55e51SPrabhakar Kushwaha 	dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj));
391a2a55e51SPrabhakar Kushwaha 	if (!dflt_dpbp) {
392a2a55e51SPrabhakar Kushwaha 		printf(" No memory: malloc() failed\n");
393a2a55e51SPrabhakar Kushwaha 		return -ENOMEM;
394a2a55e51SPrabhakar Kushwaha 	}
395a2a55e51SPrabhakar Kushwaha 	dflt_dpbp->dpbp_attr.id = obj_desc.id;
396a2a55e51SPrabhakar Kushwaha 
397a2a55e51SPrabhakar Kushwaha 	return 0;
398a2a55e51SPrabhakar Kushwaha }
399a2a55e51SPrabhakar Kushwaha 
400*c517771aSPrabhakar Kushwaha int dprc_init_container_obj(struct dprc_obj_desc obj_desc, uint16_t dprc_handle)
401a2a55e51SPrabhakar Kushwaha {
402*c517771aSPrabhakar Kushwaha 	int error = 0, state = 0;
403*c517771aSPrabhakar Kushwaha 	struct dprc_endpoint dpni_endpoint, dpmac_endpoint;
404a2a55e51SPrabhakar Kushwaha 	if (!strcmp(obj_desc.type, "dpbp")) {
405a2a55e51SPrabhakar Kushwaha 		if (!dflt_dpbp) {
406a2a55e51SPrabhakar Kushwaha 			error = dpbp_init(obj_desc);
407a2a55e51SPrabhakar Kushwaha 			if (error < 0)
408a2a55e51SPrabhakar Kushwaha 				printf("dpbp_init failed\n");
409a2a55e51SPrabhakar Kushwaha 		}
410a2a55e51SPrabhakar Kushwaha 	} else if (!strcmp(obj_desc.type, "dpio")) {
411a2a55e51SPrabhakar Kushwaha 		if (!dflt_dpio) {
412a2a55e51SPrabhakar Kushwaha 			error = dpio_init(obj_desc);
413a2a55e51SPrabhakar Kushwaha 			if (error < 0)
414a2a55e51SPrabhakar Kushwaha 				printf("dpio_init failed\n");
415a2a55e51SPrabhakar Kushwaha 		}
416*c517771aSPrabhakar Kushwaha 	} else if (!strcmp(obj_desc.type, "dpni")) {
417*c517771aSPrabhakar Kushwaha 		strcpy(dpni_endpoint.type, obj_desc.type);
418*c517771aSPrabhakar Kushwaha 		dpni_endpoint.id = obj_desc.id;
419*c517771aSPrabhakar Kushwaha 		error = dprc_get_connection(dflt_mc_io, dprc_handle,
420*c517771aSPrabhakar Kushwaha 				     &dpni_endpoint, &dpmac_endpoint, &state);
421*c517771aSPrabhakar Kushwaha 		if (!strcmp(dpmac_endpoint.type, "dpmac"))
422*c517771aSPrabhakar Kushwaha 			error = ldpaa_eth_init(obj_desc);
423*c517771aSPrabhakar Kushwaha 		if (error < 0)
424*c517771aSPrabhakar Kushwaha 			printf("ldpaa_eth_init failed\n");
425a2a55e51SPrabhakar Kushwaha 	}
426a2a55e51SPrabhakar Kushwaha 
427a2a55e51SPrabhakar Kushwaha 	return error;
428a2a55e51SPrabhakar Kushwaha }
429a2a55e51SPrabhakar Kushwaha 
430a2a55e51SPrabhakar Kushwaha int dprc_scan_container_obj(uint16_t dprc_handle, char *obj_type, int i)
431a2a55e51SPrabhakar Kushwaha {
432a2a55e51SPrabhakar Kushwaha 	int error = 0;
433a2a55e51SPrabhakar Kushwaha 	struct dprc_obj_desc obj_desc;
434a2a55e51SPrabhakar Kushwaha 
435a2a55e51SPrabhakar Kushwaha 	memset((void *)&obj_desc, 0x00, sizeof(struct dprc_obj_desc));
436a2a55e51SPrabhakar Kushwaha 
437a2a55e51SPrabhakar Kushwaha 	error = dprc_get_obj(dflt_mc_io, dprc_handle,
438a2a55e51SPrabhakar Kushwaha 			     i, &obj_desc);
439a2a55e51SPrabhakar Kushwaha 	if (error < 0) {
440a2a55e51SPrabhakar Kushwaha 		printf("dprc_get_obj(i=%d) failed: %d\n",
441a2a55e51SPrabhakar Kushwaha 		       i, error);
442a2a55e51SPrabhakar Kushwaha 		return error;
443a2a55e51SPrabhakar Kushwaha 	}
444a2a55e51SPrabhakar Kushwaha 
445a2a55e51SPrabhakar Kushwaha 	if (!strcmp(obj_desc.type, obj_type)) {
446a2a55e51SPrabhakar Kushwaha 		debug("Discovered object: type %s, id %d, req %s\n",
447a2a55e51SPrabhakar Kushwaha 		      obj_desc.type, obj_desc.id, obj_type);
448a2a55e51SPrabhakar Kushwaha 
449*c517771aSPrabhakar Kushwaha 		error = dprc_init_container_obj(obj_desc, dprc_handle);
450a2a55e51SPrabhakar Kushwaha 		if (error < 0) {
451a2a55e51SPrabhakar Kushwaha 			printf("dprc_init_container_obj(i=%d) failed: %d\n",
452a2a55e51SPrabhakar Kushwaha 			       i, error);
453a2a55e51SPrabhakar Kushwaha 			return error;
454a2a55e51SPrabhakar Kushwaha 		}
455a2a55e51SPrabhakar Kushwaha 	}
456a2a55e51SPrabhakar Kushwaha 
457a2a55e51SPrabhakar Kushwaha 	return error;
458a2a55e51SPrabhakar Kushwaha }
459a2a55e51SPrabhakar Kushwaha 
460a2a55e51SPrabhakar Kushwaha int fsl_mc_ldpaa_init(bd_t *bis)
461a2a55e51SPrabhakar Kushwaha {
462a2a55e51SPrabhakar Kushwaha 	int i, error = 0;
463a2a55e51SPrabhakar Kushwaha 	int dprc_opened = 0, container_id;
464a2a55e51SPrabhakar Kushwaha 	int num_child_objects = 0;
465a2a55e51SPrabhakar Kushwaha 
466a2a55e51SPrabhakar Kushwaha 	error = mc_init();
467a2a55e51SPrabhakar Kushwaha 
468a2a55e51SPrabhakar Kushwaha 	error = dprc_get_container_id(dflt_mc_io, &container_id);
469a2a55e51SPrabhakar Kushwaha 	if (error < 0) {
470a2a55e51SPrabhakar Kushwaha 		printf("dprc_get_container_id() failed: %d\n", error);
471a2a55e51SPrabhakar Kushwaha 		goto error;
472a2a55e51SPrabhakar Kushwaha 	}
473a2a55e51SPrabhakar Kushwaha 
474a2a55e51SPrabhakar Kushwaha 	debug("fsl-mc: Container id=0x%x\n", container_id);
475a2a55e51SPrabhakar Kushwaha 
476a2a55e51SPrabhakar Kushwaha 	error = dprc_open(dflt_mc_io, container_id, &dflt_dprc_handle);
477a2a55e51SPrabhakar Kushwaha 	if (error < 0) {
478a2a55e51SPrabhakar Kushwaha 		printf("dprc_open() failed: %d\n", error);
479a2a55e51SPrabhakar Kushwaha 		goto error;
480a2a55e51SPrabhakar Kushwaha 	}
481a2a55e51SPrabhakar Kushwaha 	dprc_opened = true;
482a2a55e51SPrabhakar Kushwaha 
483a2a55e51SPrabhakar Kushwaha 	error = dprc_get_obj_count(dflt_mc_io,
484a2a55e51SPrabhakar Kushwaha 				   dflt_dprc_handle,
485a2a55e51SPrabhakar Kushwaha 				   &num_child_objects);
486a2a55e51SPrabhakar Kushwaha 	if (error < 0) {
487a2a55e51SPrabhakar Kushwaha 		printf("dprc_get_obj_count() failed: %d\n", error);
488a2a55e51SPrabhakar Kushwaha 		goto error;
489a2a55e51SPrabhakar Kushwaha 	}
490a2a55e51SPrabhakar Kushwaha 	debug("Total child in container %d = %d\n", container_id,
491a2a55e51SPrabhakar Kushwaha 	      num_child_objects);
492a2a55e51SPrabhakar Kushwaha 
493a2a55e51SPrabhakar Kushwaha 	if (num_child_objects != 0) {
494a2a55e51SPrabhakar Kushwaha 		/*
495a2a55e51SPrabhakar Kushwaha 		 * Discover objects currently in the DPRC container in the MC:
496a2a55e51SPrabhakar Kushwaha 		 */
497a2a55e51SPrabhakar Kushwaha 		for (i = 0; i < num_child_objects; i++)
498a2a55e51SPrabhakar Kushwaha 			error = dprc_scan_container_obj(dflt_dprc_handle,
499a2a55e51SPrabhakar Kushwaha 							"dpbp", i);
500a2a55e51SPrabhakar Kushwaha 
501a2a55e51SPrabhakar Kushwaha 		for (i = 0; i < num_child_objects; i++)
502a2a55e51SPrabhakar Kushwaha 			error = dprc_scan_container_obj(dflt_dprc_handle,
503a2a55e51SPrabhakar Kushwaha 							"dpio", i);
504a2a55e51SPrabhakar Kushwaha 
505a2a55e51SPrabhakar Kushwaha 		for (i = 0; i < num_child_objects; i++)
506a2a55e51SPrabhakar Kushwaha 			error = dprc_scan_container_obj(dflt_dprc_handle,
507a2a55e51SPrabhakar Kushwaha 							"dpni", i);
508a2a55e51SPrabhakar Kushwaha 	}
509a2a55e51SPrabhakar Kushwaha error:
510a2a55e51SPrabhakar Kushwaha 	if (dprc_opened)
511a2a55e51SPrabhakar Kushwaha 		dprc_close(dflt_mc_io, dflt_dprc_handle);
512a2a55e51SPrabhakar Kushwaha 
513a2a55e51SPrabhakar Kushwaha 	return error;
514a2a55e51SPrabhakar Kushwaha }
515a2a55e51SPrabhakar Kushwaha 
516a2a55e51SPrabhakar Kushwaha void fsl_mc_ldpaa_exit(bd_t *bis)
517a2a55e51SPrabhakar Kushwaha {
518a2a55e51SPrabhakar Kushwaha 	int err;
519a2a55e51SPrabhakar Kushwaha 
520a2a55e51SPrabhakar Kushwaha 
521a2a55e51SPrabhakar Kushwaha 	err = dpio_disable(dflt_mc_io, dflt_dpio_handle);
522a2a55e51SPrabhakar Kushwaha 	if (err < 0) {
523a2a55e51SPrabhakar Kushwaha 		printf("dpio_disable() failed: %d\n", err);
524a2a55e51SPrabhakar Kushwaha 		return;
525a2a55e51SPrabhakar Kushwaha 	}
526a2a55e51SPrabhakar Kushwaha 	err = dpio_reset(dflt_mc_io, dflt_dpio_handle);
527a2a55e51SPrabhakar Kushwaha 	if (err < 0) {
528a2a55e51SPrabhakar Kushwaha 		printf("dpio_reset() failed: %d\n", err);
529a2a55e51SPrabhakar Kushwaha 		return;
530a2a55e51SPrabhakar Kushwaha 	}
531a2a55e51SPrabhakar Kushwaha 	err = dpio_close(dflt_mc_io, dflt_dpio_handle);
532a2a55e51SPrabhakar Kushwaha 	if (err < 0) {
533a2a55e51SPrabhakar Kushwaha 		printf("dpio_close() failed: %d\n", err);
534a2a55e51SPrabhakar Kushwaha 		return;
535a2a55e51SPrabhakar Kushwaha 	}
536a2a55e51SPrabhakar Kushwaha 
537a2a55e51SPrabhakar Kushwaha 	free(dflt_dpio);
538a2a55e51SPrabhakar Kushwaha 	free(dflt_dpbp);
539a2a55e51SPrabhakar Kushwaha 	free(dflt_mc_io);
540a2a55e51SPrabhakar Kushwaha }
541