crypto: caam - optimize RNG sample size
authorMeenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Mon, 12 Jun 2023 08:30:42 +0000 (10:30 +0200)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 23 Jun 2023 08:15:36 +0000 (16:15 +0800)
TRNG "sample size" (the total number of entropy samples that will be taken
during entropy generation) default / POR value is very conservatively
set to 2500.

Let's set it to 512, the same as the caam driver in U-boot
(drivers/crypto/fsl_caam.c) does.

This solves the issue of RNG performance dropping after a suspend/resume
cycle on parts where caam loses power, since the initial U-boot setttings
are lost and kernel does not restore them when resuming.

Note: when changing the sample size, the self-test parameters need to be
updated accordingly.

Signed-off-by: Horia Geantă <horia.geanta@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/regs.h

index ee6478e..ff9ddbb 100644 (file)
@@ -358,7 +358,7 @@ static void kick_trng(struct device *dev, int ent_delay)
        struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
        struct caam_ctrl __iomem *ctrl;
        struct rng4tst __iomem *r4tst;
-       u32 val;
+       u32 val, rtsdctl;
 
        ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
        r4tst = &ctrl->r4tst[0];
@@ -374,26 +374,38 @@ static void kick_trng(struct device *dev, int ent_delay)
         * 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.
+        * were instantiated properly).
         */
-       val = (rd_reg32(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK)
-             >> RTSDCTL_ENT_DLY_SHIFT;
-       if (ent_delay <= val)
-               goto start_rng;
-
-       val = rd_reg32(&r4tst->rtsdctl);
-       val = (val & ~RTSDCTL_ENT_DLY_MASK) |
-             (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
-       wr_reg32(&r4tst->rtsdctl, val);
-       /* min. freq. count, equal to 1/4 of the entropy sample length */
-       wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2);
-       /* max. freq. count, equal to 16 times the entropy sample length */
-       wr_reg32(&r4tst->rtfrqmax, ent_delay << 4);
-       /* read the control register */
-       val = rd_reg32(&r4tst->rtmctl);
-start_rng:
+       rtsdctl = rd_reg32(&r4tst->rtsdctl);
+       val = (rtsdctl & RTSDCTL_ENT_DLY_MASK) >> RTSDCTL_ENT_DLY_SHIFT;
+       if (ent_delay > val) {
+               val = ent_delay;
+               /* min. freq. count, equal to 1/4 of the entropy sample length */
+               wr_reg32(&r4tst->rtfrqmin, val >> 2);
+               /* max. freq. count, equal to 16 times the entropy sample length */
+               wr_reg32(&r4tst->rtfrqmax, val << 4);
+       }
+
+       wr_reg32(&r4tst->rtsdctl, (val << RTSDCTL_ENT_DLY_SHIFT) |
+                RTSDCTL_SAMP_SIZE_VAL);
+
+       /*
+        * To avoid reprogramming the self-test parameters over and over again,
+        * use RTSDCTL[SAMP_SIZE] as an indicator.
+        */
+       if ((rtsdctl & RTSDCTL_SAMP_SIZE_MASK) != RTSDCTL_SAMP_SIZE_VAL) {
+               wr_reg32(&r4tst->rtscmisc, (2 << 16) | 32);
+               wr_reg32(&r4tst->rtpkrrng, 570);
+               wr_reg32(&r4tst->rtpkrmax, 1600);
+               wr_reg32(&r4tst->rtscml, (122 << 16) | 317);
+               wr_reg32(&r4tst->rtscrl[0], (80 << 16) | 107);
+               wr_reg32(&r4tst->rtscrl[1], (57 << 16) | 62);
+               wr_reg32(&r4tst->rtscrl[2], (39 << 16) | 39);
+               wr_reg32(&r4tst->rtscrl[3], (27 << 16) | 26);
+               wr_reg32(&r4tst->rtscrl[4], (19 << 16) | 18);
+               wr_reg32(&r4tst->rtscrl[5], (18 << 16) | 17);
+       }
+
        /*
         * select raw sampling in both entropy shifter
         * and statistical checker; ; put RNG4 into run mode
index 66928f8..189e74c 100644 (file)
@@ -3,7 +3,7 @@
  * CAAM hardware register-level view
  *
  * Copyright 2008-2011 Freescale Semiconductor, Inc.
- * Copyright 2018 NXP
+ * Copyright 2018, 2023 NXP
  */
 
 #ifndef REGS_H
@@ -523,6 +523,8 @@ struct rng4tst {
 #define RTSDCTL_ENT_DLY_MASK (0xffff << RTSDCTL_ENT_DLY_SHIFT)
 #define RTSDCTL_ENT_DLY_MIN 3200
 #define RTSDCTL_ENT_DLY_MAX 12800
+#define RTSDCTL_SAMP_SIZE_MASK 0xffff
+#define RTSDCTL_SAMP_SIZE_VAL 512
        u32 rtsdctl;            /* seed control register */
        union {
                u32 rtsblim;    /* PRGM=1: sparse bit limit register */
@@ -534,7 +536,15 @@ struct rng4tst {
                u32 rtfrqmax;   /* PRGM=1: freq. count max. limit register */
                u32 rtfrqcnt;   /* PRGM=0: freq. count register */
        };
-       u32 rsvd1[40];
+       union {
+               u32 rtscmc;     /* statistical check run monobit count */
+               u32 rtscml;     /* statistical check run monobit limit */
+       };
+       union {
+               u32 rtscrc[6];  /* statistical check run length count */
+               u32 rtscrl[6];  /* statistical check run length limit */
+       };
+       u32 rsvd1[33];
 #define RDSTA_SKVT 0x80000000
 #define RDSTA_SKVN 0x40000000
 #define RDSTA_PR0 BIT(4)