[U-Boot] [PATCH 1/8] armv8/fsl-lsch3: Add Freescale Debug Server driver

York Sun yorksun at freescale.com
Thu Mar 19 17:20:43 CET 2015


From: Bhupesh Sharma <bhupesh.sharma at freescale.com>

The Debug Server driver is responsible for loading the Debug
server FW on the Service Processor (Cortex-A5 core) on LS2085A like
SoCs and then polling for the successful initialization of the same.
TOP MEM HIDE is adjusted to ensure the space required by Debug Server
FW is accounted for. MC uses the DDR area which is calculated as:

MC DDR region start = Top of DDR - area reserved by Debug Server FW

Signed-off-by: Bhupesh Sharma <bhupesh.sharma at freescale.com>
---
 arch/arm/cpu/armv8/fsl-lsch3/cpu.c           |    2 +-
 arch/arm/include/asm/arch-fsl-lsch3/config.h |   10 +-
 board/freescale/ls2085a/ls2085a.c            |   29 +++
 drivers/misc/Makefile                        |    1 +
 drivers/misc/fsl_debug_server.c              |  246 ++++++++++++++++++++++++++
 drivers/net/fsl-mc/mc.c                      |    4 +
 include/configs/ls2085a_common.h             |   20 ++-
 include/fsl-mc/fsl_mc.h                      |    1 +
 include/fsl_debug_server.h                   |   32 ++++
 9 files changed, 338 insertions(+), 7 deletions(-)
 create mode 100644 drivers/misc/fsl_debug_server.c
 create mode 100644 include/fsl_debug_server.h

diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
index 4997487..618fbc2 100644
--- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
@@ -10,6 +10,7 @@
 #include <asm/armv8/mmu.h>
 #include <asm/io.h>
 #include <asm/arch-fsl-lsch3/immap_lsch3.h>
+#include <fsl_debug_server.h>
 #include <fsl-mc/fsl_mc.h>
 #include "cpu.h"
 #include "mp.h"
@@ -384,7 +385,6 @@ int cpu_eth_init(bd_t *bis)
 	return error;
 }
 
-
 int arch_early_init_r(void)
 {
 	int rv;
diff --git a/arch/arm/include/asm/arch-fsl-lsch3/config.h b/arch/arm/include/asm/arch-fsl-lsch3/config.h
index b140c1f..59d10bf 100644
--- a/arch/arm/include/asm/arch-fsl-lsch3/config.h
+++ b/arch/arm/include/asm/arch-fsl-lsch3/config.h
@@ -30,6 +30,15 @@
 #define CONFIG_SYS_FSL_PMU_CLTBENR		(CONFIG_SYS_FSL_PMU_ADDR + \
 						 0x18A0)
 
+/* SP (Cortex-A5) related */
+#define CONFIG_SYS_FSL_SP_ADDR			(CONFIG_SYS_IMMR + 0x00F00000)
+#define CONFIG_SYS_FSL_SP_VSG_GIC_ADDR		(CONFIG_SYS_FSL_SP_ADDR)
+#define CONFIG_SYS_FSL_SP_VSG_GIC_VIGR1		(CONFIG_SYS_FSL_SP_ADDR)
+#define CONFIG_SYS_FSL_SP_VSG_GIC_VIGR2		\
+					(CONFIG_SYS_FSL_SP_ADDR + 0x0008)
+#define CONFIG_SYS_FSL_SP_LOOPBACK_DUART	\
+					(CONFIG_SYS_FSL_SP_ADDR + 0x1000)
+
 #define CONFIG_SYS_FSL_DCSR_DDR_ADDR		0x70012c000ULL
 #define CONFIG_SYS_FSL_DCSR_DDR2_ADDR		0x70012d000ULL
 #define CONFIG_SYS_FSL_DCSR_DDR3_ADDR		0x700132000ULL
@@ -88,7 +97,6 @@
 #define CONFIG_MAX_MEM_MAPPED		CONFIG_SYS_LS2_DDR_BLOCK1_SIZE
 #define CONFIG_SYS_FSL_DDR_VER		FSL_DDR_VER_5_0
 
