diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 3ad032f570ae..9e9215ac130e 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -44,6 +44,17 @@ static void build_instantiation_desc(u32 *desc) append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT); } +/* Descriptor for deinstantiation of State Handle 0 of the RNG block. */ +static void build_deinstantiation_desc(u32 *desc) +{ + init_job_desc(desc, 0); + + /* Uninstantiate State Handle 0 */ + append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | + OP_ALG_AS_INITFINAL); + + append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT); +} /* * run_descriptor_deco0 - runs a descriptor on DECO0, under direct control of @@ -59,7 +70,7 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc) struct caam_full __iomem *topregs; unsigned int timeout = 100000; u32 deco_dbg_reg, flags; - int i, ret = 0; + int i; /* Set the bit to request direct access to DECO0 */ topregs = (struct caam_full __iomem *)ctrlpriv->ctrl; @@ -102,11 +113,6 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc) cpu_relax(); } while ((deco_dbg_reg & DESC_DBG_DECO_STAT_VALID) && --timeout); - if (!timeout) { - dev_err(ctrldev, "failed to instantiate RNG\n"); - ret = -EIO; - } - /* Mark the DECO as free */ clrbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE); @@ -146,6 +152,39 @@ static int instantiate_rng(struct device *ctrldev) return ret; } +/* + * deinstantiate_rng - builds and executes a descriptor on DECO0, + * which deinitializes the RNG block. + * @ctrldev - pointer to device + * + * Return: - 0 if no error occurred + * - -ENOMEM if there isn't enough memory to allocate the descriptor + * - -ENODEV if DECO0 couldn't be acquired + * - -EAGAIN if an error occurred when executing the descriptor + */ +static int deinstantiate_rng(struct device *ctrldev) +{ + u32 *desc; + int i, ret = 0; + + desc = kmalloc(CAAM_CMD_SZ * 3, GFP_KERNEL); + if (!desc) + return -ENOMEM; + + /* Create the descriptor for deinstantating RNG State Handle 0 */ + build_deinstantiation_desc(desc); + + /* Try to run it through DECO0 */ + ret = run_descriptor_deco0(ctrldev, desc); + + if (ret) + dev_err(ctrldev, "failed to deinstantiate RNG\n"); + + kfree(desc); + + return ret; +} + static int caam_remove(struct platform_device *pdev) { struct device *ctrldev; @@ -165,6 +204,10 @@ static int caam_remove(struct platform_device *pdev) irq_dispose_mapping(jrpriv->irq); } + /* De-initialize RNG if it was initialized by this driver. */ + if (ctrlpriv->rng4_init) + deinstantiate_rng(ctrldev); + /* Shut down debug views */ #ifdef CONFIG_DEBUG_FS debugfs_remove_recursive(ctrlpriv->dfs_root); @@ -384,6 +427,8 @@ static int caam_probe(struct platform_device *pdev) return ret; } + ctrlpriv->rng4_init = 1; + /* Enable RDB bit so that RNG works faster */ setbits32(&topregs->ctrl.scfgr, SCFGR_RDBENABLE); } diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h index 34c4b9f7fbfa..ada24294c729 100644 --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h @@ -87,6 +87,12 @@ struct caam_drv_private { /* list of registered hash algorithms (mk generic context handle?) */ struct list_head hash_list; + /* RNG4 block */ + bool rng4_init; /* If RNG4 block is initialized by this driver, + then this will be set; if it was initialized + by another entity (e.g. u-boot), it will be + cleared. */ + /* * debugfs entries for developer view into driver/device * variables at runtime.