LF-3946 crypto: caam: Fix kick_trng for i.MX
authorYe Li <ye.li@nxp.com>
Mon, 7 Jun 2021 13:31:07 +0000 (06:31 -0700)
committerYe Li <ye.li@nxp.com>
Mon, 7 Jun 2021 13:56:00 +0000 (06:56 -0700)
Porting the RNG init relevant configurations for i.MX from fsl_caam.c
to jr.c to fix hwrng performance issue in kernel.

Signed-off-by: Ye Li <ye.li@nxp.com>
Acked-by: Gaurav Jain <gaurav.jain@nxp.com>
drivers/crypto/fsl/jr.c
include/fsl_sec.h

index bdbc7d4..8430183 100644 (file)
@@ -588,6 +588,115 @@ static u8 get_rng_vid(ccsr_sec_t *sec)
        return vid;
 }
 
+#if defined(CONFIG_ARCH_IMX8M) || defined(CONFIG_ARCH_MX7ULP) || \
+       defined(CONFIG_ARCH_MX6) || defined (CONFIG_ARCH_MX7)
+
+static void kick_trng(u32 ent_delay, ccsr_sec_t *sec)
+{
+       u32 samples  = 512; /* number of bits to generate and test */
+       u32 mono_min = 195;
+       u32 mono_max = 317;
+       u32 mono_range  = mono_max - mono_min;
+       u32 poker_min = 1031;
+       u32 poker_max = 1600;
+       u32 poker_range = poker_max - poker_min + 1;
+       u32 retries    = 2;
+       u32 lrun_max   = 32;
+       s32 run_1_min   = 27;
+       s32 run_1_max   = 107;
+       s32 run_1_range = run_1_max - run_1_min;
+       s32 run_2_min   = 7;
+       s32 run_2_max   = 62;
+       s32 run_2_range = run_2_max - run_2_min;
+       s32 run_3_min   = 0;
+       s32 run_3_max   = 39;
+       s32 run_3_range = run_3_max - run_3_min;
+       s32 run_4_min   = -1;
+       s32 run_4_max   = 26;
+       s32 run_4_range = run_4_max - run_4_min;
+       s32 run_5_min   = -1;
+       s32 run_5_max   = 18;
+       s32 run_5_range = run_5_max - run_5_min;
+       s32 run_6_min   = -1;
+       s32 run_6_max   = 17;
+       s32 run_6_range = run_6_max - run_6_min;
+       u32 val;
+
+       struct rng4tst __iomem *rng =
+                       (struct rng4tst __iomem *)&sec->rng;
+
+       /* Put RNG in program mode */
+       /* Setting both RTMCTL:PRGM and RTMCTL:TRNG_ACC causes TRNG to
+        * properly invalidate the entropy in the entropy register and
+        * force re-generation.
+        */
+       sec_setbits32(&rng->rtmctl, RTMCTL_PRGM | RTMCTL_ACC);
+
+       /* Configure the RNG Entropy 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.
+        */
+       val = sec_in32(&rng->rtsdctl);
+       val &= RTSDCTL_ENT_DLY_MASK;
+       val >>= RTSDCTL_ENT_DLY_SHIFT;
+       if (ent_delay < val) {
+               /* Put RNG4 into run mode */
+               sec_clrbits32(&rng->rtmctl, RTMCTL_PRGM | RTMCTL_ACC);
+               return;
+       }
+
+       val = (ent_delay << RTSDCTL_ENT_DLY_SHIFT) | samples;
+       sec_out32(&rng->rtsdctl, val);
+
+       /*
+        * Recommended margins (min,max) for freq. count:
+        *   freq_mul = RO_freq / TRNG_clk_freq
+        *   rtfrqmin = (ent_delay x freq_mul) >> 1;
+        *   rtfrqmax = (ent_delay x freq_mul) << 3;
+        * Given current deployments of CAAM in i.MX SoCs, and to simplify
+        * the configuration, we consider [1,16] to be a safe interval
+        * for the freq_mul and the limits of the interval are used to compute
+        * rtfrqmin, rtfrqmax
+        */
+       sec_out32(&rng->rtfreqmin, ent_delay >> 1);
+       sec_out32(&rng->rtfreqmax, ent_delay << 7);
+
+       sec_out32(&rng->rtscmisc, (retries << 16) | lrun_max);
+       sec_out32(&rng->rtpkrmax, poker_max);
+       sec_out32(&rng->rtpkrrng, poker_range);
+       sec_out32(&rng->rsvd1[0], (mono_range << 16) | mono_max);
+       sec_out32(&rng->rsvd1[1], (run_1_range << 16) | run_1_max);
+       sec_out32(&rng->rsvd1[2], (run_2_range << 16) | run_2_max);
+       sec_out32(&rng->rsvd1[3], (run_3_range << 16) | run_3_max);
+       sec_out32(&rng->rsvd1[4], (run_4_range << 16) | run_4_max);
+       sec_out32(&rng->rsvd1[5], (run_5_range << 16) | run_5_max);
+       sec_out32(&rng->rsvd1[6], (run_6_range << 16) | run_6_max);
+
+       val = sec_in32(&rng->rtmctl);
+       /*
+        * Select raw sampling in both entropy shifter
+        * and statistical checker
+        */
+       val &= ~RTMCTL_SAMP_MODE_INVALID;
+       val |= RTMCTL_SAMP_MODE_RAW_ES_SC;
+       /* Put RNG4 into run mode */
+       val &= ~(RTMCTL_PRGM | RTMCTL_ACC);
+       /*test with sample mode only */
+       sec_out32(&rng->rtmctl, val);
+
+       /* Clear the ERR bit in RTMCTL if set. The TRNG error can occur when the
+        * RNG clock is not within 1/2x to 8x the system clock.
+        * This error is possible if ROM code does not initialize the system PLLs
+        * immediately after PoR.
+        */
+       /* setbits_le32(CAAM_RTMCTL, RTMCTL_ERR); */
+}
+
+#else
 /*
  * By default, the TRNG runs for 200 clocks per sample;
  * 1200 clocks per sample generates better entropy.
@@ -619,6 +728,7 @@ static void kick_trng(int ent_delay, ccsr_sec_t *sec)
        /* put RNG4 into run mode */
        sec_clrbits32(&rng->rtmctl, RTMCTL_PRGM);
 }
+#endif
 
 static int rng_init(uint8_t sec_idx, ccsr_sec_t *sec)
 {
index 0b1e444..ebdf6a9 100644 (file)
@@ -34,6 +34,7 @@
 #if CONFIG_SYS_FSL_SEC_COMPAT >= 4
 /* RNG4 TRNG test registers */
 struct rng4tst {
+#define RTMCTL_ACC  0x20
 #define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
 #define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_SC     0 /* use von Neumann data in
                                                    both entropy shifter and