-
 /* IFC */
 #define CONFIG_SYS_FSL_IFC_LE
 
diff --git a/board/freescale/ls2085a/ls2085a.c b/board/freescale/ls2085a/ls2085a.c
index 519d61c..a16c2c8 100644
--- a/board/freescale/ls2085a/ls2085a.c
+++ b/board/freescale/ls2085a/ls2085a.c
@@ -12,6 +12,7 @@
 #include <asm/io.h>
 #include <fdt_support.h>
 #include <libfdt.h>
+#include <fsl_debug_server.h>
 #include <fsl-mc/fsl_mc.h>
 #include <environment.h>
 
@@ -79,6 +80,34 @@ void reset_cpu(ulong addr)
 {
 }
 
+#if defined(CONFIG_ARCH_MISC_INIT)
+int arch_misc_init(void)
+{
+#ifdef CONFIG_FSL_DEBUG_SERVER
+	debug_server_init();
+#endif
+
+	return 0;
+}
+#endif
+
+unsigned long get_dram_size_to_hide(void)
+{
+	unsigned long dram_to_hide = 0;
+
+/* Carve the Debug Server private DRAM block from the end of DRAM */
+#ifdef CONFIG_FSL_DEBUG_SERVER
+	dram_to_hide += debug_server_get_dram_block_size();
+#endif
+
+/* Carve the MC private DRAM block from the end of DRAM */
+#ifdef CONFIG_FSL_MC_ENET
+	dram_to_hide += mc_get_dram_block_size();
+#endif
+
+	return dram_to_hide;
+}
+
 int board_eth_init(bd_t *bis)
 {
 	int error = 0;
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 6028cd4..3dd76eb 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o
 obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
 obj-$(CONFIG_CROS_EC_SANDBOX) += cros_ec_sandbox.o
 obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
+obj-$(CONFIG_FSL_DEBUG_SERVER) += fsl_debug_server.o
 obj-$(CONFIG_FSL_IIM) += fsl_iim.o
 obj-$(CONFIG_GPIO_LED) += gpio_led.o
 obj-$(CONFIG_I2C_EEPROM) += i2c_eeprom.o
diff --git a/drivers/misc/fsl_debug_server.c b/drivers/misc/fsl_debug_server.c
new file mode 100644
index 0000000..e080fe6
--- /dev/null
+++ b/drivers/misc/fsl_debug_server.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/arch-fsl-lsch3/immap_lsch3.h>
+
+#include <fsl_debug_server.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+static int debug_server_ver_info_maj, debug_server_ver_info_min;
+
+/**
+ * Copying Debug Server firmware to DDR
+ */
+static int debug_server_copy_image(const char *title, u64 image_addr,
+				   u32 image_size, u64 debug_server_ram_addr)
+{
+	debug("%s copied to address %p\n", title,
+	      (void *)debug_server_ram_addr);
+	memcpy((void *)debug_server_ram_addr, (void *)image_addr, image_size);
+
+	return 0;
+}
+
+/**
+ * Debug Server FIT image parser checks if the image is in FIT
+ * format, verifies integrity of the image and calculates
+ * raw image address and size values.
+ *
+ * Returns 0 if success and -1 if any of the above mentioned
+ * task fail.
+ **/
+int debug_server_parse_firmware_fit_image(const void **raw_image_addr,
+					  size_t *raw_image_size)
+{
+	int format;
+	void *fit_hdr;
+	int node_offset;
+	const void *data;
+	size_t size;
+	const char *uname = "firmware";
+	char *desc;
+	char *debug_server_ver_info;
+	char *debug_server_ver_info_major, *debug_server_ver_info_minor;
+
+	/* Check if the image is in NOR flash */
+#ifdef CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR
+	fit_hdr = (void *)CONFIG_SYS_DEBUG_SERVER_FW_ADDR;
+#else
+#error "CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR not defined"
+#endif
+
+	/* Check if Image is in FIT format */
+	format = genimg_get_format(fit_hdr);
+	if (format != IMAGE_FORMAT_FIT) {
+		printf("Error! Not a FIT image\n");
+		goto out_error;
+	}
+
+	if (!fit_check_format(fit_hdr)) {
+		printf("Error! Bad FIT image format\n");
+		goto out_error;
+	}
+
+	node_offset = fit_image_get_node(fit_hdr, uname);
+	if (node_offset < 0) {
+		printf("Error! Can not find %s subimage\n", uname);
+		goto out_error;
+	}
+
+	/* Verify Debug Server firmware image */
+	if (!fit_image_verify(fit_hdr, node_offset)) {
+		printf("Error! Bad Debug Server firmware hash");
+		goto out_error;
+	}
+
+	if (fit_get_desc(fit_hdr, node_offset, &desc) < 0) {
+		printf("Error! Failed to get Debug Server fw description");
+		goto out_error;
+	}
+
+	debug_server_ver_info = strstr(desc, "Version");
+	debug_server_ver_info_major = strtok(debug_server_ver_info, ".");
+	debug_server_ver_info_minor = strtok(NULL, ".");
+
+	debug_server_ver_info_maj =
+			simple_strtoul(debug_server_ver_info_major, NULL, 10);
+	debug_server_ver_info_min =
+			simple_strtoul(debug_server_ver_info_minor, NULL, 10);
+
+	/* Debug server version checking */
+	if ((debug_server_ver_info_maj < DEBUG_SERVER_VER_MAJOR) ||
+	    (debug_server_ver_info_min < DEBUG_SERVER_VER_MINOR)) {
+		printf("Debug server FW mismatches the min version required\n");
+		printf("Expected:%d.%d, Got %d.%d\n",
+		       DEBUG_SERVER_VER_MAJOR, DEBUG_SERVER_VER_MINOR,
+		       debug_server_ver_info_maj,
+		       debug_server_ver_info_min);
+		goto out_error;
+	}
+
+	/* Get address and size of raw image */
+	fit_image_get_data(fit_hdr, node_offset, &data, &size);
+
+	*raw_image_addr = data;
+	*raw_image_size = size;
+
+	return 0;
+
+out_error:
+	return -1;
+}
+
+/**
+ * Return the actual size of the Debug Server private DRAM block.
+ *
+ * NOTE: For now this function always returns the minimum required size,
+ * However, in the future, the actual size may be obtained from an environment
+ * variable.
+ */
+unsigned long debug_server_get_dram_block_size(void)
+{
+	return CONFIG_SYS_DEBUG_SERVER_DRAM_BLOCK_MIN_SIZE;
+}
+
+int debug_server_init(void)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	int error, timeout = CONFIG_SYS_DEBUG_SERVER_TIMEOUT;
+	int debug_server_boot_status;
+	u64 debug_server_ram_addr, debug_server_ram_size;
+	const void *raw_image_addr;
+	size_t raw_image_size = 0;
+
+	debug("debug_server_init called\n");
+	/*
+	 * The Debug Server private DRAM block was already carved at the end of
+	 * DRAM by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE:
+	 */
+	debug_server_ram_size = debug_server_get_dram_block_size();
+	if (gd->bd->bi_dram[1].start)
+		debug_server_ram_addr =
+			gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size;
+	else
+		debug_server_ram_addr =
+			gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
+
+	error = debug_server_parse_firmware_fit_image(&raw_image_addr,
+							&raw_image_size);
+	if (error != 0)
+		goto out;
+
+	debug("debug server (ram addr = 0x%llx, ram size = 0x%llx)\n",
+	      debug_server_ram_addr, debug_server_ram_size);
+	/*
+	 * Load the Debug Server FW at the beginning of the Debug Server
+	 * private DRAM block:
+	 */
+	debug_server_copy_image("Debug Server Firmware",
+				(u64)raw_image_addr, raw_image_size,
+				debug_server_ram_addr);
+
+	/* flush dcache */
+	flush_dcache_range((unsigned long)debug_server_ram_addr,
+			   (unsigned long)debug_server_ram_addr +
+			   (unsigned long)debug_server_ram_size);
+
+	/*
+	 * Tell SP that the Debug Server FW is about to be launched. Before that
+	 * populate the following:
+	 * 1. Write the size allocated to SP Memory region into Bits {31:16} of
+	 *    SCRATCHRW5.
+	 * 2. Write the start address of the SP memory regions into
+	 *    SCRATCHRW5 (Bits {15:0}, contain most significant bits, Bits
+	 *    {47:32} of the SP Memory Region physical start address
+	 *    (SoC address)) and SCRATCHRW6 (Bits {31:0}).
+	 * 3. To know the Debug Server FW boot status, set bit 0 of SCRATCHRW11
+	 *    to 1. The Debug Server sets this to 0 to indicate a
+	 *    successul boot.
+	 * 4. Wakeup SP by writing 0x1F to VSG GIC reg VIGR2.
+	 */
+
+	/* 512 MB */
+	out_le32(&gur->scratchrw[5 - 1],
+		 (u32)((u64)debug_server_ram_addr >> 32) | (0x000D << 16));
+	out_le32(&gur->scratchrw[6 - 1],
+		 ((u32)debug_server_ram_addr) & 0xFFFFFFFF);
+
+	out_le32(&gur->scratchrw[11 - 1], DEBUG_SERVER_INIT_STATUS);
+	/* Allow the changes to reflect in GUR block */
+	mb();
+
+	/*
+	 * Program VGIC to raise an interrupt to SP
+	 */
+	out_le32(CONFIG_SYS_FSL_SP_VSG_GIC_VIGR2, 0x1F);
+	/* Allow the changes to reflect in VIGR2 */
+	mb();
+
+	dmb();
+	debug("Polling for Debug server to launch ...\n");
+
+	while (1) {
+		debug_server_boot_status = in_le32(&gur->scratchrw[11 - 1]);
+		if (!(debug_server_boot_status & DEBUG_SERVER_INIT_STATUS_MASK))
+			break;
+
+		udelay(1);	/* throttle polling */
+		if (timeout-- <= 0)
+			break;
+	}
+
+	if (timeout <= 0) {
+		printf("Debug Server FW timed out (boot status: 0x%x)\n",
+		       debug_server_boot_status);
+		error = -ETIMEDOUT;
+		goto out;
+	}
+
+	if (debug_server_boot_status & DEBUG_SERVER_INIT_STATUS_MASK) {
+		printf("Debug server FW error'ed out (boot status: 0x%x)\n",
+		       debug_server_boot_status);
+		error = -ENODEV;
+		goto out;
+	}
+
+	printf("Debug server booted\n");
+	printf("Detected firmware %d.%d, (boot status: 0x0%x)\n",
+	       debug_server_ver_info_maj, debug_server_ver_info_min,
+	       debug_server_boot_status);
+
+out:
+	if (error != 0)
+		debug_server_boot_status = -error;
+	else
+		debug_server_boot_status = 0;
+
+	return debug_server_boot_status;
+}
+
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c
index 74b0085..76581cb 100644
--- a/drivers/net/fsl-mc/mc.c
+++ b/drivers/net/fsl-mc/mc.c
@@ -9,6 +9,7 @@
 #include <fsl-mc/fsl_mc.h>
 #include <fsl-mc/fsl_mc_sys.h>
 #include <fsl-mc/fsl_dpmng.h>
