[U-Boot] [Patch v2 4/5] armv8/fsl-lsch3: Add support to load and start MC Firmware

York Sun yorksun at freescale.com
Wed Mar 19 22:02:24 CET 2014


From: "J. German Rivera" <German.Rivera at freescale.com>

Adding supoort to load and start the Layerscape Management Complex (MC)
firmware. First, the MC GCR register is set to 0 to reset all cores. MC
firmware and DPL images are copied from their location in NOR flash to
DDR. MC registers are updated with the location of these images.
Deasserting the reset bit of MC GCR register releases core 0 to run.
Core 1 will be released by MC firmware. Stop bits are not touched for
this step. U-boot waits for MC until it boots up.

Signed-off-by: J. German Rivera <German.Rivera at freescale.com>
Signed-off-by: York Sun <yorksun at freescale.com>
---
 README                             |   27 ++++++++
 arch/arm/cpu/armv8/fsl-lsch3/cpu.c |   11 +++
 drivers/net/Makefile               |    1 +
 drivers/net/fsl_mc/Makefile        |    9 +++
 drivers/net/fsl_mc/mc.c            |  132 ++++++++++++++++++++++++++++++++++++
 include/fsl_mc.h                   |   59 ++++++++++++++++
 6 files changed, 239 insertions(+)
 create mode 100644 drivers/net/fsl_mc/Makefile
 create mode 100644 drivers/net/fsl_mc/mc.c
 create mode 100644 include/fsl_mc.h

diff --git a/README b/README
index 216f0c7..2f6532e 100644
--- a/README
+++ b/README
@@ -4520,6 +4520,33 @@ within that device.
 	window->master inbound window->master LAW->the ucode address in
 	master's memory space.
 
+Freescale Layerscape Management Complex Firmware Support:
+---------------------------------------------------------
+The Freescale Layerscape Management Complex (MC) supports the loading of
+"firmware".
+This firmware often needs to be loaded during U-Boot booting, so macros
+are used to identify the storage device (NOR flash, SPI, etc) and the address
+within that device.
+
+- CONFIG_FSL_MC_ENET
+	Enable the MC driver for Layerscape SoCs.
+
+- CONFIG_SYS_LS_MC_FW_ADDR
+	The address in the storage device where the firmware is located.  The
+	meaning of this address depends on which CONFIG_SYS_LS_MC_FW_IN_xxx macro
+	is also specified.
+
+- CONFIG_SYS_LS_MC_FW_LENGTH
+	The maximum possible size of the firmware.  The firmware binary format
+	has a field that specifies the actual size of the firmware, but it
+	might not be possible to read any part of the firmware unless some
+	local storage is allocated to hold the entire firmware first.
+
+- CONFIG_SYS_LS_MC_FW_IN_NOR
+	Specifies that MC firmware is located in NOR flash, mapped as
+	normal addressable memory via the LBC. CONFIG_SYS_LS_MC_FW_ADDR is the
+	virtual address in NOR flash.
+
 Building the Software:
 ======================
 
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
index 69c78a9..f976235 100644
--- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
@@ -12,6 +12,7 @@
 #include <asm/arch-fsl-lsch3/immap_lsch3.h>
 #include "cpu.h"
 #include "speed.h"
+#include <fsl_mc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -463,3 +464,13 @@ int print_cpuinfo(void)
 	return 0;
 }
 #endif
+
+int cpu_eth_init(bd_t *bis)
+{
+	int error = 0;
+
+#ifdef CONFIG_FSL_MC_ENET
+	error = mc_init(bis);
+#endif
+	return error;
+}
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 7f9ce90..184133a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -63,3 +63,4 @@ obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
 obj-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \
 		xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o
 obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o
