|
@@ -16,82 +16,75 @@
|
|
|
#include "error.h"
|
|
|
#include "ctrl.h"
|
|
|
|
|
|
-static int caam_remove(struct platform_device *pdev)
|
|
|
-{
|
|
|
- struct device *ctrldev;
|
|
|
- struct caam_drv_private *ctrlpriv;
|
|
|
- struct caam_drv_private_jr *jrpriv;
|
|
|
- struct caam_full __iomem *topregs;
|
|
|
- int ring, ret = 0;
|
|
|
-
|
|
|
- ctrldev = &pdev->dev;
|
|
|
- ctrlpriv = dev_get_drvdata(ctrldev);
|
|
|
- topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
|
|
|
-
|
|
|
- /* shut down JobRs */
|
|
|
- for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) {
|
|
|
- ret |= caam_jr_shutdown(ctrlpriv->jrdev[ring]);
|
|
|
- jrpriv = dev_get_drvdata(ctrlpriv->jrdev[ring]);
|
|
|
- irq_dispose_mapping(jrpriv->irq);
|
|
|
- }
|
|
|
-
|
|
|
- /* Shut down debug views */
|
|
|
-#ifdef CONFIG_DEBUG_FS
|
|
|
- debugfs_remove_recursive(ctrlpriv->dfs_root);
|
|
|
-#endif
|
|
|
-
|
|
|
- /* Unmap controller region */
|
|
|
- iounmap(&topregs->ctrl);
|
|
|
-
|
|
|
- kfree(ctrlpriv->jrdev);
|
|
|
- kfree(ctrlpriv);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Descriptor to instantiate RNG State Handle 0 in normal mode and
|
|
|
* load the JDKEK, TDKEK and TDSK registers
|
|
|
*/
|
|
|
-static void build_instantiation_desc(u32 *desc)
|
|
|
+static void build_instantiation_desc(u32 *desc, int handle, int do_sk)
|
|
|
{
|
|
|
- u32 *jump_cmd;
|
|
|
+ u32 *jump_cmd, op_flags;
|
|
|
|
|
|
init_job_desc(desc, 0);
|
|
|
|
|
|
+ op_flags = OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
|
|
|
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT;
|
|
|
+
|
|
|
/* INIT RNG in non-test mode */
|
|
|
- append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
|
|
|
- OP_ALG_AS_INIT);
|
|
|
+ append_operation(desc, op_flags);
|
|
|
+
|
|
|
+ if (!handle && do_sk) {
|
|
|
+ /*
|
|
|
+ * For SH0, Secure Keys must be generated as well
|
|
|
+ */
|
|
|
+
|
|
|
+ /* wait for done */
|
|
|
+ jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
|
|
|
+ set_jump_tgt_here(desc, jump_cmd);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * load 1 to clear written reg:
|
|
|
+ * resets the done interrrupt and returns the RNG to idle.
|
|
|
+ */
|
|
|
+ append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
|
|
|
+
|
|
|
+ /* Initialize State Handle */
|
|
|
+ append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
|
|
|
+ OP_ALG_AAI_RNG4_SK);
|
|
|
+ }
|
|
|
|
|
|
- /* wait for done */
|
|
|
- jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
|
|
|
- set_jump_tgt_here(desc, jump_cmd);
|
|
|
+ append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
|
|
|
+}
|
|
|
|
|
|
- /*
|
|
|
- * load 1 to clear written reg:
|
|
|
- * resets the done interrupt and returns the RNG to idle.
|
|
|
- */
|
|
|
- append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
|
|
|
+/* Descriptor for deinstantiation of State Handle 0 of the RNG block. */
|
|
|
+static void build_deinstantiation_desc(u32 *desc, int handle)
|
|
|
+{
|
|
|
+ init_job_desc(desc, 0);
|
|
|
|
|
|
- /* generate secure keys (non-test) */
|
|
|
+ /* Uninstantiate State Handle 0 */
|
|
|
append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
|
|
|
- OP_ALG_RNG4_SK);
|
|
|
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INITFINAL);
|
|
|
+
|
|
|
+ append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
|
|
|
}
|
|
|
|
|
|
-static int instantiate_rng(struct device *ctrldev)
|
|
|
+/*
|
|
|
+ * run_descriptor_deco0 - runs a descriptor on DECO0, under direct control of
|
|
|
+ * the software (no JR/QI used).
|
|
|
+ * @ctrldev - pointer to device
|
|
|
+ * @status - descriptor status, after being run
|
|
|
+ *
|
|
|
+ * Return: - 0 if no error occurred
|
|
|
+ * - -ENODEV if the DECO couldn't be acquired
|
|
|
+ * - -EAGAIN if an error occurred while executing the descriptor
|
|
|
+ */
|
|
|
+static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
|
|
|
+ u32 *status)
|
|
|
{
|
|
|
struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
|
|
|
struct caam_full __iomem *topregs;
|
|
|
unsigned int timeout = 100000;
|
|
|
- u32 *desc;
|
|
|
- int i, ret = 0;
|
|
|
-
|
|
|
- desc = kmalloc(CAAM_CMD_SZ * 6, GFP_KERNEL | GFP_DMA);
|
|
|
- if (!desc) {
|
|
|
- dev_err(ctrldev, "can't allocate RNG init descriptor memory\n");
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
- build_instantiation_desc(desc);
|
|
|
+ u32 deco_dbg_reg, flags;
|
|
|
+ int i;
|
|
|
|
|
|
/* Set the bit to request direct access to DECO0 */
|
|
|
topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
|
|
@@ -103,36 +96,219 @@ static int instantiate_rng(struct device *ctrldev)
|
|
|
|
|
|
if (!timeout) {
|
|
|
dev_err(ctrldev, "failed to acquire DECO 0\n");
|
|
|
- ret = -EIO;
|
|
|
- goto out;
|
|
|
+ clrbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
|
|
|
+ return -ENODEV;
|
|
|
}
|
|
|
|
|
|
for (i = 0; i < desc_len(desc); i++)
|
|
|
- topregs->deco.descbuf[i] = *(desc + i);
|
|
|
+ wr_reg32(&topregs->deco.descbuf[i], *(desc + i));
|
|
|
+
|
|
|
+ flags = DECO_JQCR_WHL;
|
|
|
+ /*
|
|
|
+ * If the descriptor length is longer than 4 words, then the
|
|
|
+ * FOUR bit in JRCTRL register must be set.
|
|
|
+ */
|
|
|
+ if (desc_len(desc) >= 4)
|
|
|
+ flags |= DECO_JQCR_FOUR;
|
|
|
|
|
|
- wr_reg32(&topregs->deco.jr_ctl_hi, DECO_JQCR_WHL | DECO_JQCR_FOUR);
|
|
|
+ /* Instruct the DECO to execute it */
|
|
|
+ wr_reg32(&topregs->deco.jr_ctl_hi, flags);
|
|
|
|
|
|
timeout = 10000000;
|
|
|
- while ((rd_reg32(&topregs->deco.desc_dbg) & DECO_DBG_VALID) &&
|
|
|
- --timeout)
|
|
|
+ do {
|
|
|
+ deco_dbg_reg = rd_reg32(&topregs->deco.desc_dbg);
|
|
|
+ /*
|
|
|
+ * If an error occured in the descriptor, then
|
|
|
+ * the DECO status field will be set to 0x0D
|
|
|
+ */
|
|
|
+ if ((deco_dbg_reg & DESC_DBG_DECO_STAT_MASK) ==
|
|
|
+ DESC_DBG_DECO_STAT_HOST_ERR)
|
|
|
+ break;
|
|
|
cpu_relax();
|
|
|
+ } while ((deco_dbg_reg & DESC_DBG_DECO_STAT_VALID) && --timeout);
|
|
|
|
|
|
- if (!timeout) {
|
|
|
- dev_err(ctrldev, "failed to instantiate RNG\n");
|
|
|
- ret = -EIO;
|
|
|
- }
|
|
|
+ *status = rd_reg32(&topregs->deco.op_status_hi) &
|
|
|
+ DECO_OP_STATUS_HI_ERR_MASK;
|
|
|
|
|
|
+ /* Mark the DECO as free */
|
|
|
clrbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
|
|
|
-out:
|
|
|
+
|
|
|
+ if (!timeout)
|
|
|
+ return -EAGAIN;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * instantiate_rng - builds and executes a descriptor on DECO0,
|
|
|
+ * which initializes the RNG block.
|
|
|
+ * @ctrldev - pointer to device
|
|
|
+ * @state_handle_mask - bitmask containing the instantiation status
|
|
|
+ * for the RNG4 state handles which exist in
|
|
|
+ * the RNG4 block: 1 if it's been instantiated
|
|
|
+ * by an external entry, 0 otherwise.
|
|
|
+ * @gen_sk - generate data to be loaded into the JDKEK, TDKEK and TDSK;
|
|
|
+ * Caution: this can be done only once; if the keys need to be
|
|
|
+ * regenerated, a POR is required
|
|
|
+ *
|
|
|
+ * 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
|
|
|
+ * f.i. there was a RNG hardware error due to not "good enough"
|
|
|
+ * entropy being aquired.
|
|
|
+ */
|
|
|
+static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
|
|
|
+ int gen_sk)
|
|
|
+{
|
|
|
+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
|
|
|
+ struct caam_full __iomem *topregs;
|
|
|
+ struct rng4tst __iomem *r4tst;
|
|
|
+ u32 *desc, status, rdsta_val;
|
|
|
+ int ret = 0, sh_idx;
|
|
|
+
|
|
|
+ topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
|
|
|
+ r4tst = &topregs->ctrl.r4tst[0];
|
|
|
+
|
|
|
+ desc = kmalloc(CAAM_CMD_SZ * 7, GFP_KERNEL);
|
|
|
+ if (!desc)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
|
|
|
+ /*
|
|
|
+ * If the corresponding bit is set, this state handle
|
|
|
+ * was initialized by somebody else, so it's left alone.
|
|
|
+ */
|
|
|
+ if ((1 << sh_idx) & state_handle_mask)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /* Create the descriptor for instantiating RNG State Handle */
|
|
|
+ build_instantiation_desc(desc, sh_idx, gen_sk);
|
|
|
+
|
|
|
+ /* Try to run it through DECO0 */
|
|
|
+ ret = run_descriptor_deco0(ctrldev, desc, &status);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If ret is not 0, or descriptor status is not 0, then
|
|
|
+ * something went wrong. No need to try the next state
|
|
|
+ * handle (if available), bail out here.
|
|
|
+ * Also, if for some reason, the State Handle didn't get
|
|
|
+ * instantiated although the descriptor has finished
|
|
|
+ * without any error (HW optimizations for later
|
|
|
+ * CAAM eras), then try again.
|
|
|
+ */
|
|
|
+ rdsta_val =
|
|
|
+ rd_reg32(&topregs->ctrl.r4tst[0].rdsta) & RDSTA_IFMASK;
|
|
|
+ if (status || !(rdsta_val & (1 << sh_idx)))
|
|
|
+ ret = -EAGAIN;
|
|
|
+ if (ret)
|
|
|
+ break;
|
|
|
+
|
|
|
+ dev_info(ctrldev, "Instantiated RNG4 SH%d\n", sh_idx);
|
|
|
+ /* Clear the contents before recreating the descriptor */
|
|
|
+ memset(desc, 0x00, CAAM_CMD_SZ * 7);
|
|
|
+ }
|
|
|
+
|
|
|
kfree(desc);
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * By default, the TRNG runs for 200 clocks per sample;
|
|
|
- * 1600 clocks per sample generates better entropy.
|
|
|
+ * deinstantiate_rng - builds and executes a descriptor on DECO0,
|
|
|
+ * which deinitializes the RNG block.
|
|
|
+ * @ctrldev - pointer to device
|
|
|
+ * @state_handle_mask - bitmask containing the instantiation status
|
|
|
+ * for the RNG4 state handles which exist in
|
|
|
+ * the RNG4 block: 1 if it's been instantiated
|
|
|
+ *
|
|
|
+ * 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 void kick_trng(struct platform_device *pdev)
|
|
|
+static int deinstantiate_rng(struct device *ctrldev, int state_handle_mask)
|
|
|
+{
|
|
|
+ u32 *desc, status;
|
|
|
+ int sh_idx, ret = 0;
|
|
|
+
|
|
|
+ desc = kmalloc(CAAM_CMD_SZ * 3, GFP_KERNEL);
|
|
|
+ if (!desc)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
|
|
|
+ /*
|
|
|
+ * If the corresponding bit is set, then it means the state
|
|
|
+ * handle was initialized by us, and thus it needs to be
|
|
|
+ * deintialized as well
|
|
|
+ */
|
|
|
+ if ((1 << sh_idx) & state_handle_mask) {
|
|
|
+ /*
|
|
|
+ * Create the descriptor for deinstantating this state
|
|
|
+ * handle
|
|
|
+ */
|
|
|
+ build_deinstantiation_desc(desc, sh_idx);
|
|
|
+
|
|
|
+ /* Try to run it through DECO0 */
|
|
|
+ ret = run_descriptor_deco0(ctrldev, desc, &status);
|
|
|
+
|
|
|
+ if (ret || status) {
|
|
|
+ dev_err(ctrldev,
|
|
|
+ "Failed to deinstantiate RNG4 SH%d\n",
|
|
|
+ sh_idx);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ dev_info(ctrldev, "Deinstantiated RNG4 SH%d\n", sh_idx);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ kfree(desc);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int caam_remove(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ struct device *ctrldev;
|
|
|
+ struct caam_drv_private *ctrlpriv;
|
|
|
+ struct caam_full __iomem *topregs;
|
|
|
+ int ring, ret = 0;
|
|
|
+
|
|
|
+ ctrldev = &pdev->dev;
|
|
|
+ ctrlpriv = dev_get_drvdata(ctrldev);
|
|
|
+ topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
|
|
|
+
|
|
|
+ /* Remove platform devices for JobRs */
|
|
|
+ for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) {
|
|
|
+ if (ctrlpriv->jrpdev[ring])
|
|
|
+ of_device_unregister(ctrlpriv->jrpdev[ring]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* De-initialize RNG state handles initialized by this driver. */
|
|
|
+ if (ctrlpriv->rng4_sh_init)
|
|
|
+ deinstantiate_rng(ctrldev, ctrlpriv->rng4_sh_init);
|
|
|
+
|
|
|
+ /* Shut down debug views */
|
|
|
+#ifdef CONFIG_DEBUG_FS
|
|
|
+ debugfs_remove_recursive(ctrlpriv->dfs_root);
|
|
|
+#endif
|
|
|
+
|
|
|
+ /* Unmap controller region */
|
|
|
+ iounmap(&topregs->ctrl);
|
|
|
+
|
|
|
+ kfree(ctrlpriv->jrpdev);
|
|
|
+ kfree(ctrlpriv);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * kick_trng - sets the various parameters for enabling the initialization
|
|
|
+ * of the RNG4 block in CAAM
|
|
|
+ * @pdev - pointer to the platform device
|
|
|
+ * @ent_delay - Defines the length (in system clocks) of each entropy sample.
|
|
|
+ */
|
|
|
+static void kick_trng(struct platform_device *pdev, int ent_delay)
|
|
|
{
|
|
|
struct device *ctrldev = &pdev->dev;
|
|
|
struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
|
|
@@ -145,14 +321,31 @@ static void kick_trng(struct platform_device *pdev)
|
|
|
|
|
|
/* put RNG4 into program mode */
|
|
|
setbits32(&r4tst->rtmctl, RTMCTL_PRGM);
|
|
|
- /* 1600 clocks per sample */
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Performance-wise, it does not make sense to
|
|
|
+ * set the delay to a value that is lower
|
|
|
+ * than the last one that worked (i.e. the state handles
|
|
|
+ * were instantiated properly. Thus, instead of wasting
|
|
|
+ * time trying to set the values controlling the sample
|
|
|
+ * frequency, the function simply returns.
|
|
|
+ */
|
|
|
+ val = (rd_reg32(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK)
|
|
|
+ >> RTSDCTL_ENT_DLY_SHIFT;
|
|
|
+ if (ent_delay <= val) {
|
|
|
+ /* put RNG4 into run mode */
|
|
|
+ clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
val = rd_reg32(&r4tst->rtsdctl);
|
|
|
- val = (val & ~RTSDCTL_ENT_DLY_MASK) | (1600 << RTSDCTL_ENT_DLY_SHIFT);
|
|
|
+ val = (val & ~RTSDCTL_ENT_DLY_MASK) |
|
|
|
+ (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
|
|
|
wr_reg32(&r4tst->rtsdctl, val);
|
|
|
- /* min. freq. count */
|
|
|
- wr_reg32(&r4tst->rtfrqmin, 400);
|
|
|
- /* max. freq. count */
|
|
|
- wr_reg32(&r4tst->rtfrqmax, 6400);
|
|
|
+ /* min. freq. count, equal to 1/4 of the entropy sample length */
|
|
|
+ wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2);
|
|
|
+ /* max. freq. count, equal to 8 times the entropy sample length */
|
|
|
+ wr_reg32(&r4tst->rtfrqmax, ent_delay << 3);
|
|
|
/* put RNG4 into run mode */
|
|
|
clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
|
|
|
}
|
|
@@ -193,7 +386,7 @@ EXPORT_SYMBOL(caam_get_era);
|
|
|
/* Probe routine for CAAM top (controller) level */
|
|
|
static int caam_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
- int ret, ring, rspec;
|
|
|
+ int ret, ring, rspec, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
|
|
|
u64 caam_id;
|
|
|
struct device *dev;
|
|
|
struct device_node *nprop, *np;
|
|
@@ -258,8 +451,9 @@ static int caam_probe(struct platform_device *pdev)
|
|
|
rspec++;
|
|
|
}
|
|
|
|
|
|
- ctrlpriv->jrdev = kzalloc(sizeof(struct device *) * rspec, GFP_KERNEL);
|
|
|
- if (ctrlpriv->jrdev == NULL) {
|
|
|
+ ctrlpriv->jrpdev = kzalloc(sizeof(struct platform_device *) * rspec,
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (ctrlpriv->jrpdev == NULL) {
|
|
|
iounmap(&topregs->ctrl);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
@@ -267,13 +461,24 @@ static int caam_probe(struct platform_device *pdev)
|
|
|
ring = 0;
|
|
|
ctrlpriv->total_jobrs = 0;
|
|
|
for_each_compatible_node(np, NULL, "fsl,sec-v4.0-job-ring") {
|
|
|
- caam_jr_probe(pdev, np, ring);
|
|
|
+ ctrlpriv->jrpdev[ring] =
|
|
|
+ of_platform_device_create(np, NULL, dev);
|
|
|
+ if (!ctrlpriv->jrpdev[ring]) {
|
|
|
+ pr_warn("JR%d Platform device creation error\n", ring);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
ctrlpriv->total_jobrs++;
|
|
|
ring++;
|
|
|
}
|
|
|
if (!ring) {
|
|
|
for_each_compatible_node(np, NULL, "fsl,sec4.0-job-ring") {
|
|
|
- caam_jr_probe(pdev, np, ring);
|
|
|
+ ctrlpriv->jrpdev[ring] =
|
|
|
+ of_platform_device_create(np, NULL, dev);
|
|
|
+ if (!ctrlpriv->jrpdev[ring]) {
|
|
|
+ pr_warn("JR%d Platform device creation error\n",
|
|
|
+ ring);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
ctrlpriv->total_jobrs++;
|
|
|
ring++;
|
|
|
}
|
|
@@ -299,16 +504,55 @@ static int caam_probe(struct platform_device *pdev)
|
|
|
|
|
|
/*
|
|
|
* If SEC has RNG version >= 4 and RNG state handle has not been
|
|
|
- * already instantiated ,do RNG instantiation
|
|
|
+ * already instantiated, do RNG instantiation
|
|
|
*/
|
|
|
- if ((cha_vid & CHA_ID_RNG_MASK) >> CHA_ID_RNG_SHIFT >= 4 &&
|
|
|
- !(rd_reg32(&topregs->ctrl.r4tst[0].rdsta) & RDSTA_IF0)) {
|
|
|
- kick_trng(pdev);
|
|
|
- ret = instantiate_rng(dev);
|
|
|
+ if ((cha_vid & CHA_ID_RNG_MASK) >> CHA_ID_RNG_SHIFT >= 4) {
|
|
|
+ ctrlpriv->rng4_sh_init =
|
|
|
+ rd_reg32(&topregs->ctrl.r4tst[0].rdsta);
|
|
|
+ /*
|
|
|
+ * If the secure keys (TDKEK, JDKEK, TDSK), were already
|
|
|
+ * generated, signal this to the function that is instantiating
|
|
|
+ * the state handles. An error would occur if RNG4 attempts
|
|
|
+ * to regenerate these keys before the next POR.
|
|
|
+ */
|
|
|
+ gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1;
|
|
|
+ ctrlpriv->rng4_sh_init &= RDSTA_IFMASK;
|
|
|
+ do {
|
|
|
+ int inst_handles =
|
|
|
+ rd_reg32(&topregs->ctrl.r4tst[0].rdsta) &
|
|
|
+ RDSTA_IFMASK;
|
|
|
+ /*
|
|
|
+ * If either SH were instantiated by somebody else
|
|
|
+ * (e.g. u-boot) then it is assumed that the entropy
|
|
|
+ * parameters are properly set and thus the function
|
|
|
+ * setting these (kick_trng(...)) is skipped.
|
|
|
+ * Also, if a handle was instantiated, do not change
|
|
|
+ * the TRNG parameters.
|
|
|
+ */
|
|
|
+ if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
|
|
|
+ kick_trng(pdev, ent_delay);
|
|
|
+ ent_delay += 400;
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * if instantiate_rng(...) fails, the loop will rerun
|
|
|
+ * and the kick_trng(...) function will modfiy the
|
|
|
+ * upper and lower limits of the entropy sampling
|
|
|
+ * interval, leading to a sucessful initialization of
|
|
|
+ * the RNG.
|
|
|
+ */
|
|
|
+ ret = instantiate_rng(dev, inst_handles,
|
|
|
+ gen_sk);
|
|
|
+ } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
|
|
|
if (ret) {
|
|
|
+ dev_err(dev, "failed to instantiate RNG");
|
|
|
caam_remove(pdev);
|
|
|
return ret;
|
|
|
}
|
|
|
+ /*
|
|
|
+ * Set handles init'ed by this module as the complement of the
|
|
|
+ * already initialized ones
|
|
|
+ */
|
|
|
+ ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_IFMASK;
|
|
|
|
|
|
/* Enable RDB bit so that RNG works faster */
|
|
|
setbits32(&topregs->ctrl.scfgr, SCFGR_RDBENABLE);
|