Tegra186: Enable ECC and Parity Protection for A02p SKUs
authorVarun Wadekar <vwadekar@nvidia.com>
Wed, 18 May 2016 20:39:16 +0000 (13:39 -0700)
committerVarun Wadekar <vwadekar@nvidia.com>
Thu, 30 Mar 2017 23:49:05 +0000 (16:49 -0700)
This patch enables ECC and Parity Protection for Cortex-A57 CPUs during boot,
for Tegra186 A02p SKUs.

Change-Id: I8522a6cb61f5e4fa9e0471f558a0c3ee8078370e
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
plat/nvidia/tegra/include/t186/tegra_def.h
plat/nvidia/tegra/soc/t186/plat_setup.c

index 7f85351eb376f47f414a219fefe25cdb2f5f4161..f0bd5d57a75d4936c6d8b87f2114d76d6c5708dc 100644 (file)
 #define TEGRA_UARTF_BASE               0x03150000
 #define TEGRA_UARTG_BASE               0x0C290000
 
+/*******************************************************************************
+ * Tegra Fuse Controller related constants
+ ******************************************************************************/
+#define TEGRA_FUSE_BASE                        0x03820000
+#define  OPT_SUBREVISION               0x248
+#define  SUBREVISION_MASK              0xFF
+
 /*******************************************************************************
  * GICv2 & interrupt handling related constants
  ******************************************************************************/
index 49f45892fd23eee624b78a22541d90a9390d1ff0..1dd0d6ee7f3ec5d71083720600fa7ba5c6b9ee3f 100644 (file)
@@ -34,6 +34,7 @@
 #include <console.h>
 #include <context.h>
 #include <context_mgmt.h>
+#include <cortex_a57.h>
 #include <debug.h>
 #include <denver.h>
 #include <interrupt_mgmt.h>
@@ -43,6 +44,9 @@
 #include <tegra_private.h>
 #include <xlat_tables.h>
 
+DEFINE_RENAME_SYSREG_RW_FUNCS(l2ctlr_el1, L2CTLR_EL1)
+extern uint64_t tegra_enable_l2_ecc_parity_prot;
+
 /*******************************************************************************
  * The Tegra power domain tree has a single system level power domain i.e. a
  * single root node. The first entry in the power domain descriptor specifies
@@ -74,6 +78,8 @@ static const mmap_region_t tegra_mmap[] = {
                        MT_DEVICE | MT_RW | MT_SECURE),
        MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000, /* 128KB */
                        MT_DEVICE | MT_RW | MT_SECURE),
+       MAP_REGION_FLAT(TEGRA_FUSE_BASE, 0x10000, /* 64KB */
+                       MT_DEVICE | MT_RW | MT_SECURE),
        MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000, /* 128KB */
                        MT_DEVICE | MT_RW | MT_SECURE),
        MAP_REGION_FLAT(TEGRA_SE0_BASE, 0x10000, /* 64KB */
@@ -142,6 +148,55 @@ uint32_t plat_get_console_from_id(int id)
        return tegra186_uart_addresses[id];
 }
 
+/* represent chip-version as concatenation of major (15:12), minor (11:8) and subrev (7:0) */
+#define TEGRA186_VER_A02P      0x1201
+
+/*******************************************************************************
+ * Handler for early platform setup
+ ******************************************************************************/
+void plat_early_platform_setup(void)
+{
+       int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+       uint32_t chip_minor, chip_major, chip_subrev, val;
+
+       /* sanity check MCE firmware compatibility */
+       mce_verify_firmware_version();
+
+       /*
+        * Enable ECC and Parity Protection for Cortex-A57 CPUs
+        * for Tegra A02p SKUs
+        */
+       if (impl != DENVER_IMPL) {
+
+               /* get the major, minor and sub-version values */
+               chip_major = (mmio_read_32(TEGRA_MISC_BASE +
+                             HARDWARE_REVISION_OFFSET) >>
+                             MAJOR_VERSION_SHIFT) & MAJOR_VERSION_MASK;
+               chip_minor = (mmio_read_32(TEGRA_MISC_BASE +
+                             HARDWARE_REVISION_OFFSET) >>
+                             MINOR_VERSION_SHIFT) & MINOR_VERSION_MASK;
+               chip_subrev = mmio_read_32(TEGRA_FUSE_BASE + OPT_SUBREVISION) &
+                             SUBREVISION_MASK;
+
+               /* prepare chip version number */
+               val = (chip_major << 12) | (chip_minor << 8) | chip_subrev;
+
+               /* enable L2 ECC for Tegra186 A02P and beyond */
+               if (val >= TEGRA186_VER_A02P) {
+
+                       val = read_l2ctlr_el1();
+                       val |= L2_ECC_PARITY_PROTECTION_BIT;
+                       write_l2ctlr_el1(val);
+
+                       /*
+                        * Set the flag to enable ECC/Parity Protection
+                        * when we exit System Suspend or Cluster Powerdn
+                        */
+                       tegra_enable_l2_ecc_parity_prot = 1;
+               }
+       }
+}
+
 /* Secure IRQs for Tegra186 */
 static const irq_sec_cfg_t tegra186_sec_irqs[] = {
        {
@@ -171,11 +226,3 @@ void plat_gic_setup(void)
        if (sizeof(tegra186_sec_irqs) > 0)
                tegra_fiq_handler_setup();
 }
-
-/*******************************************************************************
- * Handler for early platform setup
- ******************************************************************************/
-void plat_early_platform_setup(void)
-{
-       mce_verify_firmware_version();
-}