crypto: caam - refactor RNG initialization
authorHoria GeantA <horia.geanta@nxp.com>
Mon, 17 Apr 2023 18:28:39 +0000 (20:28 +0200)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 12 May 2023 10:48:01 +0000 (18:48 +0800)
RNG (re-)initialization will be needed on pm resume path,
thus refactor the corresponding code out of the probe callback.

Signed-off-by: Horia GeantA <horia.geanta@nxp.com>
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Reviewed-by: Gaurav Jain <gaurav.jain@nxp.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/caam/ctrl.c
drivers/crypto/caam/intern.h

index bedcc2a..5fed3cf 100644 (file)
@@ -344,13 +344,12 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
 /*
  * kick_trng - sets the various parameters for enabling the initialization
  *            of the RNG4 block in CAAM
- * @pdev - pointer to the platform device
+ * @dev - pointer to the controller device
  * @ent_delay - Defines the length (in system clocks) of each entropy sample.
  */
-static void kick_trng(struct platform_device *pdev, int ent_delay)
+static void kick_trng(struct device *dev, int ent_delay)
 {
-       struct device *ctrldev = &pdev->dev;
-       struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
+       struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
        struct caam_ctrl __iomem *ctrl;
        struct rng4tst __iomem *r4tst;
        u32 val;
@@ -618,10 +617,115 @@ static bool needs_entropy_delay_adjustment(void)
        return false;
 }
 
+static int caam_ctrl_rng_init(struct device *dev)
+{
+       struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
+       struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl;
+       int ret, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
+       u8 rng_vid;
+
+       if (ctrlpriv->era < 10) {
+               struct caam_perfmon __iomem *perfmon;
+
+               perfmon = ctrlpriv->total_jobrs ?
+                         (struct caam_perfmon __iomem *)&ctrlpriv->jr[0]->perfmon :
+                         (struct caam_perfmon __iomem *)&ctrl->perfmon;
+
+               rng_vid = (rd_reg32(&perfmon->cha_id_ls) &
+                          CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
+       } else {
+               struct version_regs __iomem *vreg;
+
+               vreg = ctrlpriv->total_jobrs ?
+                       (struct version_regs __iomem *)&ctrlpriv->jr[0]->vreg :
+                       (struct version_regs __iomem *)&ctrl->vreg;
+
+               rng_vid = (rd_reg32(&vreg->rng) & CHA_VER_VID_MASK) >>
+                         CHA_VER_VID_SHIFT;
+       }
+
+       /*
+        * If SEC has RNG version >= 4 and RNG state handle has not been
+        * already instantiated, do RNG instantiation
+        * In case of SoCs with Management Complex, RNG is managed by MC f/w.
+        */
+       if (!(ctrlpriv->mc_en && ctrlpriv->pr_support) && rng_vid >= 4) {
+               ctrlpriv->rng4_sh_init =
+                       rd_reg32(&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_MASK;
+               do {
+                       int inst_handles =
+                               rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_MASK;
+                       /*
+                        * 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 (needs_entropy_delay_adjustment())
+                               ent_delay = 12000;
+                       if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
+                               dev_info(dev,
+                                        "Entropy delay = %u\n",
+                                        ent_delay);
+                               kick_trng(dev, ent_delay);
+                               ent_delay += 400;
+                       }
+                       /*
+                        * if instantiate_rng(...) fails, the loop will rerun
+                        * and the kick_trng(...) function will modify the
+                        * upper and lower limits of the entropy sampling
+                        * interval, leading to a successful initialization of
+                        * the RNG.
+                        */
+                       ret = instantiate_rng(dev, inst_handles,
+                                             gen_sk);
+                       /*
+                        * Entropy delay is determined via TRNG characterization.
+                        * TRNG characterization is run across different voltages
+                        * and temperatures.
+                        * If worst case value for ent_dly is identified,
+                        * the loop can be skipped for that platform.
+                        */
+                       if (needs_entropy_delay_adjustment())
+                               break;
+                       if (ret == -EAGAIN)
+                               /*
+                                * if here, the loop will rerun,
+                                * so don't hog the CPU
+                                */
+                               cpu_relax();
+               } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
+               if (ret) {
+                       dev_err(dev, "failed to instantiate RNG");
+                       return ret;
+               }
+               /*
+                * Set handles initialized by this module as the complement of
+                * the already initialized ones
+                */
+               ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_MASK;
+
+               /* Enable RDB bit so that RNG works faster */
+               clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
+       }
+
+       return 0;
+}
+
 /* Probe routine for CAAM top (controller) level */
 static int caam_probe(struct platform_device *pdev)
 {
-       int ret, ring, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
+       int ret, ring;
        u64 caam_id;
        const struct soc_device_attribute *imx_soc_match;
        struct device *dev;
@@ -631,10 +735,8 @@ static int caam_probe(struct platform_device *pdev)
        struct caam_perfmon __iomem *perfmon;
        struct dentry *dfs_root;
        u32 scfgr, comp_params;
-       u8 rng_vid;
        int pg_size;
        int BLOCK_OFFSET = 0;
-       bool pr_support = false;
        bool reg_access = true;
 
        ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(*ctrlpriv), GFP_KERNEL);
@@ -770,7 +872,8 @@ static int caam_probe(struct platform_device *pdev)
 
                mc_version = fsl_mc_get_version();
                if (mc_version)
-                       pr_support = check_version(mc_version, 10, 20, 0);
+                       ctrlpriv->pr_support = check_version(mc_version, 10, 20,
+                                                            0);
                else
                        return -EPROBE_DEFER;
        }
@@ -861,9 +964,6 @@ set_dma_mask:
                return -ENOMEM;
        }
 
