| From 03ec635be0eb1c1b63b1f631938d41b379dad637 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Horia=20Geant=C4=83?= <horia.geanta@nxp.com> |
| 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 <dan.douglass@nxp.com> |
| Signed-off-by: Victoria Milhoan <vicki.milhoan@freescale.com> |
| Signed-off-by: Steve Cornelius <steve.cornelius@nxp.com> |
| Signed-off-by: Fugang Duan <andy.duan@nxp.com> |
| Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com> |
| |
| 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ă <horia.geanta@nxp.com> |
| --- |
| 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 <linux/of.h> |
| +#include <linux/of_irq.h> |
| +#include <linux/of_address.h> |
| + |
| +/* 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 <linux/types.h> |
| +#include <linux/io.h> |
| + |
| +/* |
| + * 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 */ |