summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2019-01-13 22:05:22 -0800
committerYe Li <ye.li@nxp.com>2019-01-16 22:32:42 -0800
commitd520e1c6067c08103a020b0bc19feb620473e543 (patch)
tree38b833cfe81fc2cd24fd7382d750cf65ec8f1855
parentedc9581d87d7a6f27b7f9673e2959169c9be15c7 (diff)
MLK-20758 mx7: Add new command for tamper pin
Add new u-boot command "imx_tamper" to configure and check the tamper pins. The codes are used for reference and test. So command is disabled at default, user can enable it by adding CONFIG_IMX_TAMPER=y to defconfig The iMX7D has 10 tamper pins those can be used for SNVS tamper detection. Tamper 9 pin is NVCC_DRAM power switch for LPSR by default. It must be fused to tamper function by command => fuse prog -y 1 3 0x80000000 Otherwise, SNVS power consumption would be high When tamper is detected, CPU can't enter/stay in SNVS mode, the tamper must be cleared and disabled before enter SNVS. Signed-off-by: Ye Li <ye.li@nxp.com> Signed-off-by: Shaojun Wang <shaojun.wang@nxp.com> Acked-by: Peng Fan <peng.fan@nxp.com>
-rw-r--r--arch/arm/include/asm/arch-mx7/snvs.h41
-rw-r--r--arch/arm/mach-imx/mx7/Kconfig5
-rw-r--r--arch/arm/mach-imx/mx7/Makefile1
-rw-r--r--arch/arm/mach-imx/mx7/tamper.c384
4 files changed, 431 insertions, 0 deletions
diff --git a/arch/arm/include/asm/arch-mx7/snvs.h b/arch/arm/include/asm/arch-mx7/snvs.h
new file mode 100644
index 00000000000..a18f8535109
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx7/snvs.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __MX7_SNVS_H__
+#define __MX7_SNVS_H__
+
+#define SNVS_HPCOMR SNVS_BASE_ADDR + 0x04
+#define SNVS_HPSICR SNVS_BASE_ADDR + 0x0C
+#define SNVS_HPSVCR SNVS_BASE_ADDR + 0x10
+#define SNVS_HPSR SNVS_BASE_ADDR + 0x14
+#define SNVS_HPSVSR SNVS_BASE_ADDR + 0x18
+#define SNVS_LPCR SNVS_BASE_ADDR + 0x38
+#define SNVS_LPMKCR SNVS_BASE_ADDR + 0x3C
+#define SNVS_LPTGFCR SNVS_BASE_ADDR + 0x44
+#define SNVS_LPTDCR SNVS_BASE_ADDR + 0x48
+#define SNVS_LPSR SNVS_BASE_ADDR + 0x4C
+#define SNVS_LPPGDR SNVS_BASE_ADDR + 0x64
+#define SNVS_LPZMKR0 SNVS_BASE_ADDR + 0x6C
+#define SNVS_LPZMKR1 SNVS_BASE_ADDR + 0x70
+#define SNVS_LPZMKR2 SNVS_BASE_ADDR + 0x74
+#define SNVS_LPZMKR3 SNVS_BASE_ADDR + 0x78
+#define SNVS_LPZMKR4 SNVS_BASE_ADDR + 0x7C
+#define SNVS_LPZMKR5 SNVS_BASE_ADDR + 0x80
+#define SNVS_LPZMKR6 SNVS_BASE_ADDR + 0x84
+#define SNVS_LPZMKR7 SNVS_BASE_ADDR + 0x88
+#define SNVS_LPTDC2R SNVS_BASE_ADDR + 0xA0
+#define SNVS_LPTDSR SNVS_BASE_ADDR + 0xA4
+#define SNVS_LPTGF1CR SNVS_BASE_ADDR + 0xA8
+#define SNVS_LPTGF2CR SNVS_BASE_ADDR + 0xAC
+#define SNVS_LPAT1CR SNVS_BASE_ADDR + 0xC0
+#define SNVS_LPATCTLR SNVS_BASE_ADDR + 0xE0
+#define SNVS_LPATCLKR SNVS_BASE_ADDR + 0xE4
+#define SNVS_LPATRC1R SNVS_BASE_ADDR + 0xE8
+#define SNVS_LPATRC2R SNVS_BASE_ADDR + 0xEC
+
+#define AT5_POLYSEED 0x12345678
+
+#endif
diff --git a/arch/arm/mach-imx/mx7/Kconfig b/arch/arm/mach-imx/mx7/Kconfig
index 9351a9497bc..242be59798a 100644
--- a/arch/arm/mach-imx/mx7/Kconfig
+++ b/arch/arm/mach-imx/mx7/Kconfig
@@ -16,6 +16,11 @@ config MX7D
imply CMD_FUSE
bool
+config IMX_TAMPER
+ bool "Enable commands for SNVS tamper pin configuration and test"
+ help
+ Set "Y" to enable the tamper commands
+
choice
prompt "MX7 board select"
optional
diff --git a/arch/arm/mach-imx/mx7/Makefile b/arch/arm/mach-imx/mx7/Makefile
index ce289c1415a..efb12244b60 100644
--- a/arch/arm/mach-imx/mx7/Makefile
+++ b/arch/arm/mach-imx/mx7/Makefile
@@ -6,6 +6,7 @@
#
obj-y := soc.o clock.o clock_slice.o ddr.o
+obj-$(CONFIG_IMX_TAMPER) += tamper.o
ifdef CONFIG_ARMV7_PSCI
obj-y += psci-mx7.o psci.o
diff --git a/arch/arm/mach-imx/mx7/tamper.c b/arch/arm/mach-imx/mx7/tamper.c
new file mode 100644
index 00000000000..89f62397f8c
--- /dev/null
+++ b/arch/arm/mach-imx/mx7/tamper.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright 2018 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/arch/snvs.h>
+
+void enable_active_tamper(unsigned int tx, unsigned int rx)
+{
+ int val;
+
+ printf("start active tamper test on %d -> %d\n", tx, rx);
+
+ /****************************
+ * Configuring CAAM and SNVS *
+ ****************************/
+
+ /* Initialize power glitch detector register */
+ val = 0x41736166;
+ writel(val, SNVS_LPPGDR);
+
+ /* W1C PGD */
+ val = readl(SNVS_LPSR) & 0x00000008;
+ writel(val, SNVS_LPSR);
+
+ /* Programming ZMK via SW */
+ writel(0x11110000, SNVS_LPZMKR0);
+ writel(0x22220000, SNVS_LPZMKR1);
+ writel(0x33330000, SNVS_LPZMKR2);
+ writel(0x44440000, SNVS_LPZMKR3);
+ writel(0x55550000, SNVS_LPZMKR4);
+ writel(0x66660000, SNVS_LPZMKR5);
+ writel(0x77770000, SNVS_LPZMKR6);
+ writel(0x88880000, SNVS_LPZMKR7);
+
+ val = readl(SNVS_LPMKCR) | 0xa;
+ writel(val, SNVS_LPMKCR);
+ val = readl(SNVS_HPCOMR) | 0x1000;
+ writel(val, SNVS_HPCOMR);
+
+ val = readl(SNVS_LPMKCR) | 0x10;
+ writel(val, SNVS_LPMKCR);
+
+ val = readl(SNVS_HPSVSR);
+
+ /* LP Security Violation is a non-fatal Violation */
+ val = 0x40000000;
+ writel(val, SNVS_HPSVCR);
+
+ /* Enable SRTC invalidation in case of security violation */
+ val = readl(SNVS_LPCR);
+ val |= 0x11;
+ writel(val, SNVS_LPCR);
+
+ /*********************************
+ * Configuring active tamper tx output *
+ *********************************/
+
+ /* Configure LFSR polynomial and seed for active tamper tx */
+ val = AT5_POLYSEED;
+ writel(val, SNVS_LPAT1CR + (tx - 5) * 4);
+
+ /* Enable active tamper tx external pad */
+ val = readl(SNVS_LPATCTLR) | (1 << (tx - 5 + 16));
+ writel(val, SNVS_LPATCTLR);
+
+ /* Enable active tamper tx clk 16hz */
+ val = readl(SNVS_LPATCLKR);
+ val &= ~(3 << (tx - 5) * 4);
+ writel(val, SNVS_LPATCLKR);
+
+ /* Enable active tamper tx LFSR */
+ val = readl(SNVS_LPATCTLR) | (1 << (tx - 5));
+ writel(val, SNVS_LPATCTLR);
+
+ /* Enable glitch filter for external tamper rx */
+ if (rx < 2) {
+ val = readl(SNVS_LPTGFCR);
+ if (rx == 0)
+ val |= 0x800000;
+ else if (rx == 1)
+ val |= 0x80000000;
+ writel(val, SNVS_LPTGFCR);
+ } else if (rx < 6) {
+ val = readl(SNVS_LPTGF1CR);
+ val |= 1 << ((rx - 1) * 8 - 1);
+ writel(val, SNVS_LPTGF1CR);
+ } else {
+ val = readl(SNVS_LPTGF2CR);
+ val |= 1 << ((rx - 5) * 8 - 1);
+ writel(val, SNVS_LPTGF2CR);
+ }
+
+ /* Route active tamper tx to external tamper rx */
+ if (rx < 8) {
+ val = readl(SNVS_LPATRC1R);
+ val &= ~(0xf << (rx * 4));
+ val |= ((tx - 4) << (rx * 4));
+ writel(val, SNVS_LPATRC1R);
+ } else {
+ val = readl(SNVS_LPATRC2R);
+ val &= ~(0xf << ((rx - 8) * 4));
+ val |= ((tx - 4) << ((rx - 8) * 4));
+ writel(val, SNVS_LPATRC2R);
+ }
+
+ /* Enable external tamper rx */
+ if (rx < 2) {
+ val = readl(SNVS_LPTDCR);
+ if (rx == 0)
+ val |= 0x200;
+ else if (rx == 1)
+ val |= 0x400;
+ writel(val, SNVS_LPTDCR);
+ } else {
+ val = readl(SNVS_LPTDC2R);
+ val |= 1 << (rx - 2);
+ writel(val, SNVS_LPTDC2R);
+ }
+}
+
+void enable_passive_tamper(unsigned int rx, unsigned int high)
+{
+ int val;
+
+ printf("start passive tamper test on pin %d\n", rx);
+
+ /****************************
+ * Configuring CAAM and SNVS *
+ ****************************/
+
+ /* Initialize power glitch detector register */
+ val = 0x41736166;
+ writel(val, SNVS_LPPGDR);
+
+ /* W1C PGD */
+ val = readl(SNVS_LPSR) & 0x00000008;
+ writel(val, SNVS_LPSR);
+
+ /* Programming ZMK via SW */
+ writel(0x11111111, SNVS_LPZMKR0);
+ writel(0x22222222, SNVS_LPZMKR1);
+ writel(0x33333333, SNVS_LPZMKR2);
+ writel(0x44444444, SNVS_LPZMKR3);
+ writel(0x55555555, SNVS_LPZMKR4);
+ writel(0x66666666, SNVS_LPZMKR5);
+ writel(0x77777777, SNVS_LPZMKR6);
+ writel(0x88888888, SNVS_LPZMKR7);
+
+ val = readl(SNVS_LPMKCR) | 0xa;
+ writel(val, SNVS_LPMKCR);
+ val = readl(SNVS_HPCOMR) | 0x1000;
+ writel(val, SNVS_HPCOMR);
+
+ val = readl(SNVS_LPMKCR) | 0x10;
+ writel(val, SNVS_LPMKCR);
+
+ /* LP Security Violation is a non-fatal Violation */
+ val = 0x40000000;
+ writel(val, SNVS_HPSVCR);
+
+ /* Enable SRTC invalidation in case of security violation */
+ val = readl(SNVS_LPCR);
+ val |= 0x11;
+ writel(val, SNVS_LPCR);
+
+ /*********************************
+ * Configuring passive tamper rx *
+ *********************************/
+
+ /* Enable glitch filter for external tamper rx */
+ if (rx < 2) {
+ val = readl(SNVS_LPTGFCR);
+ if (rx == 0)
+ val |= 0x800000;
+ else if (rx == 1)
+ val |= 0x80000000;
+ writel(val, SNVS_LPTGFCR);
+ } else if (rx < 6) {
+ val = readl(SNVS_LPTGF1CR);
+ val |= 1 << ((rx - 1) * 8 - 1);
+ writel(val, SNVS_LPTGF1CR);
+ } else {
+ val = readl(SNVS_LPTGF2CR);
+ val |= 1 << ((rx - 5) * 8 - 1);
+ writel(val, SNVS_LPTGF2CR);
+ }
+
+ if (high == 1) {
+ /* Set external tampering rx polarity to high and enable tamper */
+ if (rx < 2) {
+ val = readl(SNVS_LPTDCR);
+ if (rx == 0)
+ val |= 0x800;
+ else if (rx == 1)
+ val |= 0x1000;
+ writel(val, SNVS_LPTDCR);
+ } else {
+ val = readl(SNVS_LPTDC2R);
+ val |= 1 << (rx - 2 + 16);
+ writel(val, SNVS_LPTDC2R);
+ }
+ }
+ /* Enable external tamper rx */
+ if (rx < 2) {
+ val = readl(SNVS_LPTDCR);
+ if (rx == 0)
+ val |= 0x200;
+ else if (rx == 1)
+ val |= 0x400;
+ writel(val, SNVS_LPTDCR);
+ } else {
+ val = readl(SNVS_LPTDC2R);
+ val |= 1 << (rx - 2);
+ writel(val, SNVS_LPTDC2R);
+ }
+}
+
+void stop_tamper(int rx)
+{
+ int val;
+
+ /* stop tamper */
+ if (rx < 2) {
+ val = readl(SNVS_LPTDCR);
+ if (rx == 0)
+ val &= ~0x200;
+ else if (rx == 1)
+ val &= ~0x400;
+ writel(val, SNVS_LPTDCR);
+ } else {
+ val = readl(SNVS_LPTDC2R);
+ val &= ~(1 << (rx - 2));
+ writel(val, SNVS_LPTDC2R);
+ }
+
+ /* clear tamper status */
+ if (rx < 2) {
+ val = readl(SNVS_LPSR);
+ val |= 1 << (rx + 9);
+ writel(val, SNVS_LPSR);
+ } else if (rx < 10) {
+ val = readl(SNVS_LPTDSR);
+ val |= 1 << (rx - 2);
+ writel(val, SNVS_LPTDSR);
+ }
+}
+
+static void get_tamper_status(void)
+{
+ unsigned int lpsr, lptdsr, hpsr, ssm;
+
+ lpsr = readl(SNVS_LPSR);
+ lptdsr = readl(SNVS_LPTDSR);
+ hpsr = readl(SNVS_HPSR);
+ ssm = (hpsr & 0xf00) >> 8;
+
+ if (lpsr & (1 << 9))
+ printf("External Tampering 0 Detected\n");
+ if (lpsr & (1 << 10))
+ printf("External Tampering 1 Detected\n");
+ if (lptdsr & (1 << 0))
+ printf("External Tampering 2 Detected\n");
+ if (lptdsr & (1 << 1))
+ printf("External Tampering 3 Detected\n");
+ if (lptdsr & (1 << 2))
+ printf("External Tampering 4 Detected\n");
+ if (lptdsr & (1 << 3))
+ printf("External Tampering 5 Detected\n");
+ if (lptdsr & (1 << 4))
+ printf("External Tampering 6 Detected\n");
+ if (lptdsr & (1 << 5))
+ printf("External Tampering 7 Detected\n");
+ if (lptdsr & (1 << 6))
+ printf("External Tampering 8 Detected\n");
+ if (lptdsr & (1 << 7))
+ printf("External Tampering 9 Detected\n");
+ if (!(lpsr & (3 << 9)) && !(lptdsr & 0xff))
+ printf("No External Tampering Detected\n");
+
+ if (hpsr & 0x80000000)
+ printf("Zeroizable Master Key is clear\n");
+ else
+ printf("Zeroizable Master Key is not zero\n");
+
+ if (ssm == 0)
+ printf("System Security Monitor State: Init\n");
+ else if (ssm == 0x8)
+ printf("System Security Monitor State: Init Intermediate\n");
+ else if (ssm == 0x9)
+ printf("System Security Monitor State: Check\n");
+ else if (ssm == 0xb)
+ printf("System Security Monitor State: Non-Secure\n");
+ else if (ssm == 0xd)
+ printf("System Security Monitor State: Trusted\n");
+ else if (ssm == 0xf)
+ printf("System Security Monitor State: Secure\n");
+ else if (ssm == 0x3)
+ printf("System Security Monitor State: Soft Fail\n");
+ else if (ssm == 0x1)
+ printf("System Security Monitor State: Hard Fail\n");
+ else
+ printf("System Security Monitor State: 0x%x\n", ssm);
+}
+
+static void clear_tamper_warning(void)
+{
+ unsigned int lpsr, lptdsr;
+
+ lpsr = readl(SNVS_LPSR);
+ lptdsr = readl(SNVS_LPTDSR);
+
+ writel(lpsr, SNVS_LPSR);
+ writel(lptdsr, SNVS_LPTDSR);
+}
+
+static int do_tamper(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+ const char *op = argc >= 2 ? argv[1] : NULL;
+ unsigned int tx, rx, high;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (!strcmp(op, "active")) {
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ tx = simple_strtoul(argv[2], NULL, 16);
+ rx = simple_strtoul(argv[3], NULL, 16);
+ if ((tx > 9) || (tx < 5))
+ return CMD_RET_USAGE;
+ if ((rx > 9) || (rx == tx))
+ return CMD_RET_USAGE;
+
+ enable_active_tamper(tx, rx);
+
+ } else if (!strcmp(op, "passive")) {
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ rx = simple_strtoul(argv[2], NULL, 16);
+ if (rx > 9)
+ return CMD_RET_USAGE;
+
+ high = simple_strtoul(argv[3], NULL, 16);
+ if (high != 0)
+ high = 1;
+ enable_passive_tamper(rx, high);
+
+ } else if (!strcmp(op, "status")) {
+ get_tamper_status();
+ } else if (!strcmp(op, "clear")) {
+ clear_tamper_warning();
+ } else if (!strcmp(op, "stop")) {
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ rx = simple_strtoul(argv[2], NULL, 16);
+ if (rx > 9)
+ return CMD_RET_USAGE;
+ stop_tamper(rx);
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ imx_tamper, CONFIG_SYS_MAXARGS, 0, do_tamper,
+ "imx tamper command for setting for test",
+ "active <tx rx> - tx is active tamper pin from 9 ~ 5, \n"
+ " rx pin is from 9 ~ 0 and should not equal to tx pin\n"
+ "passive <rx> <high> - rx is passive tamper pin from 9 ~ 0, \n"
+ " high: 1 - high assert, 0 - low assert\n"
+ "status - Get tamper status\n"
+ "clear - clear tamper warning\n"
+ "stop rx - rx is tamper pin to stop\n"
+ );