summaryrefslogtreecommitdiff
path: root/drivers/crypto/caam/secvio.c
diff options
context:
space:
mode:
authorVabhav Sharma <vabhav.sharma@nxp.com>2022-11-25 18:07:54 +0530
committerJason Liu <jason.hui.liu@nxp.com>2023-02-15 02:51:18 +0100
commit340935f2bc5ec4fb7566063709b403d00ac22e1e (patch)
tree44c87a6849f6969cf232ebab2f609ab4c395bf96 /drivers/crypto/caam/secvio.c
parenta6656a017abeb3675049eb6711a918aa61ac5bd6 (diff)
LF-6722: drivers/crypto: caam/snvs: SNVS state during linux boot
SNVS HP state is read incorrectly because there is Software dependency between SECVIO and CAAM driver. Added code to read SNVS version ID register which contain non-zero constants to identify the endianness of the device. This register includes a 16-bit field called IP_ID, and seems to have one of four different values 0x003A, 0x003C, 0x003E or 0x003F. Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com> Reviewed-by: Pankaj Gupta <pankaj.gupta@nxp.com> Reviewed-by: Horia Geanta <horia.geanta@nxp.com>
Diffstat (limited to 'drivers/crypto/caam/secvio.c')
-rw-r--r--drivers/crypto/caam/secvio.c62
1 files changed, 54 insertions, 8 deletions
diff --git a/drivers/crypto/caam/secvio.c b/drivers/crypto/caam/secvio.c
index d6ebe0af40fc..e319677132cf 100644
--- a/drivers/crypto/caam/secvio.c
+++ b/drivers/crypto/caam/secvio.c
@@ -3,7 +3,7 @@
* SNVS Security Violation Handler
*
* Copyright 2012-2016 Freescale Semiconductor, Inc.
- * Copyright 2017-2019 NXP
+ * Copyright 2017-2019, 2023 NXP
*/
#include "compat.h"
@@ -54,6 +54,24 @@ static const u8 *snvs_ssm_state_name[] = {
"secure",
};
+static DEFINE_STATIC_KEY_TRUE(snvs_little_end);
+
+static inline u32 secvio_read(void __iomem *reg)
+{
+ if (static_branch_likely(&snvs_little_end))
+ return ioread32(reg);
+ else
+ return ioread32be(reg);
+}
+
+static inline void secvio_write(void __iomem *reg, u32 data)
+{
+ if (static_branch_likely(&snvs_little_end))
+ iowrite32(data, reg);
+ else
+ iowrite32be(data, reg);
+}
+
/* Top-level security violation interrupt */
static irqreturn_t snvs_secvio_interrupt(int irq, void *snvsdev)
{
@@ -62,8 +80,8 @@ static irqreturn_t snvs_secvio_interrupt(int irq, void *snvsdev)
clk_enable(svpriv->clk);
/* Check the HP secvio status register */
- svpriv->irqcause = rd_reg32(&svpriv->svregs->hp.secvio_status) &
- HP_SECVIOST_SECVIOMASK;
+ svpriv->irqcause = secvio_read(&svpriv->svregs->hp.secvio_status) &
+ HP_SECVIOST_SECVIOMASK;
if (!svpriv->irqcause) {
clk_disable(svpriv->clk);
@@ -192,7 +210,7 @@ static int snvs_secvio_remove(struct platform_device *pdev)
clk_enable(svpriv->clk);
/* Set all sources to nonfatal */
- wr_reg32(&svpriv->svregs->hp.secvio_intcfg, 0);
+ secvio_write(&svpriv->svregs->hp.secvio_intcfg, 0);
/* Remove tasklets and release interrupt */
for_each_possible_cpu(i)
@@ -216,6 +234,7 @@ static int snvs_secvio_probe(struct platform_device *pdev)
u32 hpstate;
const void *jtd, *wtd, *itd, *etd;
u32 td_en;
+ u32 ipidr, ipid;
svpriv = kzalloc(sizeof(struct snvs_secvio_drv_private), GFP_KERNEL);
if (!svpriv)
@@ -281,9 +300,36 @@ static int snvs_secvio_probe(struct platform_device *pdev)
clk_prepare_enable(svpriv->clk);
+ /*
+ * Reading SNVS version ID register HPVIDR1 to identify the endianness
+ * of the device which contain non-zero constants including 16-bit field
+ * called IP_ID[Bit 31-16] having one of the four values 0x003A, 0x003C,
+ * 0x003E, 0x003F.
+ */
+ ipidr = secvio_read(&svpriv->svregs->vid);
+ ipid = ipidr >> SNVS_HPVIDR_BLOCK_ID;
+ if (ipid == SNVS_ID1 || ipid == SNVS_ID2 || ipid == SNVS_ID3 || ipid == SNVS_ID4) {
+ dev_info(svdev, "ipid matched - 0x%x\n", ipid);
+ } else {
+ /*
+ * Device endianness is not LE.Reading again SNVS version ID
+ * register value to identify the endianness of device is BE.
+ */
+ ipid = (ipidr & (u32)0x0000FF00) >> 8;
+ if (ipid == SNVS_ID1 || ipid == SNVS_ID2 || ipid == SNVS_ID3 || ipid == SNVS_ID4) {
+ dev_info(svdev, "ipid matched - 0x%x\n", ipid);
+ static_branch_disable(&snvs_little_end);
+ } else {
+ dev_err(svdev, "unable to identify secvio endianness\n");
+ iounmap(svpriv->svregs);
+ kfree(svpriv);
+ return -EINVAL;
+ }
+ }
+
/* 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);
+ secvio_write(&svpriv->svregs->hp.secvio_ctl, td_en);
+ secvio_write(&svpriv->svregs->hp.secvio_intcfg, td_en);
/* Device data set up. Now init interrupt source descriptions */
for (i = 0; i < MAX_SECVIO_SOURCES; i++) {
@@ -306,8 +352,8 @@ static int snvs_secvio_probe(struct platform_device *pdev)
return -EINVAL;
}
- hpstate = (rd_reg32(&svpriv->svregs->hp.status) &
- HP_STATUS_SSM_ST_MASK) >> HP_STATUS_SSM_ST_SHIFT;
+ hpstate = (secvio_read(&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]);