summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWinter Wang <wente.wang@nxp.com>2016-11-30 16:12:57 +0800
committerWinter Wang <wente.wang@nxp.com>2016-12-01 10:21:43 +0800
commit6c5665fe850ad293342e6000827065290a79beba (patch)
treed8af09e7627bdaa4b8a762ede290d881cf6bd977
parenta442e4e7b50f52be3940d6bd885bbbff51171f05 (diff)
downloadu-boot-imx-6c5665fe850ad293342e6000827065290a79beba.zip
u-boot-imx-6c5665fe850ad293342e6000827065290a79beba.tar.gz
u-boot-imx-6c5665fe850ad293342e6000827065290a79beba.tar.bz2
MA-9077 caam: add hwrng
add caam based hwrng Change-Id: Ifabc4ec9da5531e1f1804587901a5dc438db99df Signed-off-by: Winter Wang <wente.wang@nxp.com>
-rwxr-xr-xdrivers/crypto/fsl_caam.c134
-rw-r--r--include/fsl_caam.h1
2 files changed, 102 insertions, 33 deletions
diff --git a/drivers/crypto/fsl_caam.c b/drivers/crypto/fsl_caam.c
index 3ae9bf7..ebba87c 100755
--- a/drivers/crypto/fsl_caam.c
+++ b/drivers/crypto/fsl_caam.c
@@ -39,10 +39,10 @@
uint32_t g_input_ring[JOB_RING_ENTRIES] = {0};
-/* Output job ring - single entry output ring (consists of two words) */
+/* Output job ring - single entry output ring (consists of two words) */
uint32_t g_output_ring[2*JOB_RING_ENTRIES] = {0, 0};
-uint32_t decap_dsc[] =
+uint32_t decap_dsc[] =
{
DECAP_BLOB_DESC1,
DECAP_BLOB_DESC2,
@@ -55,7 +55,7 @@ uint32_t decap_dsc[] =
DECAP_BLOB_DESC9
};
-uint32_t encap_dsc[] =
+uint32_t encap_dsc[] =
{
ENCAP_BLOB_DESC1,
ENCAP_BLOB_DESC2,
@@ -68,7 +68,8 @@ uint32_t encap_dsc[] =
ENCAP_BLOB_DESC9
};
-uint32_t rng_inst_dsc[] =
+uint32_t hwrng_dsc[6] = {0};
+uint32_t rng_inst_dsc[] =
{
RNG_INST_DESC1,
RNG_INST_DESC2,
@@ -146,7 +147,7 @@ uint32_t caam_decap_blob(uint32_t plain_text, uint32_t blob_addr, uint32_t size)
/* uncomment when using descriptor from "fsl_caam_internal.h"
does not use key modifier. */
-#if 0
+#if 0
/* Fill in input blob addr in decap_dsc */
decap_dsc[5] = (uint32_t)blob;
/* Fill in the address where to decrypt the blob */
@@ -157,14 +158,19 @@ uint32_t caam_decap_blob(uint32_t plain_text, uint32_t blob_addr, uint32_t size)
/* Add job to input ring */
g_input_ring[0] = (uint32_t)decap_dsc;
- flush_dcache_range((uint32_t)blob_addr & ALIGN_MASK,
- ((uint32_t)blob_addr & ALIGN_MASK) + 2*size);
- flush_dcache_range((uint32_t)plain_text & ALIGN_MASK,
- ((uint32_t)plain_text & ALIGN_MASK) + 2*size);
flush_dcache_range((uint32_t)decap_dsc & ALIGN_MASK,
((uint32_t)decap_dsc & ALIGN_MASK) + 128);
flush_dcache_range((uint32_t)g_input_ring & ALIGN_MASK,
((uint32_t)g_input_ring & ALIGN_MASK) + 128);
+ invalidate_dcache_range((uint32_t)decap_dsc & ALIGN_MASK,
+ ((uint32_t)decap_dsc & ALIGN_MASK) + 128);
+ invalidate_dcache_range((uint32_t)g_input_ring & ALIGN_MASK,
+ ((uint32_t)g_input_ring & ALIGN_MASK) + 128);
+ invalidate_dcache_range((uint32_t)blob_addr & ALIGN_MASK,
+ (((uint32_t)blob_addr + 2 * size + 64) & ALIGN_MASK));
+ invalidate_dcache_range((uint32_t)plain_text & ALIGN_MASK,
+ (((uint32_t)plain_text + 2 * size + 64) & ALIGN_MASK));
+
/* Increment jobs added */
__raw_writel(1, CAAM_IRJAR0);
@@ -172,7 +178,7 @@ uint32_t caam_decap_blob(uint32_t plain_text, uint32_t blob_addr, uint32_t size)
while(__raw_readl(CAAM_ORSFR0) != 1);
// TODO: check if Secure memory is cacheable.
- invalidate_dcache_range((uint32_t)g_output_ring & ALIGN_MASK,
+ flush_dcache_range((uint32_t)g_output_ring & ALIGN_MASK,
((uint32_t)g_output_ring & ALIGN_MASK) + 128);
/* check that descriptor address is the one expected in the output ring */
if(g_output_ring[0] == (uint32_t)decap_dsc)
@@ -189,9 +195,6 @@ uint32_t caam_decap_blob(uint32_t plain_text, uint32_t blob_addr, uint32_t size)
printf("Error: blob decap job output ring descriptor address does" \
" not match\n");
}
- flush_dcache_range((uint32_t)plain_text & ALIGN_MASK,
- ((uint32_t)plain_text & ALIGN_MASK) + 2*size);
-
/* Remove job from Job Ring Output Queue */
__raw_writel(1, CAAM_ORJRR0);
@@ -239,15 +242,15 @@ uint32_t caam_gen_blob(uint32_t plain_data_addr, uint32_t blob_addr, uint32_t si
encap_dsc[3] = (uint32_t)0xF0000000 | (0x0000ffff & (size));
encap_dsc[4] = (uint32_t)plain_data_addr;
encap_dsc[5] = (uint32_t)0xF8000000 | (0x0000ffff & (size+48));
- encap_dsc[6] = (uint32_t)blob;
+ encap_dsc[6] = (uint32_t)blob;
encap_dsc[7] = (uint32_t)0x870D0000;
// uncomment when using descriptor from "fsl_caam_internal.h"
- // does not use key modifier.
+ // does not use key modifier.
#if 0
//
/* Fill in the address where the DEK resides */
- encap_dsc[5] = (uint32_t)SEC_MEM_PAGE1;
+ encap_dsc[5] = (uint32_t)SEC_MEM_PAGE1;
/* Fill in output blob addr in encap_dsc */
encap_dsc[7] = (uint32_t)blob;
#endif
@@ -256,12 +259,18 @@ uint32_t caam_gen_blob(uint32_t plain_data_addr, uint32_t blob_addr, uint32_t si
/* Add job to input ring */
g_input_ring[0] = (uint32_t)encap_dsc;
- flush_dcache_range((uint32_t)plain_data_addr & ALIGN_MASK,
- ((uint32_t)plain_data_addr & ALIGN_MASK) + size);
flush_dcache_range((uint32_t)encap_dsc & ALIGN_MASK,
((uint32_t)encap_dsc & ALIGN_MASK) + 128);
- flush_dcache_range((uint32_t)blob & ALIGN_MASK,
- ((uint32_t)g_input_ring & ALIGN_MASK) + 2 * size);
+ flush_dcache_range((uint32_t)g_input_ring & ALIGN_MASK,
+ ((uint32_t)g_input_ring & ALIGN_MASK) + 128);
+ invalidate_dcache_range((uint32_t)encap_dsc & ALIGN_MASK,
+ ((uint32_t)encap_dsc & ALIGN_MASK) + 128);
+ invalidate_dcache_range((uint32_t)g_input_ring & ALIGN_MASK,
+ ((uint32_t)g_input_ring & ALIGN_MASK) + 128);
+ invalidate_dcache_range((uint32_t)plain_data_addr & ALIGN_MASK,
+ (((uint32_t)plain_data_addr + 2 * size + 64) & ALIGN_MASK));
+ invalidate_dcache_range((uint32_t)blob & ALIGN_MASK,
+ (((uint32_t)blob + 2 * size + 64) & ALIGN_MASK));
/* Increment jobs added */
__raw_writel(1, CAAM_IRJAR0);
@@ -269,9 +278,7 @@ uint32_t caam_gen_blob(uint32_t plain_data_addr, uint32_t blob_addr, uint32_t si
while(__raw_readl(CAAM_ORSFR0) != 1);
// flush cache
- invalidate_dcache_range((uint32_t)g_output_ring & ALIGN_MASK,
- ((uint32_t)g_output_ring & ALIGN_MASK) + 128);
- invalidate_dcache_range((uint32_t)g_output_ring & ALIGN_MASK,
+ flush_dcache_range((uint32_t)g_output_ring & ALIGN_MASK,
((uint32_t)g_output_ring & ALIGN_MASK) + 128);
/* check that descriptor address is the one expected in the output ring */
if(g_output_ring[0] == (uint32_t)encap_dsc)
@@ -295,6 +302,67 @@ uint32_t caam_gen_blob(uint32_t plain_data_addr, uint32_t blob_addr, uint32_t si
return ret;
}
+uint32_t caam_hwrng(uint8_t *output_ptr, uint32_t output_len) {
+ uint32_t ret = SUCCESS;
+
+ /* Buffer to hold the resulting output*/
+ uint8_t *output = (uint8_t *)output_ptr;
+
+ /* initialize the output array */
+ memset(output,0,output_len);
+
+ int n = 0;
+ hwrng_dsc[n++] = (uint32_t)0xB0800004;
+ hwrng_dsc[n++] = (uint32_t)0x82500000;
+ hwrng_dsc[n++] = (uint32_t)0x60340000| (0x0000ffff & output_len);
+ hwrng_dsc[n++] = (uint32_t)output;
+
+ /* Run descriptor with result written to blob buffer */
+ /* Add job to input ring */
+ // flush cache
+ g_input_ring[0] = (uint32_t)hwrng_dsc;
+
+ flush_dcache_range((uint32_t)hwrng_dsc & ALIGN_MASK,
+ ((uint32_t)hwrng_dsc & ALIGN_MASK) + 128);
+ flush_dcache_range((uint32_t)g_input_ring & ALIGN_MASK,
+ ((uint32_t)g_input_ring & ALIGN_MASK) + 128);
+ invalidate_dcache_range((uint32_t)hwrng_dsc & ALIGN_MASK,
+ ((uint32_t)hwrng_dsc & ALIGN_MASK) + 128);
+ invalidate_dcache_range((uint32_t)g_input_ring & ALIGN_MASK,
+ ((uint32_t)g_input_ring & ALIGN_MASK) + 128);
+ invalidate_dcache_range((uint32_t)output & ALIGN_MASK,
+ (((uint32_t)output + 2 * output_len + 64) & ALIGN_MASK));
+ /* Increment jobs added */
+ __raw_writel(1, CAAM_IRJAR0);
+
+ /* Wait for job ring to complete the job: 1 completed job expected */
+ size_t timeout = 100000;
+ while(__raw_readl(CAAM_ORSFR0) != 1 && timeout--);
+ flush_dcache_range((uint32_t)g_output_ring & ALIGN_MASK,
+ ((uint32_t)g_output_ring & ALIGN_MASK) + 128);
+
+ /* check that descriptor address is the one expected in the output ring */
+ if(g_output_ring[0] == (uint32_t)hwrng_dsc) {
+ /* check if any error is reported in the output ring */
+ if ((g_output_ring[1] & JOB_RING_STS) != 0) {
+ printf("Error: RNG job completed with errors 0x%X\n",
+ g_output_ring[1]);
+ ret = -1;
+ }
+ } else {
+ printf("Error: RNG output ring descriptor address does" \
+ " not match\n");
+ ret = -1;
+
+ }
+
+ /* Remove job from Job Ring Output Queue */
+ __raw_writel(1, CAAM_ORJRR0);
+
+ return ret;
+}
+
+
/*!
* Initialize the CAAM.
*
@@ -307,8 +375,8 @@ void caam_open(void)
/* switch on the clock */
temp_reg = __raw_readl(&mxc_ccm->CCGR0);
- temp_reg |= MXC_CCM_CCGR0_CAAM_SECURE_MEM_MASK |
- MXC_CCM_CCGR0_CAAM_WRAPPER_ACLK_MASK |
+ temp_reg |= MXC_CCM_CCGR0_CAAM_SECURE_MEM_MASK |
+ MXC_CCM_CCGR0_CAAM_WRAPPER_ACLK_MASK |
MXC_CCM_CCGR0_CAAM_WRAPPER_IPG_MASK;
__raw_writel(temp_reg, &mxc_ccm->CCGR0);
@@ -318,7 +386,7 @@ void caam_open(void)
*
* However, still need to initialize Job Rings as these are torn
* down by HAB for each command
- */
+ */
/* Initialize job ring addresses */
__raw_writel((uint32_t)g_input_ring, CAAM_IRBAR0); // input ring address
@@ -330,7 +398,7 @@ void caam_open(void)
/* HAB disables interrupts for JR0 so do the same here */
temp_reg = __raw_readl(CAAM_JRCFGR0_LS) | JRCFG_LS_IMSK;
- __raw_writel(temp_reg, CAAM_JRCFGR0_LS);
+ __raw_writel(temp_reg, CAAM_JRCFGR0_LS);
/********* Initialize and instantiate the RNG *******************/
/* if RNG already instantiated then skip it */
@@ -344,13 +412,13 @@ void caam_open(void)
__raw_writel(temp_reg, CAAM_RTMCTL);
/* Set delay */
- __raw_writel(((RNG_TRIM_ENT_DLY << 16) | 0x09C4), CAAM_RTSDCTL);
+ __raw_writel(((RNG_TRIM_ENT_DLY << 16) | 0x09C4), CAAM_RTSDCTL);
__raw_writel((RNG_TRIM_ENT_DLY >> 1), CAAM_RTFRQMIN);
__raw_writel((RNG_TRIM_ENT_DLY << 4), CAAM_RTFRQMAX);
/* Resume TRNG Run mode */
temp_reg = __raw_readl(CAAM_RTMCTL) ^ RTMCTL_PGM;
- __raw_writel(temp_reg, CAAM_RTMCTL);
+ __raw_writel(temp_reg, CAAM_RTMCTL);
/* 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.
@@ -367,7 +435,7 @@ void caam_open(void)
flush_dcache_range((uint32_t)g_input_ring & ALIGN_MASK,
((uint32_t)g_input_ring & ALIGN_MASK) + 128);
/* Increment jobs added */
- __raw_writel(1, CAAM_IRJAR0);
+ __raw_writel(1, CAAM_IRJAR0);
/* Wait for job ring to complete the job: 1 completed job expected */
while(__raw_readl(CAAM_ORSFR0) != 1);
@@ -399,13 +467,13 @@ void caam_open(void)
temp_reg = __raw_readl(CAAM_RDSTA);
if (temp_reg != (RDSTA_IF0 | RDSTA_SKVN))
{
-
+
printf("Error: RNG instantiation failed 0x%X\n", temp_reg);
}
-
+
/* Remove job from Job Ring Output Queue */
__raw_writel(1, CAAM_ORJRR0);
}
-
+
return;
}
diff --git a/include/fsl_caam.h b/include/fsl_caam.h
index d282a33..e1fdf77 100644
--- a/include/fsl_caam.h
+++ b/include/fsl_caam.h
@@ -70,5 +70,6 @@ uint32_t caam_gen_blob(uint32_t plain_data_addr, uint32_t blob_addr, uint32_t si
//! @return ERROR_XXX
////////////////////////////////////////////////////////////////////////////////
uint32_t caam_decap_blob(uint32_t plain_text, uint32_t blob_addr, uint32_t size);
+uint32_t caam_hwrng(uint8_t *output_ptr, uint32_t output_len);
#endif /* __CAAM_H__ */