From 03ec635be0eb1c1b63b1f631938d41b379dad637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Mon, 30 Sep 2019 00:22:09 +0300 Subject: [PATCH] MLKU-38-3 crypto: caam - add SNVS / SECVIO support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a squash of the following i.MX BSP commits (rel_imx_4.19.35_1.1.0_rc2) 1. 8f6a17b41917 ("ENGR00289885 [iMX6Q] Add Secure Memory and SECVIO support.") 2. 8433c811e97a ("MLK-9710-18 snvs - make SECVIO module device tree correct") 3. 35bbc34e996b ("MLK-9769-23 Replace SECVIO of_irq_to_resource() with irq_of_parse_and_map()") 4. 3ac6edcd92d4 ("MLK-11360-01 crypto: caam_snvs: add snvs clock management") 5. 9d9ca7a03e3b ("MLK-11922 i.mx6: Linux 3.14.28 CAAM & SNVS enabled by default. JTAG, DS-5 attachment causes exceptions") 6. fcdaabf1bba2 ("MLK-17412-01: Fix secvio driver to have same driver name as DTS") Signed-off-by: Dan Douglass Signed-off-by: Victoria Milhoan Signed-off-by: Steve Cornelius Signed-off-by: Fugang Duan Signed-off-by: Franck LENORMAND that have been reworked: 1. -make SM depend on JR -enable SM, SECVIO only on i.MX SoCs -fix resource leak - add off_node_put() where needed Split commit in three: - SNVS/SECVIO driver - Secure Memory driver - DT changes 3. JR changes dropped - no longer needed, already upstream in commit 549077d7d86a1 ("crypto: caam - check irq_of_parse_and_map for errors") 4. Split the patch in two: -DT bindings changes -driver changes 5. Fixed conflicts in imx7d.dtsi - added caam_sm and irq_sec_vio nodes. Split commit in 3: -SECVIO/SNVS driver changes -SECVIO/SNVS DT changes -Secure Memory DT changes Signed-off-by: Horia Geantă --- drivers/crypto/caam/Kconfig | 7 + drivers/crypto/caam/Makefile | 1 + drivers/crypto/caam/ctrl.c | 3 - drivers/crypto/caam/intern.h | 4 +- drivers/crypto/caam/secvio.c | 342 +++++++++++++++++++++++++++++++++++++++++ drivers/crypto/caam/secvio.h | 69 +++++++++ drivers/crypto/caam/snvsregs.h | 239 ++++++++++++++++++++++++++++ 7 files changed, 660 insertions(+), 5 deletions(-) create mode 100644 drivers/crypto/caam/secvio.c create mode 100644 drivers/crypto/caam/secvio.h create mode 100644 drivers/crypto/caam/snvsregs.h --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig @@ -156,6 +156,13 @@ config CRYPTO_DEV_FSL_CAAM_RNG_TEST caam RNG. This test is several minutes long and executes just before the RNG is registered with the hw_random API. +config CRYPTO_DEV_FSL_CAAM_SECVIO + tristate "CAAM/SNVS Security Violation Handler (EXPERIMENTAL)" + help + Enables installation of an interrupt handler with registrable + handler functions which can be specified to act on the consequences + of a security violation. + endif # CRYPTO_DEV_FSL_CAAM_JR endif # CRYPTO_DEV_FSL_CAAM --- a/drivers/crypto/caam/Makefile +++ b/drivers/crypto/caam/Makefile @@ -21,6 +21,7 @@ caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRY caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o +caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO) += secvio.o caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += qi.o ifneq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI),) --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -719,9 +719,6 @@ iomap_ctrl: BLOCK_OFFSET * DECO_BLOCK_NUMBER ); - /* Get the IRQ of the controller (for security violations only) */ - ctrlpriv->secvio_irq = irq_of_parse_and_map(nprop, 0); - if (!reg_access) goto set_dma_mask; --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h @@ -66,6 +66,7 @@ struct caam_drv_private_jr { * Driver-private storage for a single CAAM block instance */ struct caam_drv_private { + /* Physical-presence section */ struct caam_ctrl __iomem *ctrl; /* controller region */ struct caam_deco __iomem *deco; /* DECO/CCB views */ @@ -83,8 +84,7 @@ struct caam_drv_private { u8 qi_present; /* Nonzero if QI present in device */ u8 mc_en; /* Nonzero if MC f/w is active */ u8 scu_en; /* Nonzero if SCU f/w is active */ -+ u8 optee_en; /* Nonzero if OP-TEE f/w is active */ - int secvio_irq; /* Security violation interrupt number */ + u8 optee_en; /* Nonzero if OP-TEE f/w is active */ int virt_en; /* Virtualization enabled in CAAM */ int era; /* CAAM Era (internal HW revision) */ --- /dev/null +++ b/drivers/crypto/caam/secvio.c @@ -0,0 +1,342 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * SNVS Security Violation Handler + * + * Copyright 2012-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2019 NXP + */ + +#include "compat.h" +#include "secvio.h" +#include "regs.h" +#include "intern.h" +#include +#include +#include + +/* The driver is matched with node caam_snvs to get regmap + * It will then retrieve interruption and tamper alarm configuration from + * node caam-secvio searching for the compat string "fsl,imx6q-caam-secvio" + */ +#define DRIVER_NAME "caam-snvs" + +/* + * These names are associated with each violation handler. + * The source names were taken from MX6, and are based on recommendations + * for most common SoCs. + */ +static const u8 *violation_src_name[] = { + "CAAM Internal Security Violation", + "JTAG Alarm", + "Watchdog", + "(reserved)", + "External Boot", + "External Tamper Detect", +}; + +/* These names help describe security monitor state for the console */ +static const u8 *snvs_ssm_state_name[] = { + "init", + "hard fail", + "(undef:2)", + "soft fail", + "(undef:4)", + "(undef:5)", + "(undef:6)", + "(undef:7)", + "transition", + "check", + "(undef:10)", + "non-secure", + "(undef:12)", + "trusted", + "(undef:14)", + "secure", +}; + +/* Top-level security violation interrupt */ +static irqreturn_t snvs_secvio_interrupt(int irq, void *snvsdev) +{ + struct device *dev = snvsdev; + struct snvs_secvio_drv_private *svpriv = dev_get_drvdata(dev); + + clk_enable(svpriv->clk); + /* Check the HP secvio status register */ + svpriv->irqcause = rd_reg32(&svpriv->svregs->hp.secvio_status) & + HP_SECVIOST_SECVIOMASK; + + if (!svpriv->irqcause) { + clk_disable(svpriv->clk); + return IRQ_NONE; + } + + /* Now ACK cause */ + clrsetbits_32(&svpriv->svregs->hp.secvio_status, 0, svpriv->irqcause); + + /* And run deferred service */ + preempt_disable(); + tasklet_schedule(&svpriv->irqtask[smp_processor_id()]); + preempt_enable(); + + clk_disable(svpriv->clk); + + return IRQ_HANDLED; +} + +/* Deferred service handler. Tasklet arg is simply the SNVS dev */ +static void snvs_secvio_dispatch(unsigned long indev) +{ + struct device *dev = (struct device *)indev; + struct snvs_secvio_drv_private *svpriv = dev_get_drvdata(dev); + unsigned long flags; + int i; + + + /* Look through stored causes, call each handler if exists */ + for (i = 0; i < MAX_SECVIO_SOURCES; i++) + if (svpriv->irqcause & (1 << i)) { + spin_lock_irqsave(&svpriv->svlock, flags); + svpriv->intsrc[i].handler(dev, i, + svpriv->intsrc[i].ext); + spin_unlock_irqrestore(&svpriv->svlock, flags); + }; + + /* Re-enable now-serviced interrupts */ + clrsetbits_32(&svpriv->svregs->hp.secvio_intcfg, 0, svpriv->irqcause); +} + +/* + * Default cause handler, used in lieu of an application-defined handler. + * All it does at this time is print a console message. It could force a halt. + */ +static void snvs_secvio_default(struct device *dev, u32 cause, void *ext) +{ + struct snvs_secvio_drv_private *svpriv = dev_get_drvdata(dev); + + dev_err(dev, "Unhandled Security Violation Interrupt %d = %s\n", + cause, svpriv->intsrc[cause].intname); +} + +/* + * Install an application-defined handler for a specified cause + * Arguments: + * - dev points to SNVS-owning device + * - cause interrupt source cause + * - handler application-defined handler, gets called with dev + * source cause, and locally-defined handler argument + * - cause_description points to a string to override the default cause + * name, this can be used as an alternate for error + * messages and such. If left NULL, the default + * description string is used. + * - ext pointer to any extra data needed by the handler. + */ +int snvs_secvio_install_handler(struct device *dev, enum secvio_cause cause, + void (*handler)(struct device *dev, u32 cause, + void *ext), + u8 *cause_description, void *ext) +{ + unsigned long flags; + struct snvs_secvio_drv_private *svpriv; + + svpriv = dev_get_drvdata(dev); + + if ((handler == NULL) || (cause > SECVIO_CAUSE_SOURCE_5)) + return -EINVAL; + + spin_lock_irqsave(&svpriv->svlock, flags); + svpriv->intsrc[cause].handler = handler; + if (cause_description != NULL) + svpriv->intsrc[cause].intname = cause_description; + if (ext != NULL) + svpriv->intsrc[cause].ext = ext; + spin_unlock_irqrestore(&svpriv->svlock, flags); + + return 0; +} +EXPORT_SYMBOL(snvs_secvio_install_handler); + +/* + * Remove an application-defined handler for a specified cause (and, by + * implication, restore the "default". + * Arguments: + * - dev points to SNVS-owning device + * - cause interrupt source cause + */ +int snvs_secvio_remove_handler(struct device *dev, enum secvio_cause cause) +{ + unsigned long flags; + struct snvs_secvio_drv_private *svpriv; + + svpriv = dev_get_drvdata(dev); + + if (cause > SECVIO_CAUSE_SOURCE_5) + return -EINVAL; + + spin_lock_irqsave(&svpriv->svlock, flags); + svpriv->intsrc[cause].intname = violation_src_name[cause]; + svpriv->intsrc[cause].handler = snvs_secvio_default; + svpriv->intsrc[cause].ext = NULL; + spin_unlock_irqrestore(&svpriv->svlock, flags); + return 0; +} +EXPORT_SYMBOL(snvs_secvio_remove_handler); + +static int snvs_secvio_remove(struct platform_device *pdev) +{ + struct device *svdev; + struct snvs_secvio_drv_private *svpriv; + int i; + + svdev = &pdev->dev; + svpriv = dev_get_drvdata(svdev); + + clk_enable(svpriv->clk); + /* Set all sources to nonfatal */ + wr_reg32(&svpriv->svregs->hp.secvio_intcfg, 0); + + /* Remove tasklets and release interrupt */ + for_each_possible_cpu(i) + tasklet_kill(&svpriv->irqtask[i]); + + clk_disable_unprepare(svpriv->clk); + free_irq(svpriv->irq, svdev); + iounmap(svpriv->svregs); + kfree(svpriv); + + return 0; +} + +static int snvs_secvio_probe(struct platform_device *pdev) +{ + struct device *svdev; + struct snvs_secvio_drv_private *svpriv; + struct device_node *np, *npirq; + struct snvs_full __iomem *snvsregs; + int i, error; + u32 hpstate; + const void *jtd, *wtd, *itd, *etd; + u32 td_en; + + svpriv = kzalloc(sizeof(struct snvs_secvio_drv_private), GFP_KERNEL); + if (!svpriv) + return -ENOMEM; + + svdev = &pdev->dev; + dev_set_drvdata(svdev, svpriv); + svpriv->pdev = pdev; + np = pdev->dev.of_node; + + npirq = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-secvio"); + if (!npirq) { + dev_err(svdev, "can't find secvio node\n"); + kfree(svpriv); + return -EINVAL; + } + svpriv->irq = irq_of_parse_and_map(npirq, 0); + if (svpriv->irq <= 0) { + dev_err(svdev, "can't identify secvio interrupt\n"); + kfree(svpriv); + return -EINVAL; + } + + jtd = of_get_property(npirq, "jtag-tamper", NULL); + wtd = of_get_property(npirq, "watchdog-tamper", NULL); + itd = of_get_property(npirq, "internal-boot-tamper", NULL); + etd = of_get_property(npirq, "external-pin-tamper", NULL); + if (!jtd | !wtd | !itd | !etd ) { + dev_err(svdev, "can't identify all tamper alarm configuration\n"); + kfree(svpriv); + return -EINVAL; + } + + /* + * Configure all sources according to device tree property. + * If the property is enabled then the source is ser as + * fatal violations except LP section, + * source #5 (typically used as an external tamper detect), and + * source #3 (typically unused). Whenever the transition to + * secure mode has occurred, these will now be "fatal" violations + */ + td_en = HP_SECVIO_INTEN_SRC0; + if (!strcmp(jtd, "enabled")) + td_en |= HP_SECVIO_INTEN_SRC1; + if (!strcmp(wtd, "enabled")) + td_en |= HP_SECVIO_INTEN_SRC2; + if (!strcmp(itd, "enabled")) + td_en |= HP_SECVIO_INTEN_SRC4; + if (!strcmp(etd, "enabled")) + td_en |= HP_SECVIO_INTEN_SRC5; + + snvsregs = of_iomap(np, 0); + if (!snvsregs) { + dev_err(svdev, "register mapping failed\n"); + return -ENOMEM; + } + svpriv->svregs = (struct snvs_full __force *)snvsregs; + + svpriv->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(svpriv->clk)) { + dev_err(&pdev->dev, "can't get snvs clock\n"); + svpriv->clk = NULL; + } + + /* Write the Secvio Enable Config the SVCR */ + wr_reg32(&svpriv->svregs->hp.secvio_ctl, td_en); + wr_reg32(&svpriv->svregs->hp.secvio_intcfg, td_en); + + /* Device data set up. Now init interrupt source descriptions */ + for (i = 0; i < MAX_SECVIO_SOURCES; i++) { + svpriv->intsrc[i].intname = violation_src_name[i]; + svpriv->intsrc[i].handler = snvs_secvio_default; + } + /* Connect main handler */ + for_each_possible_cpu(i) + tasklet_init(&svpriv->irqtask[i], snvs_secvio_dispatch, + (unsigned long)svdev); + + error = request_irq(svpriv->irq, snvs_secvio_interrupt, + IRQF_SHARED, DRIVER_NAME, svdev); + if (error) { + dev_err(svdev, "can't connect secvio interrupt\n"); + irq_dispose_mapping(svpriv->irq); + svpriv->irq = 0; + iounmap(svpriv->svregs); + kfree(svpriv); + return -EINVAL; + } + + clk_prepare_enable(svpriv->clk); + + hpstate = (rd_reg32(&svpriv->svregs->hp.status) & + HP_STATUS_SSM_ST_MASK) >> HP_STATUS_SSM_ST_SHIFT; + dev_info(svdev, "violation handlers armed - %s state\n", + snvs_ssm_state_name[hpstate]); + + clk_disable(svpriv->clk); + + return 0; +} + +static struct of_device_id snvs_secvio_match[] = { + { + .compatible = "fsl,imx6q-caam-snvs", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, snvs_secvio_match); + +static struct platform_driver snvs_secvio_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = snvs_secvio_match, + }, + .probe = snvs_secvio_probe, + .remove = snvs_secvio_remove, +}; + +module_platform_driver(snvs_secvio_driver); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("FSL SNVS Security Violation Handler"); +MODULE_AUTHOR("Freescale Semiconductor - MCU"); --- /dev/null +++ b/drivers/crypto/caam/secvio.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * CAAM Security Violation Handler + * + * Copyright 2012-2015 Freescale Semiconductor, Inc. + * Copyright 2016-2019 NXP + */ + +#ifndef SECVIO_H +#define SECVIO_H + +#include "snvsregs.h" + + +/* + * Defines the published interfaces to install/remove application-specified + * handlers for catching violations + */ + +#define MAX_SECVIO_SOURCES 6 + +/* these are the untranslated causes */ +enum secvio_cause { + SECVIO_CAUSE_SOURCE_0, + SECVIO_CAUSE_SOURCE_1, + SECVIO_CAUSE_SOURCE_2, + SECVIO_CAUSE_SOURCE_3, + SECVIO_CAUSE_SOURCE_4, + SECVIO_CAUSE_SOURCE_5 +}; + +/* These are common "recommended" cause definitions for most devices */ +#define SECVIO_CAUSE_CAAM_VIOLATION SECVIO_CAUSE_SOURCE_0 +#define SECVIO_CAUSE_JTAG_ALARM SECVIO_CAUSE_SOURCE_1 +#define SECVIO_CAUSE_WATCHDOG SECVIO_CAUSE_SOURCE_2 +#define SECVIO_CAUSE_EXTERNAL_BOOT SECVIO_CAUSE_SOURCE_4 +#define SECVIO_CAUSE_TAMPER_DETECT SECVIO_CAUSE_SOURCE_5 + +int snvs_secvio_install_handler(struct device *dev, enum secvio_cause cause, + void (*handler)(struct device *dev, u32 cause, + void *ext), + u8 *cause_description, void *ext); +int snvs_secvio_remove_handler(struct device *dev, enum secvio_cause cause); + +/* + * Private data definitions for the secvio "driver" + */ + +struct secvio_int_src { + const u8 *intname; /* Points to a descriptive name for source */ + void *ext; /* Extended data to pass to the handler */ + void (*handler)(struct device *dev, u32 cause, void *ext); +}; + +struct snvs_secvio_drv_private { + struct platform_device *pdev; + spinlock_t svlock ____cacheline_aligned; + struct tasklet_struct irqtask[NR_CPUS]; + struct snvs_full __iomem *svregs; /* both HP and LP domains */ + struct clk *clk; + int irq; + u32 irqcause; /* stashed cause of violation interrupt */ + + /* Registered handlers for each violation */ + struct secvio_int_src intsrc[MAX_SECVIO_SOURCES]; + +}; + +#endif /* SECVIO_H */ --- /dev/null +++ b/drivers/crypto/caam/snvsregs.h @@ -0,0 +1,239 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * SNVS hardware register-level view + * + * Copyright 2012-2015 Freescale Semiconductor, Inc. + * Copyright 2016-2019 NXP + */ + +#ifndef SNVSREGS_H +#define SNVSREGS_H + +#include +#include + +/* + * SNVS High Power Domain + * Includes security violations, HA counter, RTC, alarm + */ +struct snvs_hp { + u32 lock; /* HPLR - HP Lock */ + u32 cmd; /* HPCOMR - HP Command */ + u32 ctl; /* HPCR - HP Control */ + u32 secvio_intcfg; /* HPSICR - Security Violation Int Config */ + u32 secvio_ctl; /* HPSVCR - Security Violation Control */ + u32 status; /* HPSR - HP Status */ + u32 secvio_status; /* HPSVSR - Security Violation Status */ + u32 ha_counteriv; /* High Assurance Counter IV */ + u32 ha_counter; /* High Assurance Counter */ + u32 rtc_msb; /* Real Time Clock/Counter MSB */ + u32 rtc_lsb; /* Real Time Counter LSB */ + u32 time_alarm_msb; /* Time Alarm MSB */ + u32 time_alarm_lsb; /* Time Alarm LSB */ +}; + +#define HP_LOCK_HAC_LCK 0x00040000 +#define HP_LOCK_HPSICR_LCK 0x00020000 +#define HP_LOCK_HPSVCR_LCK 0x00010000 +#define HP_LOCK_MKEYSEL_LCK 0x00000200 +#define HP_LOCK_TAMPCFG_LCK 0x00000100 +#define HP_LOCK_TAMPFLT_LCK 0x00000080 +#define HP_LOCK_SECVIO_LCK 0x00000040 +#define HP_LOCK_GENP_LCK 0x00000020 +#define HP_LOCK_MONOCTR_LCK 0x00000010 +#define HP_LOCK_CALIB_LCK 0x00000008 +#define HP_LOCK_SRTC_LCK 0x00000004 +#define HP_LOCK_ZMK_RD_LCK 0x00000002 +#define HP_LOCK_ZMK_WT_LCK 0x00000001 + +#define HP_CMD_NONPRIV_AXS 0x80000000 +#define HP_CMD_HAC_STOP 0x00080000 +#define HP_CMD_HAC_CLEAR 0x00040000 +#define HP_CMD_HAC_LOAD 0x00020000 +#define HP_CMD_HAC_CFG_EN 0x00010000 +#define HP_CMD_SNVS_MSTR_KEY 0x00002000 +#define HP_CMD_PROG_ZMK 0x00001000 +#define HP_CMD_SW_LPSV 0x00000400 +#define HP_CMD_SW_FSV 0x00000200 +#define HP_CMD_SW_SV 0x00000100 +#define HP_CMD_LP_SWR_DIS 0x00000020 +#define HP_CMD_LP_SWR 0x00000010 +#define HP_CMD_SSM_SFNS_DIS 0x00000004 +#define HP_CMD_SSM_ST_DIS 0x00000002 +#define HP_CMD_SMM_ST 0x00000001 + +#define HP_CTL_TIME_SYNC 0x00010000 +#define HP_CTL_CAL_VAL_SHIFT 10 +#define HP_CTL_CAL_VAL_MASK (0x1f << HP_CTL_CALIB_SHIFT) +#define HP_CTL_CALIB_EN 0x00000100 +#define HP_CTL_PI_FREQ_SHIFT 4 +#define HP_CTL_PI_FREQ_MASK (0xf << HP_CTL_PI_FREQ_SHIFT) +#define HP_CTL_PI_EN 0x00000008 +#define HP_CTL_TIMEALARM_EN 0x00000002 +#define HP_CTL_RTC_EN 0x00000001 + +#define HP_SECVIO_INTEN_EN 0x10000000 +#define HP_SECVIO_INTEN_SRC5 0x00000020 +#define HP_SECVIO_INTEN_SRC4 0x00000010 +#define HP_SECVIO_INTEN_SRC3 0x00000008 +#define HP_SECVIO_INTEN_SRC2 0x00000004 +#define HP_SECVIO_INTEN_SRC1 0x00000002 +#define HP_SECVIO_INTEN_SRC0 0x00000001 +#define HP_SECVIO_INTEN_ALL 0x8000003f + +#define HP_SECVIO_ICTL_CFG_SHIFT 30 +#define HP_SECVIO_ICTL_CFG_MASK (0x3 << HP_SECVIO_ICTL_CFG_SHIFT) +#define HP_SECVIO_ICTL_CFG5_SHIFT 5 +#define HP_SECVIO_ICTL_CFG5_MASK (0x3 << HP_SECVIO_ICTL_CFG5_SHIFT) +#define HP_SECVIO_ICTL_CFG_DISABLE 0 +#define HP_SECVIO_ICTL_CFG_NONFATAL 1 +#define HP_SECVIO_ICTL_CFG_FATAL 2 +#define HP_SECVIO_ICTL_CFG4_FATAL 0x00000010 +#define HP_SECVIO_ICTL_CFG3_FATAL 0x00000008 +#define HP_SECVIO_ICTL_CFG2_FATAL 0x00000004 +#define HP_SECVIO_ICTL_CFG1_FATAL 0x00000002 +#define HP_SECVIO_ICTL_CFG0_FATAL 0x00000001 + +#define HP_STATUS_ZMK_ZERO 0x80000000 +#define HP_STATUS_OTPMK_ZERO 0x08000000 +#define HP_STATUS_OTPMK_SYN_SHIFT 16 +#define HP_STATUS_OTPMK_SYN_MASK (0x1ff << HP_STATUS_OTPMK_SYN_SHIFT) +#define HP_STATUS_SSM_ST_SHIFT 8 +#define HP_STATUS_SSM_ST_MASK (0xf << HP_STATUS_SSM_ST_SHIFT) +#define HP_STATUS_SSM_ST_INIT 0 +#define HP_STATUS_SSM_ST_HARDFAIL 1 +#define HP_STATUS_SSM_ST_SOFTFAIL 3 +#define HP_STATUS_SSM_ST_INITINT 8 +#define HP_STATUS_SSM_ST_CHECK 9 +#define HP_STATUS_SSM_ST_NONSECURE 11 +#define HP_STATUS_SSM_ST_TRUSTED 13 +#define HP_STATUS_SSM_ST_SECURE 15 + +#define HP_SECVIOST_ZMK_ECC_FAIL 0x08000000 /* write to clear */ +#define HP_SECVIOST_ZMK_SYN_SHIFT 16 +#define HP_SECVIOST_ZMK_SYN_MASK (0x1ff << HP_SECVIOST_ZMK_SYN_SHIFT) +#define HP_SECVIOST_SECVIO5 0x00000020 +#define HP_SECVIOST_SECVIO4 0x00000010 +#define HP_SECVIOST_SECVIO3 0x00000008 +#define HP_SECVIOST_SECVIO2 0x00000004 +#define HP_SECVIOST_SECVIO1 0x00000002 +#define HP_SECVIOST_SECVIO0 0x00000001 +#define HP_SECVIOST_SECVIOMASK 0x0000003f + +/* + * SNVS Low Power Domain + * Includes glitch detector, SRTC, alarm, monotonic counter, ZMK + */ +struct snvs_lp { + u32 lock; + u32 ctl; + u32 mstr_key_ctl; /* Master Key Control */ + u32 secvio_ctl; /* Security Violation Control */ + u32 tamper_filt_cfg; /* Tamper Glitch Filters Configuration */ + u32 tamper_det_cfg; /* Tamper Detectors Configuration */ + u32 status; + u32 srtc_msb; /* Secure Real Time Clock/Counter MSB */ + u32 srtc_lsb; /* Secure Real Time Clock/Counter LSB */ + u32 time_alarm; /* Time Alarm */ + u32 smc_msb; /* Secure Monotonic Counter MSB */ + u32 smc_lsb; /* Secure Monotonic Counter LSB */ + u32 pwr_glitch_det; /* Power Glitch Detector */ + u32 gen_purpose; + u32 zmk[8]; /* Zeroizable Master Key */ +}; + +#define LP_LOCK_MKEYSEL_LCK 0x00000200 +#define LP_LOCK_TAMPDET_LCK 0x00000100 +#define LP_LOCK_TAMPFLT_LCK 0x00000080 +#define LP_LOCK_SECVIO_LCK 0x00000040 +#define LP_LOCK_GENP_LCK 0x00000020 +#define LP_LOCK_MONOCTR_LCK 0x00000010 +#define LP_LOCK_CALIB_LCK 0x00000008 +#define LP_LOCK_SRTC_LCK 0x00000004 +#define LP_LOCK_ZMK_RD_LCK 0x00000002 +#define LP_LOCK_ZMK_WT_LCK 0x00000001 + +#define LP_CTL_CAL_VAL_SHIFT 10 +#define LP_CTL_CAL_VAL_MASK (0x1f << LP_CTL_CAL_VAL_SHIFT) +#define LP_CTL_CALIB_EN 0x00000100 +#define LP_CTL_SRTC_INVAL_EN 0x00000010 +#define LP_CTL_WAKE_INT_EN 0x00000008 +#define LP_CTL_MONOCTR_EN 0x00000004 +#define LP_CTL_TIMEALARM_EN 0x00000002 +#define LP_CTL_SRTC_EN 0x00000001 + +#define LP_MKEYCTL_ZMKECC_SHIFT 8 +#define LP_MKEYCTL_ZMKECC_MASK (0xff << LP_MKEYCTL_ZMKECC_SHIFT) +#define LP_MKEYCTL_ZMKECC_EN 0x00000010 +#define LP_MKEYCTL_ZMKECC_VAL 0x00000008 +#define LP_MKEYCTL_ZMKECC_PROG 0x00000004 +#define LP_MKEYCTL_MKSEL_SHIFT 0 +#define LP_MKEYCTL_MKSEL_MASK (3 << LP_MKEYCTL_MKSEL_SHIFT) +#define LP_MKEYCTL_MK_OTP 0 +#define LP_MKEYCTL_MK_ZMK 2 +#define LP_MKEYCTL_MK_COMB 3 + +#define LP_SECVIO_CTL_SRC5 0x20 +#define LP_SECVIO_CTL_SRC4 0x10 +#define LP_SECVIO_CTL_SRC3 0x08 +#define LP_SECVIO_CTL_SRC2 0x04 +#define LP_SECVIO_CTL_SRC1 0x02 +#define LP_SECVIO_CTL_SRC0 0x01 + +#define LP_TAMPFILT_EXT2_EN 0x80000000 +#define LP_TAMPFILT_EXT2_SHIFT 24 +#define LP_TAMPFILT_EXT2_MASK (0x1f << LP_TAMPFILT_EXT2_SHIFT) +#define LP_TAMPFILT_EXT1_EN 0x00800000 +#define LP_TAMPFILT_EXT1_SHIFT 16 +#define LP_TAMPFILT_EXT1_MASK (0x1f << LP_TAMPFILT_EXT1_SHIFT) +#define LP_TAMPFILT_WM_EN 0x00000080 +#define LP_TAMPFILT_WM_SHIFT 0 +#define LP_TAMPFILT_WM_MASK (0x1f << LP_TAMPFILT_WM_SHIFT) + +#define LP_TAMPDET_OSC_BPS 0x10000000 +#define LP_TAMPDET_VRC_SHIFT 24 +#define LP_TAMPDET_VRC_MASK (3 << LP_TAMPFILT_VRC_SHIFT) +#define LP_TAMPDET_HTDC_SHIFT 20 +#define LP_TAMPDET_HTDC_MASK (3 << LP_TAMPFILT_HTDC_SHIFT) +#define LP_TAMPDET_LTDC_SHIFT 16 +#define LP_TAMPDET_LTDC_MASK (3 << LP_TAMPFILT_LTDC_SHIFT) +#define LP_TAMPDET_POR_OBS 0x00008000 +#define LP_TAMPDET_PFD_OBS 0x00004000 +#define LP_TAMPDET_ET2_EN 0x00000400 +#define LP_TAMPDET_ET1_EN 0x00000200 +#define LP_TAMPDET_WMT2_EN 0x00000100 +#define LP_TAMPDET_WMT1_EN 0x00000080 +#define LP_TAMPDET_VT_EN 0x00000040 +#define LP_TAMPDET_TT_EN 0x00000020 +#define LP_TAMPDET_CT_EN 0x00000010 +#define LP_TAMPDET_MCR_EN 0x00000004 +#define LP_TAMPDET_SRTCR_EN 0x00000002 + +#define LP_STATUS_SECURE +#define LP_STATUS_NONSECURE +#define LP_STATUS_SCANEXIT 0x00100000 /* all write 1 clear here on */ +#define LP_STATUS_EXT_SECVIO 0x00010000 +#define LP_STATUS_ET2 0x00000400 +#define LP_STATUS_ET1 0x00000200 +#define LP_STATUS_WMT2 0x00000100 +#define LP_STATUS_WMT1 0x00000080 +#define LP_STATUS_VTD 0x00000040 +#define LP_STATUS_TTD 0x00000020 +#define LP_STATUS_CTD 0x00000010 +#define LP_STATUS_PGD 0x00000008 +#define LP_STATUS_MCR 0x00000004 +#define LP_STATUS_SRTCR 0x00000002 +#define LP_STATUS_LPTA 0x00000001 + +/* Full SNVS register page, including version/options */ +struct snvs_full { + struct snvs_hp hp; + struct snvs_lp lp; + u32 rsvd[731]; /* deadspace 0x08c-0xbf7 */ + + /* Version / Revision / Option ID space - end of register page */ + u32 vid; /* 0xbf8 HP Version ID (VID 1) */ + u32 opt_rev; /* 0xbfc HP Options / Revision (VID 2) */ +}; + +#endif /* SNVSREGS_H */