+obj-$(CONFIG_FSL_MC_ENET) += fsl_mc/
diff --git a/drivers/net/fsl_mc/Makefile b/drivers/net/fsl_mc/Makefile
new file mode 100644
index 0000000..c3e6690
--- /dev/null
+++ b/drivers/net/fsl_mc/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright 2014 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+# Layerscape MC driver
+obj-y += mc.o
+
diff --git a/drivers/net/fsl_mc/mc.c b/drivers/net/fsl_mc/mc.c
new file mode 100644
index 0000000..fe729c5
--- /dev/null
+++ b/drivers/net/fsl_mc/mc.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <errno.h>
+#include <asm/io.h>
+#include <fsl_mc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * Upload MC firmware or DPL image from NOR flash to DDR
+ */
+static int mc_upload_nor_image(const char *title,
+		    u64 image_addr, u32 image_size, u64 mc_ram_addr)
+{
+	debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
+	memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
+	return 0;
+}
+
+int mc_init(bd_t *bis)
+{
+	int error = 0;
+	int timeout = 200000;
+	struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
+	u64 mc_ram_addr;
+	u32 dpl_offset;
+
+	BUILD_BUG_ON(CONFIG_SYS_LS_MC_FW_LENGTH % 4 != 0);
+
+	if (gd->bd->bi_dram[1].start) {
+		mc_ram_addr =
+			gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size;
+	} else {
+		mc_ram_addr =
+			gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
+	}
+
+	/*
+	 * Management Complex cores should be held at reset out of POR.
+	 * U-boot should be the first software to touch MC. To be safe,
+	 * we reset all cores again by setting GCR1 to 0. It doesn't do
+	 * anything if they are held at reset. After we setup the firmware
+	 * we kick off MC by deasserting the reset bit for core 0, and
+	 * deasserting the reset bits for Command Portal Managers.
+	 * The stop bits are not touched here. They are used to stop the
+	 * cores when they are active. Setting stop bits doesn't stop the
+	 * cores from fetching instructions when they are released from
+	 * reset.
+	 */
+	out_le32(&mc_ccsr_regs->reg_gcr1, 0);
+	dmb();
+
+	/*TODO: Need to verify here the integrity of firmware image */
+
+#ifdef CONFIG_SYS_LS_MC_FW_IN_NOR
+	mc_upload_nor_image(
+		"MC Firmware",
+		CONFIG_SYS_LS_MC_FW_ADDR,
+		CONFIG_SYS_LS_MC_FW_LENGTH,
+		mc_ram_addr);
+#else
+#	error "No CONFIG_SYS_LS_MC_FW_IN_xxx defined"
+#endif
+
+	/*
+	 * Load the DPL blob right after the MC firmware in DDR:
+	 */
+#ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR
+	mc_upload_nor_image(
+		"MC DPL blob",
+		CONFIG_SYS_LS_MC_DPL_ADDR,
+		CONFIG_SYS_LS_MC_DPL_LENGTH,
+		mc_ram_addr + CONFIG_SYS_LS_MC_FW_LENGTH);
+#else
+#   error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined"
+#endif
+
+	debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
+
+	/*
+	 * Tell MC where the MC Firmware image was loaded in DDR:
+	 */
+	out_le32(&mc_ccsr_regs->reg_mcfbalr, (u32)mc_ram_addr);
+	out_le32(&mc_ccsr_regs->reg_mcfbahr, (u32)((u64)mc_ram_addr >> 32));
+	out_le32(&mc_ccsr_regs->reg_mcfapr, MCFAPR_BYPASS_ICID_MASK);
+
+	/*
+	 * Tell MC where the DPL blob was loaded in DDR, by indicating
+	 * its offset relative to the beginning of the DDR block
+	 * allocated to the MC firmware.
+	 *
+	 * NOTE: bits [31:2] of this offset need to be stored in bits [29:0] of
+	 * the GSR MC CCSR register. So, this offset is assumed to be 4-byte
+	 * aligned.
+	 * Care must be taken not to write 1s into bits 31 and 30 of the GSR in
+	 * this case as the SoC COP or PIC will be signaled.
+	 */
+	BUILD_BUG_ON((u64)CONFIG_SYS_LS_MC_FW_LENGTH > 0xFFFFFFFFULL);
+	dpl_offset = CONFIG_SYS_LS_MC_FW_LENGTH;
+	BUG_ON((dpl_offset & 0x3) != 0);
+	out_le32(&mc_ccsr_regs->reg_gsr, dpl_offset >> 2);
+
+	/*
+	 * Deassert reset and release MC core 0 to run
+	 */
+	out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
+	dmb();
+	debug("Polling mc_ccsr_regs->reg_gsr ...\n");
+
+	while ((in_le32(&mc_ccsr_regs->reg_gsr) & GSR_FS_MASK) != 0x1) {
+		udelay(1000);	/* throttle polling */
+		if (timeout-- <= 0)
+			break;
+	}
+
+	if (timeout <= 0) {
+		printf("%s: timeout booting management complex firmware\n",
+		       __func__);
+
+		/* TODO: Get an error status from an MC CCSR register */
+		error = -ETIMEDOUT;
+		goto out;
+	}
+
+	printf("Management complex booted\n");
+out:
+	return error;
+}
+
diff --git a/include/fsl_mc.h b/include/fsl_mc.h
new file mode 100644
index 0000000..eceb705
--- /dev/null
+++ b/include/fsl_mc.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __FSL_MC_H__
+#define __FSL_MC_H__
+
+#include <common.h>
+
+#define MC_CCSR_BASE_ADDR \
+	((struct mc_ccsr_registers __iomem *)0x8340000)
+
+#define BIT(x)			(1 << (x))
+#define GCR1_P1_STOP		BIT(31)
+#define GCR1_P2_STOP		BIT(30)
+#define GCR1_P1_DE_RST		BIT(23)
+#define GCR1_P2_DE_RST		BIT(22)
+#define GCR1_M1_DE_RST		BIT(15)
+#define GCR1_M2_DE_RST		BIT(14)
+#define GCR1_M_ALL_DE_RST	(GCR1_M1_DE_RST | GCR1_M2_DE_RST)
+#define GSR_FS_MASK		0xffff
+#define MCFAPR_PL_MASK		(0x1 << 18)
+#define MCFAPR_BMT_MASK		(0x1 << 17)
+#define MCFAPR_BYPASS_ICID_MASK	\
+	(MCFAPR_PL_MASK | MCFAPR_BMT_MASK)
+
+#define SOC_MC_PORTALS_BASE_ADDR    ((void __iomem *)0x00080C000000)
+#define SOC_MC_PORTAL_STRIDE	    0x10000
+
+#define SOC_MC_PORTAL_ADDR(_portal_id) \
+	((void __iomem *)((uintptr_t)SOC_MC_PORTALS_BASE_ADDR + \
+	 (_portal_id) * SOC_MC_PORTAL_STRIDE))
+
+struct mc_ccsr_registers {
+	u32 reg_gcr1;
+	u32 reserved1;
+	u32 reg_gsr;
+	u32 reserved2;
+	u32 reg_sicbalr;
+	u32 reg_sicbahr;
+	u32 reg_sicapr;
+	u32 reserved3;
+	u32 reg_mcfbalr;
+	u32 reg_mcfbahr;
+	u32 reg_mcfapr;
+	u32 reserved4[0x2f1];
+	u32 reg_psr;
+	u32 reserved5;
+	u32 reg_brr[2];
+	u32 reserved6[0x80];
+	u32 reg_error[];
+};
+
+int mc_init(bd_t *bis);
+
+#endif
+
-- 
1.7.9.5




More information about the U-Boot mailing list