+#include <fsl_debug_server.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 static int mc_boot_status;
@@ -112,6 +113,9 @@ int mc_init(bd_t *bis)
 			gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
 	}
 
+#ifdef CONFIG_FSL_DEBUG_SERVER
+		mc_ram_addr -= debug_server_get_dram_block_size();
+#endif
 	/*
 	 * Management Complex cores should be held at reset out of POR.
 	 * U-boot should be the first software to touch MC. To be safe,
diff --git a/include/configs/ls2085a_common.h b/include/configs/ls2085a_common.h
index f80efed..c70ba70 100644
--- a/include/configs/ls2085a_common.h
+++ b/include/configs/ls2085a_common.h
@@ -19,6 +19,9 @@
 #define CONFIG_ARM_ERRATA_828024
 #define CONFIG_ARM_ERRATA_826974
 
+/* We need architecture specific misc initializations */
+#define CONFIG_ARCH_MISC_INIT
+
 /* Link Definitions */
 #define CONFIG_SYS_TEXT_BASE		0x30001000
 
@@ -206,6 +209,14 @@
 #define CONFIG_SYS_CS0_FTIM2		CONFIG_SYS_NOR_FTIM2
 #define CONFIG_SYS_CS0_FTIM3		CONFIG_SYS_NOR_FTIM3
 
