diff options
-rw-r--r-- | arch/arm/include/asm/arch-mx7/snvs.h | 41 | ||||
-rw-r--r-- | arch/arm/mach-imx/mx7/Kconfig | 5 | ||||
-rw-r--r-- | arch/arm/mach-imx/mx7/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/mx7/tamper.c | 384 |
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" + ); |