-       if (!reg_access)
-               goto report_live;
-
        comp_params = rd_reg32(&perfmon->comp_parms_ls);
        ctrlpriv->blob_present = !!(comp_params & CTPR_LS_BLOB);
 
@@ -873,8 +973,6 @@ set_dma_mask:
         * check both here.
         */
        if (ctrlpriv->era < 10) {
-               rng_vid = (rd_reg32(&perfmon->cha_id_ls) &
-                          CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
                ctrlpriv->blob_present = ctrlpriv->blob_present &&
                        (rd_reg32(&perfmon->cha_num_ls) & CHA_ID_LS_AES_MASK);
        } else {
@@ -884,91 +982,16 @@ set_dma_mask:
                        (struct version_regs __iomem *)&ctrlpriv->jr[0]->vreg :
                        (struct version_regs __iomem *)&ctrl->vreg;
 
-               rng_vid = (rd_reg32(&vreg->rng) & CHA_VER_VID_MASK) >>
-                          CHA_VER_VID_SHIFT;
                ctrlpriv->blob_present = ctrlpriv->blob_present &&
                        (rd_reg32(&vreg->aesa) & CHA_VER_MISC_AES_NUM_MASK);
        }
 
-       /*
-        * If SEC has RNG version >= 4 and RNG state handle has not been
-        * already instantiated, do RNG instantiation
-        * In case of SoCs with Management Complex, RNG is managed by MC f/w.
-        */
-       if (!(ctrlpriv->mc_en && pr_support) && rng_vid >= 4) {
-               ctrlpriv->rng4_sh_init =
-                       rd_reg32(&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_MASK;
-               do {
-                       int inst_handles =
-                               rd_reg32(&ctrl->r4tst[0].rdsta) &
-                                                               RDSTA_MASK;
-                       /*
-                        * 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 (needs_entropy_delay_adjustment())
-                               ent_delay = 12000;
-                       if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
-                               dev_info(dev,
-                                        "Entropy delay = %u\n",
-                                        ent_delay);
-                               kick_trng(pdev, ent_delay);
-                               ent_delay += 400;
-                       }
-                       /*
-                        * if instantiate_rng(...) fails, the loop will rerun
-                        * and the kick_trng(...) function will modify the
-                        * upper and lower limits of the entropy sampling
-                        * interval, leading to a successful initialization of
-                        * the RNG.
-                        */
-                       ret = instantiate_rng(dev, inst_handles,
-                                             gen_sk);
-                       /*
-                        * Entropy delay is determined via TRNG characterization.
-                        * TRNG characterization is run across different voltages
-                        * and temperatures.
-                        * If worst case value for ent_dly is identified,
-                        * the loop can be skipped for that platform.
-                        */
-                       if (needs_entropy_delay_adjustment())
-                               break;
-                       if (ret == -EAGAIN)
-                               /*
-                                * if here, the loop will rerun,
-                                * so don't hog the CPU
-                                */
-                               cpu_relax();
-               } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
-               if (ret) {
-                       dev_err(dev, "failed to instantiate RNG");
+       if (reg_access) {
+               ret = caam_ctrl_rng_init(dev);
+               if (ret)
                        return ret;
-               }
-               /*
-                * Set handles initialized by this module as the complement of
-                * the already initialized ones
-                */
-               ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_MASK;
-
-               /* Enable RDB bit so that RNG works faster */
-               clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
        }
 
-report_live:
-       /* NOTE: RTIC detection ought to go here, around Si time */
-
        caam_id = (u64)rd_reg32(&perfmon->caam_id_ms) << 32 |
                  (u64)rd_reg32(&perfmon->caam_id_ls);
 
index 86ed1b9..b4f7bf7 100644 (file)
@@ -95,6 +95,7 @@ struct caam_drv_private {
        u8 blob_present;        /* Nonzero if BLOB support present in device */
        u8 mc_en;               /* Nonzero if MC f/w is active */
        u8 optee_en;            /* Nonzero if OP-TEE f/w is active */
+       bool pr_support;        /* RNG prediction resistance available */
        int secvio_irq;         /* Security violation interrupt number */
        int virt_en;            /* Virtualization enabled in CAAM */
        int era;                /* CAAM Era (internal HW revision) */