]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
armv8/fsl-lsch3: Add Freescale Debug Server driver
authorBhupesh Sharma <bhupesh.sharma@freescale.com>
Thu, 19 Mar 2015 16:20:43 +0000 (09:20 -0700)
committerYork Sun <yorksun@freescale.com>
Tue, 21 Apr 2015 17:26:29 +0000 (10:26 -0700)
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@freescale.com>
Reviewed-by: York Sun <yorksun@freescale.com>
arch/arm/cpu/armv8/fsl-lsch3/cpu.c
arch/arm/include/asm/arch-fsl-lsch3/config.h
board/freescale/ls2085a/ls2085a.c
drivers/misc/Makefile
drivers/misc/fsl_debug_server.c [new file with mode: 0644]
drivers/net/fsl-mc/mc.c
include/configs/ls2085a_common.h
include/fsl-mc/fsl_mc.h
include/fsl_debug_server.h [new file with mode: 0644]

index 49974878b9c774a66cedaafd0edde801438c525f..618fbc2a687b91ec940f7b92ff53cee041deaf11 100644 (file)
@@ -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;
index b140c1fac2c2d51fb43ea2157ddec7f3a4b60c20..59d10bfacb726ae6b2f54399497b6e6d13b917fa 100644 (file)
 #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
 
index 519d61cb1e8539fba78990c4c0001767021f2676..a16c2c8282108c098c9159f8e2901d1733bb071a 100644 (file)
@@ -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;
index 842209a2eca8a4275b58c98120b6eca3b2979201..25630c3f2b42cbd30508fa171ad8cd4f11928a96 100644 (file)
@@ -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 (file)
index 0000000..e080fe6
--- /dev/null
@@ -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;
+}
+
index 74b0085301c5ac407089971399ba49ec8c713355..76581cbfda84729a8a8dffec2e65e3e3a11171fe 100644 (file)
@@ -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,
index e0435cc0a7a7429c88a394031c81de36868f3b13..94d372f791892cf9cb3051e6da8f2acdcdf5f686 100644 (file)
@@ -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
 
 #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)
 #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 */
 #define CONFIG_SYS_CLK_FREQ    100000000
 #define CONFIG_DDR_CLK_FREQ    133333333
 
-
 #define CONFIG_NR_DRAM_BANKS           3
 
 #define CONFIG_HWCONFIG
 #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 */
index b9f089e5f32c8d2264e5b4b6bf32abd8c4c7d87b..28d596184eb4f7373c17e89a5d24e4e2edaa5b1d 100644 (file)
@@ -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 (file)
index 0000000..28d8adb
--- /dev/null
@@ -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__ */
+