summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/crypto/fsl/jobdesc.c35
-rw-r--r--drivers/crypto/fsl/jobdesc.h2
-rw-r--r--drivers/crypto/fsl/jr.c57
-rw-r--r--drivers/crypto/fsl/jr.h2
-rw-r--r--include/fsl_sec.h3
5 files changed, 60 insertions, 39 deletions
diff --git a/drivers/crypto/fsl/jobdesc.c b/drivers/crypto/fsl/jobdesc.c
index 375ff9d0e3..aadf851101 100644
--- a/drivers/crypto/fsl/jobdesc.c
+++ b/drivers/crypto/fsl/jobdesc.c
@@ -257,7 +257,7 @@ void inline_cnstr_jobdesc_blob_decap(uint32_t *desc, uint8_t *key_idnfr,
* Descriptor to instantiate RNG State Handle 0 in normal mode and
* load the JDKEK, TDKEK and TDSK registers
*/
-void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc)
+void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc, int handle)
{
u32 *jump_cmd;
@@ -265,21 +265,24 @@ void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc)
/* INIT RNG in non-test mode */
append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- OP_ALG_AS_INIT);
-
- /* 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);
-
- /* generate secure keys (non-test) */
- append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- OP_ALG_RNG4_SK);
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT);
+
+ /* For SH0, Secure Keys must be generated as well */
+ if (handle == 0) {
+ /* 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 interrupt and returns the RNG to idle.
+ */
+ append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
+
+ /* generate secure keys (non-test) */
+ append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+ OP_ALG_RNG4_SK);
+ }
}
/* Change key size to bytes form bits in calling function*/
diff --git a/drivers/crypto/fsl/jobdesc.h b/drivers/crypto/fsl/jobdesc.h
index 112404c74d..75c9424c4a 100644
--- a/drivers/crypto/fsl/jobdesc.h
+++ b/drivers/crypto/fsl/jobdesc.h
@@ -40,7 +40,7 @@ void inline_cnstr_jobdesc_blob_decap(uint32_t *desc, uint8_t *key_idnfr,
uint8_t *enc_blob, uint8_t *plain_txt,
uint32_t out_sz);
-void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc);
+void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc, int handle);
void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc,
struct pk_in_params *pkin, uint8_t *out,
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index a05779826f..34bd070426 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -444,35 +444,49 @@ int sec_reset(void)
#ifndef CONFIG_SPL_BUILD
static int instantiate_rng(uint8_t sec_idx)
{
- struct result op;
u32 *desc;
u32 rdsta_val;
- int ret = 0;
+ int ret = 0, sh_idx, size;
ccsr_sec_t __iomem *sec = (ccsr_sec_t __iomem *)SEC_ADDR(sec_idx);
struct rng4tst __iomem *rng =
(struct rng4tst __iomem *)&sec->rng;
- memset(&op, 0, sizeof(struct result));
-
desc = memalign(ARCH_DMA_MINALIGN, sizeof(uint32_t) * 6);
if (!desc) {
printf("cannot allocate RNG init descriptor memory\n");
return -1;
}
- inline_cnstr_jobdesc_rng_instantiation(desc);
- int size = roundup(sizeof(uint32_t) * 6, ARCH_DMA_MINALIGN);
- flush_dcache_range((unsigned long)desc,
- (unsigned long)desc + size);
+ 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.
+ */
+ rdsta_val = sec_in32(&rng->rdsta) & RNG_STATE_HANDLE_MASK;
+ if (rdsta_val & (1 << sh_idx))
+ continue;
+
+ inline_cnstr_jobdesc_rng_instantiation(desc, sh_idx);
+ size = roundup(sizeof(uint32_t) * 6, ARCH_DMA_MINALIGN);
+ flush_dcache_range((unsigned long)desc,
+ (unsigned long)desc + size);
- ret = run_descriptor_jr_idx(desc, sec_idx);
+ ret = run_descriptor_jr_idx(desc, sec_idx);
- if (ret)
- printf("RNG: Instantiation failed with error %x\n", ret);
+ if (ret)
+ printf("RNG: Instantiation failed with error 0x%x\n",
+ ret);
- rdsta_val = sec_in32(&rng->rdsta);
- if (op.status || !(rdsta_val & RNG_STATE0_HANDLE_INSTANTIATED))
- return -1;
+ rdsta_val = sec_in32(&rng->rdsta) & RNG_STATE_HANDLE_MASK;
+ if (!(rdsta_val & (1 << sh_idx))) {
+ free(desc);
+ return -1;
+ }
+
+ memset(desc, 0, sizeof(uint32_t) * 6);
+ }
+
+ free(desc);
return ret;
}
@@ -524,14 +538,11 @@ static int rng_init(uint8_t sec_idx)
ccsr_sec_t __iomem *sec = (ccsr_sec_t __iomem *)SEC_ADDR(sec_idx);
struct rng4tst __iomem *rng =
(struct rng4tst __iomem *)&sec->rng;
-
- u32 rdsta = sec_in32(&rng->rdsta);
-
- /* Check if RNG state 0 handler is already instantiated */
- if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED)
- return 0;
+ u32 inst_handles;
do {
+ inst_handles = sec_in32(&rng->rdsta) & RNG_STATE_HANDLE_MASK;
+
/*
* If either of the SH's were instantiated by somebody else
* then it is assumed that the entropy
@@ -540,8 +551,10 @@ static int rng_init(uint8_t sec_idx)
* Also, if a handle was instantiated, do not change
* the TRNG parameters.
*/
- kick_trng(ent_delay, sec_idx);
- ent_delay += 400;
+ if (!inst_handles) {
+ kick_trng(ent_delay, sec_idx);
+ ent_delay += 400;
+ }
/*
* if instantiate_rng(...) fails, the loop will rerun
* and the kick_trng(...) function will modfiy the
diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h
index 8aab4c988d..ef515e74f8 100644
--- a/drivers/crypto/fsl/jr.h
+++ b/drivers/crypto/fsl/jr.h
@@ -41,6 +41,8 @@
#define JQ_DEQ_TO_ERR -2
#define JQ_ENQ_ERR -3
+#define RNG4_MAX_HANDLES 2
+
struct op_ring {
phys_addr_t desc;
uint32_t status;
diff --git a/include/fsl_sec.h b/include/fsl_sec.h
index a2f5f5a5f1..4cbdb2d65a 100644
--- a/include/fsl_sec.h
+++ b/include/fsl_sec.h
@@ -67,6 +67,9 @@ struct rng4tst {
};
u32 rsvd1[40];
#define RNG_STATE0_HANDLE_INSTANTIATED 0x00000001
+#define RNG_STATE1_HANDLE_INSTANTIATED 0x00000002
+#define RNG_STATE_HANDLE_MASK \
+ (RNG_STATE0_HANDLE_INSTANTIATED | RNG_STATE1_HANDLE_INSTANTIATED)
u32 rdsta; /*RNG DRNG Status Register*/
u32 rsvd2[15];
};