MLK-10897-1 ARM: imx7d: Add CAAM support for i.mx7d
authorDan Douglass <dan.douglass@freescale.com>
Thu, 14 May 2015 21:28:52 +0000 (16:28 -0500)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:49:55 +0000 (14:49 -0500)
CAAM only has a single clock in i.mx7d. Logic was added to initialize only the
single clock.

The Secure Memory registers moved in CAAM era included in i.mx7d. This required
changes to support access to two different versions of the register map. The
registers are access through a data structure that overlay the register region.
Two new Secure Memory register structures were created to support the different
versions. Logic was also added to determine which version is implemented based on
the CAAM era, and access functions were added to support register access to the
Secure Memory Command and Status registers.

Signed-off-by: Dan Douglass <dan.douglass@freescale.com>
drivers/crypto/caam/ctrl.c
drivers/crypto/caam/regs.h
drivers/crypto/caam/sm.h
drivers/crypto/caam/sm_store.c

index db0f280..5f18460 100644 (file)
@@ -507,57 +507,61 @@ static int caam_probe(struct platform_device *pdev)
        }
        ctrlpriv->caam_ipg = clk;
 
-       clk = caam_drv_identify_clk(&pdev->dev, "mem");
-       if (IS_ERR(clk)) {
-               ret = PTR_ERR(clk);
-               dev_err(&pdev->dev,
-                       "can't identify CAAM mem clk: %d\n", ret);
-               return ret;
-       }
-       ctrlpriv->caam_mem = clk;
-
-       clk = caam_drv_identify_clk(&pdev->dev, "aclk");
-       if (IS_ERR(clk)) {
-               ret = PTR_ERR(clk);
-               dev_err(&pdev->dev,
-                       "can't identify CAAM aclk clk: %d\n", ret);
-               return ret;
-       }
-       ctrlpriv->caam_aclk = clk;
-
-       clk = caam_drv_identify_clk(&pdev->dev, "emi_slow");
-       if (IS_ERR(clk)) {
-               ret = PTR_ERR(clk);
-               dev_err(&pdev->dev,
-                       "can't identify CAAM emi_slow clk: %d\n", ret);
-               return ret;
-       }
-       ctrlpriv->caam_emi_slow = clk;
-
        ret = clk_prepare_enable(ctrlpriv->caam_ipg);
        if (ret < 0) {
                dev_err(&pdev->dev, "can't enable CAAM ipg clock: %d\n", ret);
                return ret;
        }
 
-       ret = clk_prepare_enable(ctrlpriv->caam_mem);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n",
-                       ret);
-               goto disable_caam_ipg;
-       }
+       /* imx7d only has one caam clock */
+       if (!(of_find_compatible_node(NULL, NULL, "fsl,imx7d-caam"))) {
 
-       ret = clk_prepare_enable(ctrlpriv->caam_aclk);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n", ret);
-               goto disable_caam_mem;
-       }
+               clk = caam_drv_identify_clk(&pdev->dev, "mem");
+               if (IS_ERR(clk)) {
+                       ret = PTR_ERR(clk);
+                       dev_err(&pdev->dev,
+                               "can't identify CAAM mem clk: %d\n", ret);
+                       goto disable_caam_ipg;
+               }
+               ctrlpriv->caam_mem = clk;
+
+               clk = caam_drv_identify_clk(&pdev->dev, "aclk");
+               if (IS_ERR(clk)) {
+                       ret = PTR_ERR(clk);
+                       dev_err(&pdev->dev,
+                               "can't identify CAAM aclk clk: %d\n", ret);
+                       goto disable_caam_ipg;
+               }
+               ctrlpriv->caam_aclk = clk;
+
+               clk = caam_drv_identify_clk(&pdev->dev, "emi_slow");
+               if (IS_ERR(clk)) {
+                       ret = PTR_ERR(clk);
+                       dev_err(&pdev->dev,
+                               "can't identify CAAM emi_slow clk: %d\n", ret);
+                       goto disable_caam_ipg;
+               }
+               ctrlpriv->caam_emi_slow = clk;
 
-       ret = clk_prepare_enable(ctrlpriv->caam_emi_slow);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n",
-                       ret);
-               goto disable_caam_aclk;
+               ret = clk_prepare_enable(ctrlpriv->caam_mem);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n",
+                               ret);
+                       goto disable_caam_ipg;
+               }
+
+               ret = clk_prepare_enable(ctrlpriv->caam_aclk);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n", ret);
+                       goto disable_caam_mem;
+               }
+
+               ret = clk_prepare_enable(ctrlpriv->caam_emi_slow);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n",
+                               ret);
+                       goto disable_caam_aclk;
+               }
        }
 
        /* Get configuration properties from device tree */
