diff options
author | Dan Douglass <dan.douglass@freescale.com> | 2015-05-14 16:28:52 -0500 |
---|---|---|
committer | Nitin Garg <nitin.garg@nxp.com> | 2016-01-20 14:28:50 -0600 |
commit | 5702e5758b3ab81474aa25f579652f6345eb73b6 (patch) | |
tree | 3d6ac30bca724fb39761b4ebb4248146a2688497 /drivers | |
parent | b71be5e41fd4b61239c408b6457410292768df06 (diff) |
MLK-10897-1 ARM: imx7d: Add CAAM support for i.mx7d
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/crypto/caam/ctrl.c | 127 | ||||
-rw-r--r-- | drivers/crypto/caam/regs.h | 42 | ||||
-rw-r--r-- | drivers/crypto/caam/sm.h | 3 | ||||
-rw-r--r-- | drivers/crypto/caam/sm_store.c | 67 |
4 files changed, 164 insertions, 75 deletions
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 6eda66732fdb..463768426fd7 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -307,9 +307,12 @@ static int caam_remove(struct platform_device *pdev) #ifdef CONFIG_ARM /* shut clocks off before finalizing shutdown */ clk_disable(ctrlpriv->caam_ipg); - clk_disable(ctrlpriv->caam_mem); - clk_disable(ctrlpriv->caam_aclk); - clk_disable(ctrlpriv->caam_emi_slow); + /* imx7d only has one caam clock */ + if (!(of_find_compatible_node(NULL, NULL, "fsl,imx7d-caam"))) { + clk_disable(ctrlpriv->caam_mem); + clk_disable(ctrlpriv->caam_aclk); + clk_disable(ctrlpriv->caam_emi_slow); + } #endif kfree(ctrlpriv->jrpdev); @@ -489,7 +492,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; @@ -508,70 +510,83 @@ static int caam_probe(struct platform_device *pdev) "can't identify CAAM ipg clk: %d\n", ret); return -ENODEV; } - ctrlpriv->caam_mem = devm_clk_get(&ctrlpriv->pdev->dev, "caam_mem"); - if (IS_ERR(ctrlpriv->caam_mem)) { - ret = PTR_ERR(ctrlpriv->caam_mem); - dev_err(&ctrlpriv->pdev->dev, - "can't identify CAAM secure mem clk: %d\n", ret); - return -ENODEV; - } - ctrlpriv->caam_aclk = devm_clk_get(&ctrlpriv->pdev->dev, "caam_aclk"); - if (IS_ERR(ctrlpriv->caam_aclk)) { - ret = PTR_ERR(ctrlpriv->caam_aclk); - dev_err(&ctrlpriv->pdev->dev, - "can't identify CAAM aclk clk: %d\n", ret); - return -ENODEV; - } - - ctrlpriv->caam_emi_slow = devm_clk_get(&ctrlpriv->pdev->dev, - "caam_emi_slow"); - ret = clk_prepare_enable(ctrlpriv->caam_emi_slow); - if (ret < 0) { - dev_err(&pdev->dev, "can't prepare CAAM emi" - " slow clock: %d\n", ret); - return -ENODEV; - } - ret = clk_prepare(ctrlpriv->caam_ipg); if (ret < 0) { dev_err(&pdev->dev, "can't prepare CAAM ipg clock: %d\n", ret); return -ENODEV; } - ret = clk_prepare(ctrlpriv->caam_mem); - if (ret < 0) { - dev_err(&pdev->dev, "can't prepare CAAM secure mem clock: %d\n", - ret); - return -ENODEV; - } - ret = clk_prepare(ctrlpriv->caam_aclk); - if (ret < 0) { - dev_err(&pdev->dev, "can't prepare CAAM aclk clock: %d\n", ret); - return -ENODEV; - } - ret = clk_enable(ctrlpriv->caam_ipg); if (ret < 0) { dev_err(&pdev->dev, "can't enable CAAM ipg clock: %d\n", ret); return -ENODEV; } - ret = clk_enable(ctrlpriv->caam_mem); - if (ret < 0) { - dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n", - ret); - return -ENODEV; - } - ret = clk_enable(ctrlpriv->caam_aclk); - if (ret < 0) { - dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n", ret); - return -ENODEV; - } pr_debug("%s caam_ipg clock:%d\n", __func__, - (int)clk_get_rate(ctrlpriv->caam_ipg)); - pr_debug("%s caam_mem clock:%d\n", __func__, - (int)clk_get_rate(ctrlpriv->caam_mem)); - pr_debug("%s caam_aclk clock:%d\n", __func__, - (int)clk_get_rate(ctrlpriv->caam_aclk)); + (int)clk_get_rate(ctrlpriv->caam_ipg)); + + /* imx7d only has one caam clock */ + if (!(of_find_compatible_node(NULL, NULL, "fsl,imx7d-caam"))) { + ctrlpriv->caam_mem = devm_clk_get(&ctrlpriv->pdev->dev, + "caam_mem"); + if (IS_ERR(ctrlpriv->caam_mem)) { + ret = PTR_ERR(ctrlpriv->caam_mem); + dev_err(&ctrlpriv->pdev->dev, + "can't identify CAAM secure mem clk: %d\n", + ret); + return -ENODEV; + } + ctrlpriv->caam_aclk = devm_clk_get(&ctrlpriv->pdev->dev, + "caam_aclk"); + if (IS_ERR(ctrlpriv->caam_aclk)) { + ret = PTR_ERR(ctrlpriv->caam_aclk); + dev_err(&ctrlpriv->pdev->dev, + "can't identify CAAM aclk clk: %d\n", + ret); + return -ENODEV; + } + ctrlpriv->caam_emi_slow = devm_clk_get(&ctrlpriv->pdev->dev, + "caam_emi_slow"); + ret = clk_prepare_enable(ctrlpriv->caam_emi_slow); + if (ret < 0) { + dev_err(&pdev->dev, + "can't prepare CAAM emi slow clock: %d\n", + ret); + return -ENODEV; + } + + ret = clk_prepare(ctrlpriv->caam_mem); + if (ret < 0) { + dev_err(&pdev->dev, "can't prepare CAAM secure mem clock: %d\n", + ret); + return -ENODEV; + } + ret = clk_prepare(ctrlpriv->caam_aclk); + if (ret < 0) { + dev_err(&pdev->dev, + "can't prepare CAAM aclk clock: %d\n", + ret); + return -ENODEV; + } + + + ret = clk_enable(ctrlpriv->caam_mem); + if (ret < 0) { + dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n", + ret); + return -ENODEV; + } + ret = clk_enable(ctrlpriv->caam_aclk); + if (ret < 0) { + dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n", + ret); + return -ENODEV; + } + + pr_debug("%s caam_mem clock:%d\n", __func__, + (int)clk_get_rate(ctrlpriv->caam_mem)); + pr_debug("%s caam_aclk clock:%d\n", __func__, + (int)clk_get_rate(ctrlpriv->caam_aclk)); + } #endif /* diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index 0168b6d199bb..f590464ca225 100644 --- a/drivers/crypto/caam/regs.h +++ b/drivers/crypto/caam/regs.h @@ -542,6 +542,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 @@ -583,19 +611,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; diff --git a/drivers/crypto/caam/sm.h b/drivers/crypto/caam/sm.h index c8114d126700..65ec9d75ef56 100644 --- a/drivers/crypto/caam/sm.h +++ b/drivers/crypto/caam/sm.h @@ -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 */ diff --git a/drivers/crypto/caam/sm_store.c b/drivers/crypto/caam/sm_store.c index 51c1f2ee93e4..21d4d82157c1 100644 --- a/drivers/crypto/caam/sm_store.c +++ b/drivers/crypto/caam/sm_store.c @@ -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 = |