+/* Debug Server firmware */
+#define CONFIG_FSL_DEBUG_SERVER
+#define CONFIG_SYS_DEBUG_SERVER_DRAM_BLOCK_MIN_SIZE	(512UL * 1024 * 1024)
+#define CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR
+#define CONFIG_SYS_DEBUG_SERVER_FW_ADDR			0x580C00000ULL
+/* 2 sec timeout */
+#define CONFIG_SYS_DEBUG_SERVER_TIMEOUT			(2 * 1000 * 1000)
+
 /* MC firmware */
 #define CONFIG_FSL_MC_ENET
 #define CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE	(512UL * 1024 * 1024)
@@ -217,9 +228,9 @@
 #define CONFIG_SYS_LS_MC_DPL_MAX_LENGTH	(256 * 1024)
 #define CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET    0xe00000
 
-/* Carve the MC private DRAM block from the end of DRAM */
-#ifdef CONFIG_FSL_MC_ENET
-#define CONFIG_SYS_MEM_TOP_HIDE		mc_get_dram_block_size()
+/* Carve out a DDR region which will not be used by u-boot/Linux */
+#if defined(CONFIG_FSL_MC_ENET) || defined(CONFIG_FSL_DEBUG_SERVER)
+#define CONFIG_SYS_MEM_TOP_HIDE		get_dram_size_to_hide()
 #endif
 
 /* Command line configuration */