@@ -596,7 +600,6 @@ static int caam_probe(struct platform_device *pdev)
 
        /* Get CAAM-SM node and of_iomap() and save */
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-sm");
-
        if (!np)
                return -ENODEV;
 
index ddb526e..e51c4e2 100644 (file)
@@ -595,6 +595,34 @@ struct caam_ctrl {
 #define JRSTART_JR2_START       0x00000004 /* Start Job ring 2 */
 #define JRSTART_JR3_START       0x00000008 /* Start Job ring 3 */
 
+/* Secure Memory Configuration - if you have it */
+/* Secure Memory Register Offset from JR Base Reg*/
+#define SM_V1_OFFSET 0x0f4
+#define SM_V2_OFFSET 0xa00
+
+/* Minimum SM Version ID requiring v2 SM register mapping */
+#define SMVID_V2 0x20105
+
+struct caam_secure_mem_v1 {
+       u32 sm_cmd;     /* SMCJRx - Secure memory command */
+       u32 rsvd1;
+       u32 sm_status;  /* SMCSJRx - Secure memory status */
+
+       u32 sm_perm;    /* SMAPJRx - Secure memory access perms */
+       u32 sm_group2;  /* SMAP2JRx - Secure memory access group 2 */
+       u32 sm_group1;  /* SMAP1JRx - Secure memory access group 1 */
+};
+
+struct caam_secure_mem_v2 {
+       u32 sm_perm;    /* SMAPJRx - Secure memory access perms */
+       u32 sm_group2;  /* SMAP2JRx - Secure memory access group 2 */
+       u32 sm_group1;  /* SMAP1JRx - Secure memory access group 1 */
+       u32 rsvd1[118];
+       u32 sm_cmd;     /* SMCJRx - Secure memory command */
+       u32 rsvd2;
+       u32 sm_status;  /* SMCSJRx - Secure memory status */
+};
+
 /*
  * caam_job_ring - direct job ring setup
  * 1-4 possible per instantiation, base + 1000/2000/3000/4000
@@ -636,19 +664,7 @@ struct caam_job_ring {
        /* Command/control */
        u32 rsvd11;
        u32 jrcommand;  /* JRCRx - JobR command */
-
-       u32 rsvd12[33];
-
-       /* Secure Memory Configuration - if you have it */
-       u32 sm_cmd;     /* SMCJRx - Secure memory command */
-       u32 rsvd13;
-       u32 sm_status;  /* SMCSJRx - Secure memory status */
-       u32 rsvd14;
-       u32 sm_perm;    /* SMAPJRx - Secure memory access perms */
-       u32 sm_group2;  /* SMAP2JRx - Secure memory access group 2 */
-       u32 sm_group1;  /* SMAP1JRx - Secure memory access group 1 */
-
-       u32 rsvd15[891];
+       u32 rsvd12[931];
 
        /* Performance Monitor                                  f00-fff */
        struct caam_perfmon perfmon;
index c8114d1..65ec9d7 100644 (file)
@@ -96,6 +96,9 @@ struct caam_drv_private_sm {
        struct platform_device *sm_pdev;  /* Secure Memory platform device */
        spinlock_t kslock ____cacheline_aligned;
 
+       /* SM Register offset from JR base address */
+       u32 sm_reg_offset;
+
        /* Default parameters for geometry */
        u32 max_pages;          /* maximum pages this instance can support */
        u32 top_partition;      /* highest partition number in this instance */
index 51c1f2e..21d4d82 100644 (file)
@@ -58,6 +58,50 @@ void sm_show_page(struct device *dev, struct sm_page_descriptor *pgdesc)
 
 #define INITIAL_DESCSZ 16      /* size of tmp buffer for descriptor const. */
 
+static __always_inline int sm_set_cmd_reg(struct caam_drv_private_sm *smpriv,
+                                         struct caam_drv_private_jr *jrpriv,
+                                         u32 val)
+{
+
+       if (smpriv->sm_reg_offset == SM_V1_OFFSET) {
+               struct caam_secure_mem_v1 *sm_regs_v1;
+               sm_regs_v1 = (struct caam_secure_mem_v1 *)
+                       ((void *)jrpriv->rregs + SM_V1_OFFSET);
+               wr_reg32(&sm_regs_v1->sm_cmd, val);
+
+       } else if (smpriv->sm_reg_offset == SM_V2_OFFSET) {
+               struct caam_secure_mem_v2 *sm_regs_v2;
+               sm_regs_v2 = (struct caam_secure_mem_v2 *)
+                       ((void *)jrpriv->rregs + SM_V2_OFFSET);
+               wr_reg32(&sm_regs_v2->sm_cmd, val);
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static __always_inline u32 sm_get_status_reg(struct caam_drv_private_sm *smpriv,
+                                            struct caam_drv_private_jr *jrpriv,
+                                            u32 *val)
+{
+       if (smpriv->sm_reg_offset == SM_V1_OFFSET) {
+               struct caam_secure_mem_v1 *sm_regs_v1;
+               sm_regs_v1 = (struct caam_secure_mem_v1 *)
+                       ((void *)jrpriv->rregs + SM_V1_OFFSET);
+               *val = rd_reg32(&sm_regs_v1->sm_status);
+       } else if (smpriv->sm_reg_offset == SM_V2_OFFSET) {
+               struct caam_secure_mem_v2 *sm_regs_v2;
+               sm_regs_v2 = (struct caam_secure_mem_v2 *)
+                       ((void *)jrpriv->rregs + SM_V2_OFFSET);
+               *val = rd_reg32(&sm_regs_v2->sm_status);
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /*
  * Construct a black key conversion job descriptor
  *
@@ -949,7 +993,7 @@ int caam_sm_startup(struct platform_device *pdev)
        struct caam_drv_private_jr *jrpriv;     /* need this for reg page */
        struct platform_device *sm_pdev;
        struct sm_page_descriptor *lpagedesc;
-       u32 page, pgstat, lpagect, detectedpage;
+       u32 page, pgstat, lpagect, detectedpage, smvid;
 
        struct device_node *np;
        ctrldev = &pdev->dev;
@@ -986,6 +1030,13 @@ int caam_sm_startup(struct platform_device *pdev)
        dev_set_drvdata(smdev, smpriv);
        ctrlpriv->smdev = smdev;
 
+       /* Set the Secure Memory Register Map Version */
+       smvid = rd_reg32(&ctrlpriv->ctrl->perfmon.smvid);
+       if (smvid < SMVID_V2)
+               smpriv->sm_reg_offset = SM_V1_OFFSET;
+       else
+               smpriv->sm_reg_offset = SM_V2_OFFSET;
+
        /*
         * Collect configuration limit data for reference
         * This batch comes from the partition data/vid registers in perfmon
@@ -994,7 +1045,7 @@ int caam_sm_startup(struct platform_device *pdev)
                            & SMPART_MAX_NUMPG_MASK) >>
                            SMPART_MAX_NUMPG_SHIFT) + 1;
        smpriv->top_partition = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart)
-                               & SMPART_MAX_PNUM_MASK) >>
+                                 & SMPART_MAX_PNUM_MASK) >>
                                SMPART_MAX_PNUM_SHIFT) + 1;
        smpriv->top_page =  ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart)
                            & SMPART_MAX_PG_MASK) >> SMPART_MAX_PG_SHIFT) + 1;
@@ -1024,6 +1075,7 @@ int caam_sm_startup(struct platform_device *pdev)
        smpriv->smringdev = &ctrlpriv->jrpdev[0]->dev;
        jrpriv = dev_get_drvdata(smpriv->smringdev);
        lpagect = 0;
+       pgstat = 0;
        lpagedesc = kzalloc(sizeof(struct sm_page_descriptor)
                            * smpriv->max_pages, GFP_KERNEL);
        if (lpagedesc == NULL) {
@@ -1032,10 +1084,13 @@ int caam_sm_startup(struct platform_device *pdev)
        }
 
        for (page = 0; page < smpriv->max_pages; page++) {
-               wr_reg32(&jrpriv->rregs->sm_cmd,
-                        ((page << SMC_PAGE_SHIFT) & SMC_PAGE_MASK) |
-                        (SMC_CMD_PAGE_INQUIRY & SMC_CMD_MASK));
-               pgstat = rd_reg32(&jrpriv->rregs->sm_status);
+               if (sm_set_cmd_reg(smpriv, jrpriv,
+                                  ((page << SMC_PAGE_SHIFT) & SMC_PAGE_MASK) |
+                                  (SMC_CMD_PAGE_INQUIRY & SMC_CMD_MASK)))
+                       return -EINVAL;
+               if (sm_get_status_reg(smpriv, jrpriv, &pgstat))
+                       return -EINVAL;
+
                if (((pgstat & SMCS_PGWON_MASK) >> SMCS_PGOWN_SHIFT)
                    == SMCS_PGOWN_OWNED) { /* our page? */
                        lpagedesc[page].phys_pagenum =