@@ -251,7 +262,6 @@
 #define CONFIG_SYS_CLK_FREQ	100000000
 #define CONFIG_DDR_CLK_FREQ	133333333
 
-
 #define CONFIG_NR_DRAM_BANKS		3
 
 #define CONFIG_HWCONFIG
@@ -298,7 +308,7 @@
 #define CONFIG_SYS_MAXARGS		64	/* max command args */
 
 #ifndef __ASSEMBLY__
-unsigned long mc_get_dram_block_size(void);
+unsigned long get_dram_size_to_hide(void);
 #endif
 
 #endif /* __LS2_COMMON_H */
diff --git a/include/fsl-mc/fsl_mc.h b/include/fsl-mc/fsl_mc.h
index b9f089e..28d5961 100644
--- a/include/fsl-mc/fsl_mc.h
+++ b/include/fsl-mc/fsl_mc.h
@@ -56,4 +56,5 @@ struct mc_ccsr_registers {
 int mc_init(bd_t *bis);
 
 int get_mc_boot_status(void);
+unsigned long mc_get_dram_block_size(void);
 #endif
diff --git a/include/fsl_debug_server.h b/include/fsl_debug_server.h
new file mode 100644
index 0000000..28d8adb
--- /dev/null
+++ b/include/fsl_debug_server.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __FSL_DBG_SERVER_H__
+#define __FSL_DBG_SERVER_H__
+
+#include <asm/io.h>
+#include <common.h>
+
+/*
+ * Define Debug Server firmware version information
+ */
+
+/* Major version number: incremented on API compatibility changes */
+#define DEBUG_SERVER_VER_MAJOR	0
+
+/* Minor version number: incremented on API additions (backward
+ * compatible); reset when major version is incremented.
+ */
+#define DEBUG_SERVER_VER_MINOR	1
+
+#define DEBUG_SERVER_INIT_STATUS	(1 << 0)
+#define DEBUG_SERVER_INIT_STATUS_MASK	(0x00000001)
+
+int debug_server_init(void);
+unsigned long debug_server_get_dram_block_size(void);
+
+#endif /* __FSL_DBG_SERVER_H__ */
+
-- 
1.7.9.5



More information about the U-Boot mailing list