diff options
author | Aymen Sghaier <aymen.sghaier@nxp.com> | 2018-04-24 18:36:02 +0200 |
---|---|---|
committer | Aymen Sghaier <aymen.sghaier@nxp.com> | 2018-07-17 15:09:23 +0200 |
commit | 1f4134c85f6416cbdadaf5f4ff6321f6c685c74c (patch) | |
tree | 674c182be3ff1e39260f6ab812182380f18ac9bb /drivers/crypto | |
parent | 4da1ab91f864b804ad561e04f44b618ec86b99b7 (diff) |
MLK-18703: crypto: caam: Add init TRNG into SPL or U-Boot
The following reasons lead to instantiate the TRNG into U-Boot/SPL:
- On some i.MX platforms Linux Kernel could not instantiate RNG
- RNG could be used/needed by M4/M0 cores before Kernel stage
- Having the RNG instantiation implemented only once for
almost i.MX platforms
Signed-off-by: Aymen Sghaier <aymen.sghaier@nxp.com>
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/fsl_caam.c | 904 | ||||
-rw-r--r-- | drivers/crypto/fsl_caam_internal.h | 482 |
2 files changed, 767 insertions, 619 deletions
diff --git a/drivers/crypto/fsl_caam.c b/drivers/crypto/fsl_caam.c index e9edb6792c5..7d57e44eaba 100644 --- a/drivers/crypto/fsl_caam.c +++ b/drivers/crypto/fsl_caam.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2012-2016, Freescale Semiconductor, Inc. * All rights reserved. + * Copyright 2018 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -29,67 +30,75 @@ */ #include <common.h> +#include <malloc.h> +#include <memalign.h> #include <asm/io.h> #include <asm/arch/crm_regs.h> #include "fsl_caam_internal.h" +#include "fsl/desc_constr.h" #include <fsl_caam.h> -/*---------- Global variables ----------*/ -/* Input job ring - single entry input ring */ -uint32_t g_input_ring[JOB_RING_ENTRIES] = {0}; +DECLARE_GLOBAL_DATA_PTR; +static void rng_init(void); +static void caam_clock_enable(void); +static int do_cfg_jrqueue(void); +static int do_job(u32 *desc); +static int jr_reset(void); -/* 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[] = -{ - DECAP_BLOB_DESC1, - DECAP_BLOB_DESC2, - DECAP_BLOB_DESC3, - DECAP_BLOB_DESC4, - DECAP_BLOB_DESC5, - DECAP_BLOB_DESC6, - DECAP_BLOB_DESC7, - DECAP_BLOB_DESC8, - DECAP_BLOB_DESC9 +/* + * Structures + */ +/* Definition of input ring object */ +struct inring_entry { + u32 desc; /* Pointer to input descriptor */ }; -uint32_t encap_dsc[] = -{ - ENCAP_BLOB_DESC1, - ENCAP_BLOB_DESC2, - ENCAP_BLOB_DESC3, - ENCAP_BLOB_DESC4, - ENCAP_BLOB_DESC5, - ENCAP_BLOB_DESC6, - ENCAP_BLOB_DESC7, - ENCAP_BLOB_DESC8, - ENCAP_BLOB_DESC9 +/* Definition of output ring object */ +struct outring_entry { + u32 desc; /* Pointer to output descriptor */ + u32 status; /* Status of the Job Ring */ }; -uint32_t hwrng_dsc[6] = {0}; -uint32_t rng_inst_dsc[] = -{ - RNG_INST_DESC1, - RNG_INST_DESC2, - RNG_INST_DESC3, - RNG_INST_DESC4, - RNG_INST_DESC5, - RNG_INST_DESC6, - RNG_INST_DESC7, - RNG_INST_DESC8, - RNG_INST_DESC9 +/* Main job ring data structure */ +struct jr_data_st { + struct inring_entry *inrings; + struct outring_entry *outrings; + u32 status; /* Ring buffers init status */ + u32 *desc; /* Pointer to output descriptor */ + u32 raw_addr[DESC_MAX_SIZE * 2]; }; -static uint8_t skeymod[] = { +/* + * Global variables + */ +static struct jr_data_st g_jrdata = {0}; + +static u8 skeymod[] = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; - -/* arm v7 need 64 align */ -#define ALIGN_MASK 0xffffffc0 +/* + * Local functions + */ +static void dump_error(void) +{ + int i; + + debug("Dump CAAM Error\n"); + debug("MCFGR 0x%08X\n", __raw_readl(CAAM_MCFGR)); + debug("FAR 0x%08X\n", __raw_readl(CAAM_FAR)); + debug("FAMR 0x%08X\n", __raw_readl(CAAM_FAMR)); + debug("FADR 0x%08X\n", __raw_readl(CAAM_FADR)); + debug("CSTA 0x%08X\n", __raw_readl(CAAM_STA)); + debug("RTMCTL 0x%X\n", __raw_readl(CAAM_RTMCTL)); + debug("RTSTATUS 0x%X\n", __raw_readl(CAAM_RTSTATUS)); + debug("RDSTA 0x%X\n", __raw_readl(CAAM_RDSTA)); + + for (i = 0; i < desc_len(g_jrdata.desc); i++) + debug("desc[%d]: 0x%08x\n", i, g_jrdata.desc[i]); +} /*! * Secure memory run command. @@ -97,13 +106,13 @@ static uint8_t skeymod[] = { * @param sec_mem_cmd Secure memory command register * @return cmd_status Secure memory command status register */ -uint32_t secmem_set_cmd_1(uint32_t sec_mem_cmd) +u32 secmem_set_cmd_1(u32 sec_mem_cmd) { - uint32_t temp_reg; + u32 temp_reg; __raw_writel(sec_mem_cmd, CAAM_SMCJR0); do { temp_reg = __raw_readl(CAAM_SMCSJR0); - } while(temp_reg & CMD_COMPLETE); + } while (temp_reg & CMD_COMPLETE); return temp_reg; } @@ -118,77 +127,34 @@ uint32_t secmem_set_cmd_1(uint32_t sec_mem_cmd) * * @return SUCCESS or ERROR_XXX */ -uint32_t caam_decap_blob(uint32_t plain_text, uint32_t blob_addr, uint32_t size) +u32 caam_decap_blob(u32 plain_text, u32 blob_addr, u32 size) { - uint32_t ret = SUCCESS; - - /* Buffer that holds blob */ - - - /* TODO: Fix Hardcoded Descriptor */ - decap_dsc[0] = (uint32_t)0xB0800008; - decap_dsc[1] = (uint32_t)0x14400010; - decap_dsc[2] = (uint32_t)skeymod; - decap_dsc[3] = (uint32_t)0xF0000000 | (0x0000ffff & (size+48) ); - decap_dsc[4] = blob_addr; - decap_dsc[5] = (uint32_t)0xF8000000 | (0x0000ffff & (size)); - decap_dsc[6] = (uint32_t)(uint8_t*)plain_text; - decap_dsc[7] = (uint32_t)0x860D0000; - -/* uncomment when using descriptor from "fsl_caam_internal.h" - does not use key modifier. */ - - /* Run descriptor with result written to blob buffer */ - /* 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 + 2 * size + 64) & ALIGN_MASK)); - flush_dcache_range((uint32_t)plain_text & ALIGN_MASK, - (((uint32_t)plain_text + 2 * size + 64) & ALIGN_MASK)); - 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); - - /* Wait for job ring to complete the job: 1 completed job expected */ - while(__raw_readl(CAAM_ORSFR0) != 1); - - // TODO: check if Secure memory is cacheable. - flush_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, - ((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) - { - /* check if any error is reported in the output ring */ - if ((g_output_ring[1] & JOB_RING_STS) != 0) - { - printf("Error: blob decap job completed with errors 0x%X\n", - g_output_ring[1]); - } - } - else - { - printf("Error: blob decap job output ring descriptor address does" \ - " not match\n"); - } + u32 ret = SUCCESS; + u32 key_sz = sizeof(skeymod); + u32 *decap_desc = g_jrdata.desc; + + /* prepare job descriptor */ + init_job_desc(decap_desc, 0); + append_load(decap_desc, PTR2CAAMDMA(skeymod), key_sz, + LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY); + append_seq_in_ptr_intlen(decap_desc, blob_addr, size + 48, 0); + append_seq_out_ptr_intlen(decap_desc, plain_text, size, 0); + append_operation(decap_desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB); + + flush_dcache_range((uintptr_t)blob_addr & ALIGN_MASK, + ((uintptr_t)blob_addr & ALIGN_MASK) + + ROUND(2 * size, ARCH_DMA_MINALIGN)); + flush_dcache_range((uintptr_t)plain_text & ALIGN_MASK, + (plain_text & ALIGN_MASK) + + ROUND(2 * size, ARCH_DMA_MINALIGN)); + /* Run descriptor with result written to blob buffer */ + ret = do_job(decap_desc); - /* Remove job from Job Ring Output Queue */ - __raw_writel(1, CAAM_ORJRR0); + if (ret != SUCCESS) { + dump_error(); + printf("Error: blob decap job failed 0x%x\n", ret); + } return ret; } @@ -201,129 +167,73 @@ uint32_t caam_decap_blob(uint32_t plain_text, uint32_t blob_addr, uint32_t size) * * @return SUCCESS or ERROR_XXX */ -uint32_t caam_gen_blob(uint32_t plain_data_addr, uint32_t blob_addr, uint32_t size) +u32 caam_gen_blob(u32 plain_data_addr, u32 blob_addr, u32 size) { - uint32_t ret = SUCCESS; - + u32 ret = SUCCESS; + u32 key_sz = sizeof(skeymod); + u32 *encap_desc = g_jrdata.desc; /* Buffer to hold the resulting blob */ - uint8_t *blob = (uint8_t *)blob_addr; + u8 *blob = (u8 *)CAAMDMA2PTR(blob_addr); /* initialize the blob array */ memset(blob,0,size); - - /* TODO: Fix Hardcoded Descriptor */ - encap_dsc[0] = (uint32_t)0xB0800008; - encap_dsc[1] = (uint32_t)0x14400010; - encap_dsc[2] = (uint32_t)skeymod; - 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[7] = (uint32_t)0x870D0000; - - /* Run descriptor with result written to blob buffer */ - /* 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 + 2 * size + 64) & ALIGN_MASK)); - 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)blob + 2 * size + 64) & ALIGN_MASK)); - flush_dcache_range((uint32_t)g_input_ring & ALIGN_MASK, - ((uint32_t)g_input_ring & ALIGN_MASK) + 128); - - invalidate_dcache_range((uint32_t)blob & ALIGN_MASK, - (((uint32_t)blob + 2 * size + 64) & ALIGN_MASK)); - /* Increment jobs added */ - __raw_writel(1, CAAM_IRJAR0); - - /* Wait for job ring to complete the job: 1 completed job expected */ - while(__raw_readl(CAAM_ORSFR0) != 1); - - // flush cache - 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) - { - /* check if any error is reported in the output ring */ - if ((g_output_ring[1] & JOB_RING_STS) != 0) - { - printf("Error: blob encap job completed with errors 0x%X\n", - g_output_ring[1]); - } - } - else - { - printf("Error: blob encap job output ring descriptor address does" \ - " not match\n"); + /* prepare job descriptor */ + init_job_desc(encap_desc, 0); + append_load(encap_desc, PTR2CAAMDMA(skeymod), key_sz, + LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY); + append_seq_in_ptr_intlen(encap_desc, plain_data_addr, size, 0); + append_seq_out_ptr_intlen(encap_desc, PTR2CAAMDMA(blob), size + 48, 0); + append_operation(encap_desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB); + + flush_dcache_range((uintptr_t)plain_data_addr & ALIGN_MASK, + (plain_data_addr & ALIGN_MASK) + + ROUND(2 * size, ARCH_DMA_MINALIGN)); + flush_dcache_range((uintptr_t)blob & ALIGN_MASK, + ((uintptr_t)blob & ALIGN_MASK) + + ROUND(2 * size, ARCH_DMA_MINALIGN)); + + ret = do_job(encap_desc); + + if (ret != SUCCESS) { + dump_error(); + printf("Error: blob encap job failed 0x%x\n", ret); } - /* Remove job from Job Ring Output Queue */ - __raw_writel(1, CAAM_ORJRR0); - return ret; } -uint32_t caam_hwrng(uint8_t *output_ptr, uint32_t output_len) { - uint32_t ret = SUCCESS; - +u32 caam_hwrng(u8 *output_ptr, u32 output_len) +{ + u32 ret = SUCCESS; + u32 *hwrng_desc = g_jrdata.desc; /* Buffer to hold the resulting output*/ - uint8_t *output = (uint8_t *)output_ptr; + u8 *output = (u8 *)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; + /* prepare job descriptor */ + init_job_desc(hwrng_desc, 0); + append_operation(hwrng_desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG); + append_fifo_store(hwrng_desc, PTR2CAAMDMA(output), + output_len, FIFOST_TYPE_RNGSTORE); - /* 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); + /* flush cache */ + flush_dcache_range((uintptr_t)hwrng_desc & ALIGN_MASK, + ((uintptr_t)hwrng_desc & ALIGN_MASK) + + ROUND(DESC_MAX_SIZE, ARCH_DMA_MINALIGN)); - /* 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; + ret = do_job(hwrng_desc); - } + flush_dcache_range((uintptr_t)output & ALIGN_MASK, + ((uintptr_t)output & ALIGN_MASK) + + ROUND(2 * output_len, ARCH_DMA_MINALIGN)); - /* Remove job from Job Ring Output Queue */ - __raw_writel(1, CAAM_ORJRR0); + if (ret != SUCCESS) { + dump_error(); + printf("Error: RNG generate failed 0x%x\n", ret); + } return ret; } @@ -334,112 +244,496 @@ uint32_t caam_hwrng(uint8_t *output_ptr, uint32_t output_len) { */ void caam_open(void) { - uint32_t temp_reg; - //uint32_t addr; + u32 temp_reg; + int ret; - /* switch on the clock */ -#if defined(CONFIG_MX6) + /* switch on the clock */ +#ifndef CONFIG_ARCH_IMX8 + caam_clock_enable(); +#endif + + /* reset the CAAM */ + temp_reg = __raw_readl(CAAM_MCFGR) | + CAAM_MCFGR_DMARST | CAAM_MCFGR_SWRST; + __raw_writel(temp_reg, CAAM_MCFGR); + while (__raw_readl(CAAM_MCFGR) & CAAM_MCFGR_DMARST) + ; + + jr_reset(); + ret = do_cfg_jrqueue(); + + if (ret != SUCCESS) { + printf("Error CAAM JR initialization\n"); + return; + } + + /* Check if the RNG is already instantiated */ + temp_reg = __raw_readl(CAAM_RDSTA); + if (temp_reg == (RDSTA_IF0 | RDSTA_IF1 | RDSTA_SKVN)) { + printf("RNG already instantiated 0x%X\n", temp_reg); + return; + } + + rng_init(); +} + +static void caam_clock_enable(void) +{ +#if defined(CONFIG_ARCH_MX6) struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; - temp_reg = __raw_readl(&mxc_ccm->CCGR0); - temp_reg |= MXC_CCM_CCGR0_CAAM_SECURE_MEM_MASK | + u32 reg; + + reg = __raw_readl(&mxc_ccm->CCGR0); + + 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); -#elif defined(CONFIG_MX7) - HW_CCM_CCGR_SET(36, MXC_CCM_CCGR36_CAAM_DOMAIN0_MASK); + MXC_CCM_CCGR0_CAAM_WRAPPER_IPG_MASK); + + __raw_writel(reg, &mxc_ccm->CCGR0); + +#ifndef CONFIG_MX6UL + /* EMI slow clk */ + reg = __raw_readl(&mxc_ccm->CCGR6); + reg |= MXC_CCM_CCGR6_EMI_SLOW_MASK; + + __raw_writel(reg, &mxc_ccm->CCGR6); +#endif + +#elif defined(CONFIG_ARCH_MX7) + HW_CCM_CCGR_SET(36, MXC_CCM_CCGR36_CAAM_DOMAIN0_MASK); +#elif defined(CONFIG_ARCH_MX7ULP) + pcc_clock_enable(PER_CLK_CAAM, true); #endif +} - /* MID for CAAM - already done by HAB in ROM during preconfigure, - * That is JROWN for JR0/1 = 1 (TZ, Secure World, ARM) - * JRNSMID and JRSMID for JR0/1 = 2 (TZ, Secure World, CAAM) - * - * 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 - __raw_writel((uint32_t)g_output_ring, CAAM_ORBAR0); // output ring address - - /* Initialize job ring sizes to 1 */ - __raw_writel(JOB_RING_ENTRIES, CAAM_IRSR0); - __raw_writel(JOB_RING_ENTRIES, CAAM_ORSR0); - - /* 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); - - /********* Initialize and instantiate the RNG *******************/ - /* if RNG already instantiated then skip it */ - if ((__raw_readl(CAAM_RDSTA) & RDSTA_IF0) != RDSTA_IF0) - { - /* Enter TRNG Program mode */ - __raw_writel(RTMCTL_PGM, CAAM_RTMCTL); - - /* Set OSC_DIV field to TRNG */ - temp_reg = __raw_readl(CAAM_RTMCTL) | (RNG_TRIM_OSC_DIV << 2); - __raw_writel(temp_reg, CAAM_RTMCTL); - - /* Set delay */ - __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); +static void kick_trng(u32 ent_delay) +{ + 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; + + /* Put RNG in program mode */ + setbits_le32(CAAM_RTMCTL, RTMCTL_PGM); + /* 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 = __raw_readl(CAAM_RTSDCTL); + val &= BM_TRNG_ENT_DLY; + val >>= BS_TRNG_ENT_DLY; + if (ent_delay < val) { + /* Put RNG4 into run mode */ + clrbits_le32(CAAM_RTMCTL, RTMCTL_PGM); + return; + } + + val = (ent_delay << BS_TRNG_ENT_DLY) | samples; + __raw_writel(val, CAAM_RTSDCTL); + + /* min. freq. count, equal to 1/2 of the entropy sample length */ + __raw_writel(ent_delay >> 1, CAAM_RTFRQMIN); + + /* max. freq. count, equal to 32 times the entropy sample length */ + __raw_writel(ent_delay << 5, CAAM_RTFRQMAX); + + __raw_writel((retries << 16) | lrun_max, CAAM_RTSCMISC); + __raw_writel(poker_max, CAAM_RTPKRMAX); + __raw_writel(poker_range, CAAM_RTPKRRNG); + __raw_writel((mono_range << 16) | mono_max, CAAM_RTSCML); + __raw_writel((run_1_range << 16) | run_1_max, CAAM_RTSCR1L); + __raw_writel((run_2_range << 16) | run_2_max, CAAM_RTSCR2L); + __raw_writel((run_3_range << 16) | run_3_max, CAAM_RTSCR3L); + __raw_writel((run_4_range << 16) | run_4_max, CAAM_RTSCR4L); + __raw_writel((run_5_range << 16) | run_5_max, CAAM_RTSCR5L); + __raw_writel((run_6_range << 16) | run_6_max, CAAM_RTSCR6PL); + + val = __raw_readl(CAAM_RTMCTL); + /* + * Select raw sampling in both entropy shifter + * and statistical checker + */ + val &= ~BM_TRNG_SAMP_MODE; + val |= TRNG_SAMP_MODE_RAW_ES_SC; + /* Put RNG4 into run mode */ + val &= ~RTMCTL_PGM; +/*test with sample mode only */ + __raw_writel(val, 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. * This error is possible if ROM code does not initialize the system PLLs * immediately after PoR. */ - temp_reg = __raw_readl(CAAM_RTMCTL) | RTMCTL_ERR; - __raw_writel(temp_reg, CAAM_RTMCTL); + /* setbits_le32(CAAM_RTMCTL, RTMCTL_ERR); */ +} + +/* + * Descriptors to instantiate SH0, SH1, load the keys + */ +static const u32 rng_inst_sh0_desc[] = { + /* Header, don't setup the size */ + CAAM_HDR_CTYPE | CAAM_HDR_ONE | CAAM_HDR_START_INDEX(0), + /* Operation instantiation (sh0) */ + CAAM_PROTOP_CTYPE | CAAM_C1_RNG | ALGO_RNG_SH(0) | ALGO_RNG_INSTANTIATE, +}; + +static const u32 rng_inst_sh1_desc[] = { + /* wait for done - Jump to next entry */ + CAAM_C1_JUMP | CAAM_JUMP_LOCAL | CAAM_JUMP_TST_ALL_COND_TRUE + | CAAM_JUMP_OFFSET(1), + /* Clear written register (write 1) */ + CAAM_C0_LOAD_IMM | CAAM_DST_CLEAR_WRITTEN | sizeof(u32), + 0x00000001, + /* Operation instantiation (sh1) */ + CAAM_PROTOP_CTYPE | CAAM_C1_RNG | ALGO_RNG_SH(1) + | ALGO_RNG_INSTANTIATE, +}; + +static const u32 rng_inst_load_keys[] = { + /* wait for done - Jump to next entry */ + CAAM_C1_JUMP | CAAM_JUMP_LOCAL | CAAM_JUMP_TST_ALL_COND_TRUE + | CAAM_JUMP_OFFSET(1), + /* Clear written register (write 1) */ + CAAM_C0_LOAD_IMM | CAAM_DST_CLEAR_WRITTEN | sizeof(u32), + 0x00000001, + /* Generate the Key */ + CAAM_PROTOP_CTYPE | CAAM_C1_RNG | BM_ALGO_RNG_SK | ALGO_RNG_GENERATE, +}; + +static void do_inst_desc(u32 *desc, u32 status) +{ + u32 *pdesc = desc; + u8 desc_len; + bool add_sh0 = false; + bool add_sh1 = false; + bool load_keys = false; + + /* + * Modify the the descriptor to remove if necessary: + * - The key loading + * - One of the SH already instantiated + */ + desc_len = RNG_DESC_SH0_SIZE; + if ((status & RDSTA_IF0) != RDSTA_IF0) + add_sh0 = true; + + if ((status & RDSTA_IF1) != RDSTA_IF1) { + add_sh1 = true; + if (add_sh0) + desc_len += RNG_DESC_SH1_SIZE; + } + + if ((status & RDSTA_SKVN) != RDSTA_SKVN) { + load_keys = true; + desc_len += RNG_DESC_KEYS_SIZE; + } + + /* Copy the SH0 descriptor anyway */ + memcpy(pdesc, rng_inst_sh0_desc, sizeof(rng_inst_sh0_desc)); + pdesc += RNG_DESC_SH0_SIZE; + + if (load_keys) { + debug("RNG - Load keys\n"); + memcpy(pdesc, rng_inst_load_keys, sizeof(rng_inst_load_keys)); + pdesc += RNG_DESC_KEYS_SIZE; + } + + if (add_sh1) { + if (add_sh0) { + debug("RNG - Instantiation of SH0 and SH1\n"); + /* Add the sh1 descriptor */ + memcpy(pdesc, rng_inst_sh1_desc, + sizeof(rng_inst_sh1_desc)); + } else { + debug("RNG - Instantiation of SH1 only\n"); + /* Modify the SH0 descriptor to instantiate only SH1 */ + desc[1] &= ~BM_ALGO_RNG_SH; + desc[1] |= ALGO_RNG_SH(1); + } + } + + /* Setup the descriptor size */ + desc[0] &= ~(0x3F); + desc[0] |= CAAM_HDR_DESCLEN(desc_len); +} + +static int jr_reset(void) +{ + /* + * Function reset the Job Ring HW + * Reset is done in 2 steps: + * - Flush all pending jobs (Set RESET bit) + * - Reset the Job Ring (Set RESET bit second time) + */ + u16 timeout = 10000; + u32 reg_val; + + /* Mask interrupts to poll for reset completion status */ + setbits_le32(CAAM_JRCFGR0_LS, BM_JRCFGR_LS_IMSK); + + /* Initiate flush (required prior to reset) */ + __raw_writel(JRCR_RESET, CAAM_JRCR0); + do { + reg_val = __raw_readl(CAAM_JRINTR0); + reg_val &= BM_JRINTR_HALT; + } while ((reg_val == JRINTR_HALT_ONGOING) && --timeout); - /* Run descriptor to instantiate the RNG */ - /* Add job to input ring */ - g_input_ring[0] = (uint32_t)rng_inst_dsc; + if (!timeout || reg_val != JRINTR_HALT_DONE) { + printf("Failed to flush job ring\n"); + return ERROR_ANY; + } + + /* Initiate reset */ + timeout = 100; + __raw_writel(JRCR_RESET, CAAM_JRCR0); + do { + reg_val = __raw_readl(CAAM_JRCR0); + } while ((reg_val & JRCR_RESET) && --timeout); + + if (!timeout) { + printf("Failed to reset job ring\n"); + return ERROR_ANY; + } - flush_dcache_range((uint32_t)g_input_ring & 0xffffffe0, - ((uint32_t)g_input_ring & 0xffffffe0) + 128); - /* Increment jobs added */ + return 0; +} + +static int do_job(u32 *desc) +{ + int ret; + phys_addr_t p_desc = virt_to_phys(desc); + + if (__raw_readl(CAAM_IRSAR0) == 0) + return ERROR_ANY; + g_jrdata.inrings[0].desc = p_desc; + + flush_dcache_range((uintptr_t)g_jrdata.inrings & ALIGN_MASK, + ((uintptr_t)g_jrdata.inrings & ALIGN_MASK) + + ROUND(DESC_MAX_SIZE, ARCH_DMA_MINALIGN)); + flush_dcache_range((uintptr_t)desc & ALIGN_MASK, + ((uintptr_t)desc & ALIGN_MASK) + + ROUND(DESC_MAX_SIZE, ARCH_DMA_MINALIGN)); + + /* Inform HW that a new JR is available */ __raw_writel(1, CAAM_IRJAR0); + while (__raw_readl(CAAM_ORSFR0) == 0) + ; + + flush_dcache_range((uintptr_t)g_jrdata.outrings & ALIGN_MASK, + ((uintptr_t)g_jrdata.outrings & ALIGN_MASK) + + ROUND(DESC_MAX_SIZE, ARCH_DMA_MINALIGN)); - /* Wait for job ring to complete the job: 1 completed job expected */ - while(__raw_readl(CAAM_ORSFR0) != 1); - - - invalidate_dcache_range((uint32_t)g_output_ring & 0xffffffe0, - ((uint32_t)g_output_ring & 0xffffffe0) + 128); - - /* check that descriptor address is the one expected in the out ring */ - if(g_output_ring[0] == (uint32_t)rng_inst_dsc) - { - /* check if any error is reported in the output ring */ - if ((g_output_ring[1] & JOB_RING_STS) != 0) - { - printf("Error: RNG instantiation errors g_output_ring[1]: 0x%X\n" - , g_output_ring[1]); - printf("RTMCTL 0x%X\n", __raw_readl(CAAM_RTMCTL)); - printf("RTSTATUS 0x%X\n", __raw_readl(CAAM_RTSTATUS)); - printf("RTSTA 0x%X\n", __raw_readl(CAAM_RDSTA)); - } + if (PTR2CAAMDMA(desc) == g_jrdata.outrings[0].desc) { + ret = g_jrdata.outrings[0].status; + } else { + dump_error(); + ret = ERROR_ANY; } - else - { - printf("Error: RNG job output ring descriptor address does " \ - "not match: 0x%X != 0x%X \n", g_output_ring[0], rng_inst_dsc[0]); + + /* Acknowledge interrupt */ + setbits_le32(CAAM_JRINTR0, JRINTR_JRI); + + /* Remove the JR from the output list even if no JR caller found */ + __raw_writel(1, CAAM_ORJRR0); + + return ret; +} + +static int do_cfg_jrqueue(void) +{ + u32 value = 0; + phys_addr_t ip_base; + phys_addr_t op_base; + + /* check if already configured after relocation */ + if (g_jrdata.status & RING_RELOC_INIT) + return 0; + + /* + * jr configuration needs to be updated once, after relocation to ensure + * using the right buffers. + * When buffers are updated after relocation the flag RING_RELOC_INIT + * is used to prevent extra updates + */ + if (gd->flags & GD_FLG_RELOC) { + g_jrdata.inrings = (struct inring_entry *) + memalign(ARCH_DMA_MINALIGN, + ARCH_DMA_MINALIGN); + g_jrdata.outrings = (struct outring_entry *) + memalign(ARCH_DMA_MINALIGN, + ARCH_DMA_MINALIGN); + g_jrdata.desc = (u32 *) + memalign(ARCH_DMA_MINALIGN, ARCH_DMA_MINALIGN); + g_jrdata.status |= RING_RELOC_INIT; + } else { + u32 align_idx = 0; + + /* Ensure 64bits buffers addresses alignment */ + if ((uintptr_t)g_jrdata.raw_addr & 0x7) + align_idx = 1; + g_jrdata.inrings = (struct inring_entry *) + (&g_jrdata.raw_addr[align_idx]); + g_jrdata.outrings = (struct outring_entry *) + (&g_jrdata.raw_addr[align_idx + 2]); + g_jrdata.desc = (u32 *)(&g_jrdata.raw_addr[align_idx + 4]); + g_jrdata.status |= RING_EARLY_INIT; } - /* ensure that the RNG was correctly instantiated */ - temp_reg = __raw_readl(CAAM_RDSTA); - if (temp_reg != (RDSTA_IF0 | RDSTA_SKVN)) - { - printf("Error: RNG instantiation failed 0x%X\n", temp_reg); + if (!g_jrdata.inrings || !g_jrdata.outrings) + return ERROR_ANY; + + /* Configure the HW Job Rings */ + ip_base = virt_to_phys((void *)g_jrdata.inrings); + op_base = virt_to_phys((void *)g_jrdata.outrings); + __raw_writel(ip_base, CAAM_IRBAR0); + __raw_writel(1, CAAM_IRSR0); + + __raw_writel(op_base, CAAM_ORBAR0); + __raw_writel(1, CAAM_ORSR0); + + setbits_le32(CAAM_JRINTR0, JRINTR_JRI); + + /* + * Configure interrupts but disable it: + * Optimization to generate an interrupt either when there are + * half of the job done or when there is a job done and + * 10 clock cycles elapse without new job complete + */ + value = 10 << BS_JRCFGR_LS_ICTT; + value |= (1 << BS_JRCFGR_LS_ICDCT) & BM_JRCFGR_LS_ICDCT; + value |= BM_JRCFGR_LS_ICEN; + value |= BM_JRCFGR_LS_IMSK; + __raw_writel(value, CAAM_JRCFGR0_LS); + + /* Enable deco watchdog */ + setbits_le32(CAAM_MCFGR, BM_MCFGR_WDE); + + return 0; +} + +static void do_clear_rng_error(void) +{ + u32 val; + + val = __raw_readl(CAAM_RTMCTL); + + if (val & (RTMCTL_ERR | RTMCTL_FCT_FAIL)) { + setbits_le32(CAAM_RTMCTL, RTMCTL_ERR); + val = __raw_readl(CAAM_RTMCTL); + } +} + +static int do_instantiation(void) +{ + int ret = ERROR_ANY; + u32 cha_vid_ls; + u32 ent_delay; + u32 status; + + if (!g_jrdata.desc) { + printf("%d: CAAM Descriptor allocation error\n", __LINE__); + return ERROR_ANY; + } + + cha_vid_ls = __raw_readl(CAAM_CHAVID_LS); + + /* + * If SEC has RNG version >= 4 and RNG state handle has not been + * already instantiated, do RNG instantiation + */ + if (((cha_vid_ls & BM_CHAVID_LS_RNGVID) >> BS_CHAVID_LS_RNGVID) < 4) { + printf("%d: RNG already instantiated\n", __LINE__); + return 0; + } + + ent_delay = TRNG_SDCTL_ENT_DLY_MIN; + + do { + /* Read the CAAM RNG status */ + status = __raw_readl(CAAM_RDSTA); + + if ((status & RDSTA_IF0) != RDSTA_IF0) { + /* Configure the RNG entropy delay */ + kick_trng(ent_delay); + ent_delay += 400; } - /* Remove job from Job Ring Output Queue */ - __raw_writel(1, CAAM_ORJRR0); + + do_clear_rng_error(); + + if ((status & (RDSTA_IF0 | RDSTA_IF1)) != + (RDSTA_IF0 | RDSTA_IF1)) { + /* Prepare the instantiation descriptor */ + do_inst_desc(g_jrdata.desc, status); + + /* Run Job */ + ret = do_job(g_jrdata.desc); + + if (ret == ERROR_ANY) { + /* CAAM JR failure ends here */ + printf("RNG Instantiation error\n"); + dump_error(); + goto end_instantation; + } + } else { + ret = SUCCESS; + printf("RNG instantiation done (%d)\n", ent_delay); + goto end_instantation; + } + } while (ent_delay < TRNG_SDCTL_ENT_DLY_MAX); + + printf("RNG Instantation Failure - Entropy delay (%d)\n", ent_delay); + ret = ERROR_ANY; + +end_instantation: + return ret; +} + +static void rng_init(void) +{ + int ret; + + ret = jr_reset(); + if (ret != SUCCESS) { + printf("Error CAAM JR reset\n"); + return; } + + ret = do_instantiation(); + + if (ret != SUCCESS) + printf("Error do_instantiation\n"); + + jr_reset(); + return; } + diff --git a/drivers/crypto/fsl_caam_internal.h b/drivers/crypto/fsl_caam_internal.h index 7cc8d7ebffa..852672d1cb7 100644 --- a/drivers/crypto/fsl_caam_internal.h +++ b/drivers/crypto/fsl_caam_internal.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2012-2016, Freescale Semiconductor, Inc. * All rights reserved. + * Copyright 2018 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -29,7 +30,7 @@ */ #ifndef __CAAM_INTERNAL_H__ -#define __CAAM_INTERNAL_H__ +#define __CAAM_INTERNAL_H__ /* 4kbyte pages */ #define CAAM_SEC_RAM_START_ADDR CAAM_ARB_BASE_ADDR @@ -40,69 +41,82 @@ #define SEC_MEM_PAGE3 (CAAM_SEC_RAM_START_ADDR + 0x3000) /* Configuration and special key registers */ -#define CAAM_MCFGR CONFIG_SYS_FSL_SEC_ADDR + 0x0004 -#define CAAM_SCFGR CONFIG_SYS_FSL_SEC_ADDR + 0x000c -#define CAAM_JR0MIDR CONFIG_SYS_FSL_SEC_ADDR + 0x0010 -#define CAAM_JR1MIDR CONFIG_SYS_FSL_SEC_ADDR + 0x0018 -#define CAAM_DECORR CONFIG_SYS_FSL_SEC_ADDR + 0x009c -#define CAAM_DECO0MID CONFIG_SYS_FSL_SEC_ADDR + 0x00a0 -#define CAAM_DAR CONFIG_SYS_FSL_SEC_ADDR + 0x0120 -#define CAAM_DRR CONFIG_SYS_FSL_SEC_ADDR + 0x0124 -#define CAAM_JDKEKR CONFIG_SYS_FSL_SEC_ADDR + 0x0400 -#define CAAM_TDKEKR CONFIG_SYS_FSL_SEC_ADDR + 0x0420 -#define CAAM_TDSKR CONFIG_SYS_FSL_SEC_ADDR + 0x0440 -#define CAAM_SKNR CONFIG_SYS_FSL_SEC_ADDR + 0x04e0 -#define CAAM_SMSTA CONFIG_SYS_FSL_SEC_ADDR + 0x0FB4 -#define CAAM_STA CONFIG_SYS_FSL_SEC_ADDR + 0x0FD4 -#define CAAM_SMPO_0 CONFIG_SYS_FSL_SEC_ADDR + 0x1FBC +#define CAAM_MCFGR (CONFIG_SYS_FSL_SEC_ADDR + 0x0004) +#define CAAM_SCFGR (CONFIG_SYS_FSL_SEC_ADDR + 0x000c) +#define CAAM_JR0MIDR (CONFIG_SYS_FSL_SEC_ADDR + 0x0010) +#define CAAM_JR1MIDR (CONFIG_SYS_FSL_SEC_ADDR + 0x0018) +#define CAAM_DECORR (CONFIG_SYS_FSL_SEC_ADDR + 0x009c) +#define CAAM_DECO0MID (CONFIG_SYS_FSL_SEC_ADDR + 0x00a0) +#define CAAM_DAR (CONFIG_SYS_FSL_SEC_ADDR + 0x0120) +#define CAAM_DRR (CONFIG_SYS_FSL_SEC_ADDR + 0x0124) +#define CAAM_JDKEKR (CONFIG_SYS_FSL_SEC_ADDR + 0x0400) +#define CAAM_TDKEKR (CONFIG_SYS_FSL_SEC_ADDR + 0x0420) +#define CAAM_TDSKR (CONFIG_SYS_FSL_SEC_ADDR + 0x0440) +#define CAAM_SKNR (CONFIG_SYS_FSL_SEC_ADDR + 0x04e0) +#define CAAM_SMSTA (CONFIG_SYS_FSL_SEC_ADDR + 0x0FB4) +#define CAAM_STA (CONFIG_SYS_FSL_SEC_ADDR + 0x0FD4) +#define CAAM_SMPO_0 (CONFIG_SYS_FSL_SEC_ADDR + 0x1FBC) +#define CAAM_CHAVID_LS (CONFIG_SYS_FSL_SEC_ADDR + 0x0FEC) +#define CAAM_FAR (CONFIG_SYS_FSL_SEC_ADDR + 0x0FC0) +#define CAAM_FAMR (CONFIG_SYS_FSL_SEC_ADDR + 0x0FC8) +#define CAAM_FADR (CONFIG_SYS_FSL_SEC_ADDR + 0x0FCC) /* RNG registers */ -#define CAAM_RTMCTL CONFIG_SYS_FSL_SEC_ADDR + 0x0600 -#define CAAM_RTSDCTL CONFIG_SYS_FSL_SEC_ADDR + 0x0610 -#define CAAM_RTFRQMIN CONFIG_SYS_FSL_SEC_ADDR + 0x0618 -#define CAAM_RTFRQMAX CONFIG_SYS_FSL_SEC_ADDR + 0x061C -#define CAAM_RTSTATUS CONFIG_SYS_FSL_SEC_ADDR + 0x063C -#define CAAM_RDSTA CONFIG_SYS_FSL_SEC_ADDR + 0x06C0 +#define CAAM_RTMCTL (CONFIG_SYS_FSL_SEC_ADDR + 0x0600) +#define CAAM_RTSCMISC (CONFIG_SYS_FSL_SEC_ADDR + 0x0604) +#define CAAM_RTPKRRNG (CONFIG_SYS_FSL_SEC_ADDR + 0x0608) +#define CAAM_RTPKRMAX (CONFIG_SYS_FSL_SEC_ADDR + 0x060C) +#define CAAM_RTSDCTL (CONFIG_SYS_FSL_SEC_ADDR + 0x0610) +#define CAAM_RTFRQMIN (CONFIG_SYS_FSL_SEC_ADDR + 0x0618) +#define CAAM_RTFRQMAX (CONFIG_SYS_FSL_SEC_ADDR + 0x061C) +#define CAAM_RTSCML (CONFIG_SYS_FSL_SEC_ADDR + 0x0620) +#define CAAM_RTSCR1L (CONFIG_SYS_FSL_SEC_ADDR + 0x0624) +#define CAAM_RTSCR2L (CONFIG_SYS_FSL_SEC_ADDR + 0x0628) +#define CAAM_RTSCR3L (CONFIG_SYS_FSL_SEC_ADDR + 0x062C) +#define CAAM_RTSCR4L (CONFIG_SYS_FSL_SEC_ADDR + 0x0630) +#define CAAM_RTSCR5L (CONFIG_SYS_FSL_SEC_ADDR + 0x0634) +#define CAAM_RTSCR6PL (CONFIG_SYS_FSL_SEC_ADDR + 0x0638) +#define CAAM_RTSTATUS (CONFIG_SYS_FSL_SEC_ADDR + 0x063C) +#define CAAM_RDSTA (CONFIG_SYS_FSL_SEC_ADDR + 0x06C0) /* Job Ring 0 registers */ -#define CAAM_IRBAR0 CONFIG_SYS_FSL_SEC_ADDR + 0x1004 -#define CAAM_IRSR0 CONFIG_SYS_FSL_SEC_ADDR + 0x100c -#define CAAM_IRSAR0 CONFIG_SYS_FSL_SEC_ADDR + 0x1014 -#define CAAM_IRJAR0 CONFIG_SYS_FSL_SEC_ADDR + 0x101c -#define CAAM_ORBAR0 CONFIG_SYS_FSL_SEC_ADDR + 0x1024 -#define CAAM_ORSR0 CONFIG_SYS_FSL_SEC_ADDR + 0x102c -#define CAAM_ORJRR0 CONFIG_SYS_FSL_SEC_ADDR + 0x1034 -#define CAAM_ORSFR0 CONFIG_SYS_FSL_SEC_ADDR + 0x103c -#define CAAM_JRSTAR0 CONFIG_SYS_FSL_SEC_ADDR + 0x1044 -#define CAAM_JRINTR0 CONFIG_SYS_FSL_SEC_ADDR + 0x104c -#define CAAM_JRCFGR0_MS CONFIG_SYS_FSL_SEC_ADDR + 0x1050 -#define CAAM_JRCFGR0_LS CONFIG_SYS_FSL_SEC_ADDR + 0x1054 -#define CAAM_IRRIR0 CONFIG_SYS_FSL_SEC_ADDR + 0x105c -#define CAAM_ORWIR0 CONFIG_SYS_FSL_SEC_ADDR + 0x1064 -#define CAAM_JRCR0 CONFIG_SYS_FSL_SEC_ADDR + 0x106c -#define CAAM_SMCJR0 CONFIG_SYS_FSL_SEC_ADDR + 0x10f4 -#define CAAM_SMCSJR0 CONFIG_SYS_FSL_SEC_ADDR + 0x10fc +#define CAAM_IRBAR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x1004) +#define CAAM_IRSR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x100c) +#define CAAM_IRSAR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x1014) +#define CAAM_IRJAR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x101c) +#define CAAM_ORBAR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x1024) +#define CAAM_ORSR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x102c) +#define CAAM_ORJRR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x1034) +#define CAAM_ORSFR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x103c) +#define CAAM_JRSTAR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x1044) +#define CAAM_JRINTR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x104c) +#define CAAM_JRCFGR0_MS (CONFIG_SYS_FSL_SEC_ADDR + 0x1050) +#define CAAM_JRCFGR0_LS (CONFIG_SYS_FSL_SEC_ADDR + 0x1054) +#define CAAM_IRRIR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x105c) +#define CAAM_ORWIR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x1064) +#define CAAM_JRCR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x106c) +#define CAAM_SMCJR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x10f4) +#define CAAM_SMCSJR0 (CONFIG_SYS_FSL_SEC_ADDR + 0x10fc) #define CAAM_SMAPJR0(y) (CONFIG_SYS_FSL_SEC_ADDR + 0x1104 + y*16) #define CAAM_SMAG2JR0(y) (CONFIG_SYS_FSL_SEC_ADDR + 0x1108 + y*16) #define CAAM_SMAG1JR0(y) (CONFIG_SYS_FSL_SEC_ADDR + 0x110C + y*16) -#define CAAM_SMAPJR0_PRTN1 CONFIG_SYS_FSL_SEC_ADDR + 0x1114 -#define CAAM_SMAG2JR0_PRTN1 CONFIG_SYS_FSL_SEC_ADDR + 0x1118 -#define CAAM_SMAG1JR0_PRTN1 CONFIG_SYS_FSL_SEC_ADDR + 0x111c -#define CAAM_SMPO CONFIG_SYS_FSL_SEC_ADDR + 0x1fbc - -#define JRCFG_LS_IMSK 0x00000001 /* Interrupt Mask */ -#define JR_MID 2 /* Matches ROM configuration */ -#define KS_G1 (1 << JR_MID) /* CAAM only */ -#define PERM 0x0000B008 /* Clear on release, - * lock SMAP - * lock SMAG - * group 1 Blob - */ - -#define CMD_PAGE_ALLOC 0x1 -#define CMD_PAGE_DEALLOC 0x2 -#define CMD_PART_DEALLOC 0x3 -#define CMD_INQUIRY 0x5 +#define CAAM_SMAPJR0_PRTN1 (CONFIG_SYS_FSL_SEC_ADDR + 0x1114) +#define CAAM_SMAG2JR0_PRTN1 (CONFIG_SYS_FSL_SEC_ADDR + 0x1118) +#define CAAM_SMAG1JR0_PRTN1 (CONFIG_SYS_FSL_SEC_ADDR + 0x111c) +#define CAAM_SMPO (CONFIG_SYS_FSL_SEC_ADDR + 0x1fbc) + +#define DESC_MAX_SIZE (0x40) /* Descriptor max size */ +#define JRCFG_LS_IMSK (0x01) /* Interrupt Mask */ +#define JR_MID (0x02) /* Matches ROM configuration */ +#define KS_G1 BIT(JR_MID) /* CAAM only */ +#define PERM (0x0000B008) /* Clear on release, lock SMAP, + * lock SMAG and group 1 Blob + */ + +#define CMD_PAGE_ALLOC (0x1) +#define CMD_PAGE_DEALLOC (0x2) +#define CMD_PART_DEALLOC (0x3) +#define CMD_INQUIRY (0x5) #define PAGE(x) (x << 16) #define PARTITION(x) (x << 8) @@ -111,27 +125,55 @@ #define CMD_COMPLETE (3 << 14) #define SMCSJR_PO (3 << 6) -#define PAGE_AVAILABLE 0 +#define PAGE_AVAILABLE (0) #define PAGE_OWNED (3 << 6) #define PARTITION_OWNER(x) (0x3 << (x*2)) -#define CAAM_BUSY_MASK 0x00000001 /* BUSY from status reg */ -#define CAAM_IDLE_MASK 0x00000002 /* IDLE from status reg */ +#define CAAM_BUSY_MASK (0x00000001) /* BUSY from status reg */ +#define CAAM_IDLE_MASK (0x00000002) /* IDLE from status reg */ +#define CAAM_MCFGR_SWRST BIT(31) /* CAAM SW reset */ +#define CAAM_MCFGR_DMARST BIT(28) /* CAAM DMA reset */ -#define JOB_RING_ENTRIES 1 +#define JOB_RING_ENTRIES (1) #define JOB_RING_STS (0xF << 28) /** OSC_DIV in RNG trim fuses */ -#define RNG_TRIM_OSC_DIV 0 +#define RNG_TRIM_OSC_DIV (0) /** ENT_DLY multiplier in RNG trim fuses */ -//#define RNG_TRIM_ENT_DLY 200*4 -#define RNG_TRIM_ENT_DLY 3200 - -#define RTMCTL_PGM (1 << 16) -#define RTMCTL_ERR (1 << 12) -#define RDSTA_IF0 1 -#define RDSTA_SKVN (1 << 30) +#define TRNG_SDCTL_ENT_DLY_MIN (3200) +#define TRNG_SDCTL_ENT_DLY_MAX (4800) + +#define RTMCTL_PGM BIT(16) +#define RTMCTL_ERR BIT(12) +#define RTMCTL_RST BIT(6) +#define RDSTA_IF0 (1) +#define RDSTA_IF1 (2) +#define RDSTA_SKVN BIT(30) +#define JRCR_RESET (1) +#define RTMCTL_FCT_FAIL BIT(8) + +#define BS_TRNG_ENT_DLY (16) +#define BM_TRNG_ENT_DLY (0xffff << BS_TRNG_ENT_DLY) +#define BM_TRNG_SAMP_MODE (3) +#define TRNG_SAMP_MODE_RAW_ES_SC (1) +#define BS_JRINTR_HALT (2) +#define BM_JRINTR_HALT (0x3 << BS_JRINTR_HALT) +#define JRINTR_HALT_ONGOING (0x1 << BS_JRINTR_HALT) +#define JRINTR_HALT_DONE (0x2 << BS_JRINTR_HALT) +#define JRINTR_JRI (0x1) +#define BS_JRCFGR_LS_ICTT (16) +#define BM_JRCFGR_LS_ICTT (0xFFFF << BS_JRCFGR_LS_ICTT) +#define BS_JRCFGR_LS_ICDCT (8) +#define BM_JRCFGR_LS_ICDCT (0xFF << BS_JRCFGR_LS_ICDCT) +#define BS_JRCFGR_LS_ICEN (1) +#define BM_JRCFGR_LS_ICEN (0x1 << BS_JRCFGR_LS_ICEN) +#define BS_JRCFGR_LS_IMSK (0) +#define BM_JRCFGR_LS_IMSK (0x1 << BS_JRCFGR_LS_IMSK) +#define BS_CHAVID_LS_RNGVID (16) +#define BM_CHAVID_LS_RNGVID (0xF << BS_CHAVID_LS_RNGVID) +#define BS_MCFGR_WDE (30) +#define BM_MCFGR_WDE (0x1 << BS_MCFGR_WDE) typedef enum { PAGE_0, @@ -151,251 +193,63 @@ typedef enum { PARTITION_7, } partition_num_e; -/***************************************** - *----- Blob decapsulate descriptor -----* - *****************************************/ -/* 1. Header - * - * 1011 0000 1000 0000 0000 0000 0000 1001 - * |||| | |||| - * ++++-+-- Header ++++-- 9 words in descriptor - */ -#define DECAP_BLOB_DESC1 0xB0800009 - -/* 2. Load command KEY 2 immediate - * - * 0001 0100 1100 0000 0000 1100 0000 1000 - * |||| ||| |||| |||| |||| |||| |||| |||| - * |||| ||| |||| |||| |||| |||| ++++-++++-- Length - * |||| ||| |||| |||| ++++-++++-- Offset - * |||| ||| |+++-++++-- DST (Destination Register) Key2 - * |||| ||| +-- IMM (Immediate flag) - * |||| |++-- class 2 - * ++++-+-- Load command - */ -#define DECAP_BLOB_DESC2 0x14C00C08 - -/* 3. 8 bytes for load command above - aad data - * - * 0000 0000 0001 0000 0101 0101 0110 0110 - * |||| |||| |||| |||| |||| |||| |||| |||| - * |||| |||| |||| |||| |||| |||| ++++-++++-- CCM Mode - * |||| |||| |||| |||| ++++-++++-- AES - * |||| |||| ++++-++++-- Length - * ++++-++++-- Flag - */ -#define DECAP_BLOB_DESC3 0x00105566 -#define DECAP_BLOB_DESC4 0x00000000 - -/* 5. SEQ In Ptr - * - * 1111 0000 0000 0000 0000 0000 0100 0000 - * |||| | |||| |||| |||| |||| - * |||| | ++++-++++-++++-++++-- Length in bytes (64) - * ++++-+-- Seq In Ptr - */ -#define DECAP_BLOB_DESC5 0xF0000400 -//#define DECAP_BLOB_DESC5 0xF0000040 - -/* 6. Pointer for above SEQ In ptr command */ -/* Address is provided during run time */ -#define DECAP_BLOB_DESC6 0x00000000 - -/* 7. SEQ Out Ptr - * - * 1111 1000 0000 0000 0000 0000 0001 0000 - * |||| | |||| |||| |||| |||| - * |||| | ++++-++++-++++-++++-- Length in bytes (16) - * ++++-+-- Seq In Ptr - */ -#define DECAP_BLOB_DESC7 0xF80003d0 -//#define DECAP_BLOB_DESC7 0xF8000010 - -/* 8. Pointer for above SEQ Out ptr command */ -/* Address could be changed during run time */ -#define DECAP_BLOB_DESC8 SEC_MEM_PAGE1 - -/* 9. Protocol - * - * 1000 0110 0000 1101 0000 0000 0000 1000 - * |||| |||| |||| |||| |||| |||| |||| |||| - * |||| |||| |||| |||| ++++-++++-++++-++++-- Proto Info = sec mem blob - * |||| |||| ++++-++++-- Protocol ID = Blob - * |||| |+++-- Optype - decapsulation protocol - * ++++-+-- Seq In Ptr - */ -#define DECAP_BLOB_DESC9 0x860D0008 - -/***************************************** - *----- Blob encapsulate descriptor -----* - *****************************************/ -/* Blob Header - * - * 1011 0000 1000 0000 0000 0000 0000 1001 - * |||| | | - * ++++-+-- Header +-- 9 words in descriptor - */ -#define ENCAP_BLOB_DESC1 0xB0800009 - -/* 2. Load command KEY 2 immediate - * - * 0001 0100 1100 0000 0000 1100 0000 1000 - * |||| ||| |||| |||| |||| |||| |||| |||| - * |||| ||| |||| |||| |||| |||| ++++-++++-- Length - * |||| ||| |||| |||| ++++-++++-- Offset - * |||| ||| |+++-++++-- DST (Destination Register) Key2 - * |||| ||| +-- IMM (Immediate flag) - * |||| |++-- class 2 - * ++++-+-- Load command - */ -#define ENCAP_BLOB_DESC2 0x14C00C08 - -/* 3. 8 bytes for load command above - aad data - * - * 0000 0000 0001 0000 0101 0101 0110 0110 - * |||| |||| |||| |||| |||| |||| |||| |||| - * |||| |||| |||| |||| |||| |||| ++++-++++-- CCM Mode - * |||| |||| |||| |||| ++++-++++-- AES - * |||| |||| ++++-++++-- Length - * ++++-++++-- Flag - */ -#define ENCAP_BLOB_DESC3 0x00105566 -#define ENCAP_BLOB_DESC4 0x00000000 - -/* 5. SEQ In Ptr - * - * 1111 0000 0000 0000 0000 0000 0001 0000 - * |||| | |||| |||| |||| |||| - * |||| | ++++-++++-++++-++++-- Length in bytes (16) - * ++++-+-- Seq In Ptr - */ -#define ENCAP_BLOB_DESC5 0xF00003d0 -//#define ENCAP_BLOB_DESC5 0xF0000010 - -/* 6. Pointer for above SEQ In ptr command */ -/* Address could be changed during run time */ -#define ENCAP_BLOB_DESC6 SEC_MEM_PAGE1 - -/* 7. SEQ Out Ptr - * - * 1111 1000 0000 0000 0000 0000 0100 0000 - * |||| | |||| |||| |||| |||| - * |||| | ++++-++++-++++-++++-- Length in bytes (64) - * ++++-+-- Seq Out Ptr - */ -#define ENCAP_BLOB_DESC7 0xF8000400 -//#define ENCAP_BLOB_DESC7 0xF8000040 - -/* 8. Pointer for above SEQ Out ptr command */ -/* Address is provided during run time */ -#define ENCAP_BLOB_DESC8 0x00000000 - -/* 9. Protocol - * - * 1000 0111 0000 1101 0000 0000 0000 1000 - * |||| |||| |||| |||| |||| |||| |||| |||| - * |||| |||| |||| |||| ++++-++++-++++-++++-- Proto Info = sec mem blob - * |||| |||| ++++-++++-- Protocol ID = Blob - * |||| |+++-- Optype - encapsulation protocol - * ++++-+-- Seq In Ptr - */ -#define ENCAP_BLOB_DESC9 0x870D0008 - -/**************************************** - *----- Data encryption descriptor -----* - ****************************************/ -/* 1. Header - * - * 1011 0000 1000 0000 0000 0000 0000 1000 - * |||| | | |||| - * ++++-+-- Header +-++++-- 8 words in descriptor - */ -#define ENCRYPT_DESC1 0xB0800008 - -/* 2. Load AES-128 key from secure memory - * - * 0010 0010 0000 0000 0000 0000 0001 0000 - * |||| | | |||| |||| |||| |||| - * |||| | | ++++-++++-++++-++++-- 16 bytes - * |||| | +-- Load FIFO with data for Class 1 CHA - * ++++-+-- FIFO Load - */ -#define ENCRYPT_DESC2 0x02200010 - -/* 3. Pointer to key data in secure memory */ -/* Address is provided during run time */ -#define ENCRYPT_DESC3 0x00000000 -/* 4. Algorith Operation - Decrypt with ECB mode - * - * 1000 0010 0001 0000 0000 0010 0000 1101 - * |||| |||| |||| |||| |||| |||| |||| |||| - * |||| |||| |||| |||| |||| |||| |||| |||+-- Encrypt - * |||| |||| |||| |||| |||| |||| |||| ++-- Initialize/Finalize - * |||| |||| |||| |||| ---+-++++-++++-- ECB mode - * |||| |||| ++++-++++-- AES - * |||| |+++-- Optype: Class 1 algorithm - * ++++-+-- ALGORITHM OP. - */ -#define ENCRYPT_DESC4 0x8210020D - -/* 5. Load 16 bytes of message data - * - * 0010 0010 0001 0010 0000 0000 0001 0000 - * |||| |||| |||| |||| |||| |||| |||| |||| - * |||| |||| |||| |||| |||| |||| |||| |||| - * |||| |||| |||| |||| |||| |||| |||| |||| - * |||| |||| |||| |||| ++++-++++-++++-++++-- Msg Length = 16Bytes - * |||| |||| ||++-++++-- Input data type: Msg data LC1=1 - * |||| |||| |+-- EXT: No extended length - * |||| |||| +-- IMM: data begins at the location pointed to by the next word - * |||| |||++-SGT/VLF: FIFO Load-Pointer points to actual data - * |||| |++-- Load FIFO with data for Class 1 CHA - * ++++-+-- FIFO Load - */ -#define ENCRYPT_DESC5 0x22120010 - -/* 6. Pointer to plain text test vector message */ -/* Address is provided during run time */ -#define ENCRYPT_DESC6 0x00000000 - -/* 7. FIFO STORE - encrypted result. - * 0110 0000 0011 0000 0000 0000 0001 0000 - * |||| |||| |||| |||| |||| |||| |||| |||| - * |||| |||| |||| |||| ++++-++++-++++-++++-- Length = 16Bytes - * |||| |||| ||++-++++-- Output data type: Msg Data - * |||| |||| |+-- EXT: No extended length - * |||| |||| +-- CONT: No continue - * |||| |||+-- SGT/VLF: Pointer points to actual data - * |||| |++-- AUX: None - * ++++-+-- FIFO Store - */ -#define ENCRYPT_DESC7 0x60300010 - -/* 8. Pointer to ciphered text buffer */ -/* Address is provided during run time */ -#define ENCRYPT_DESC8 0x00000000 - -/********************************************************************* - *----- Descriptor to instantiate RNG in non-deterministic mode -----* - *********************************************************************/ -// Header -#define RNG_INST_DESC1 0xB0800009 -// Class 1 context load for personalization string, 8bytes -#define RNG_INST_DESC2 0x12A00008 -// 8 bytes of personalization string (8-byte UID + zeros) -#define RNG_INST_DESC3 0x01020304 -#define RNG_INST_DESC4 0x05060708 -// Instantiate State Handle 0 using entropy from TRNG -// without prediction resistance -#define RNG_INST_DESC5 0x82500404 -// Wait for Class 1 done -#define RNG_INST_DESC6 0xA2000001 -// Immediate 4 byte load to clear written register -#define RNG_INST_DESC7 0x10880004 -// Clear primary mode bit -#define RNG_INST_DESC8 0x00000001 -// Generate secure keys without prediction resistance -#define RNG_INST_DESC9 0x82501000 +/* + * Local defines + */ +/* arm v7 need 64 align */ +#define ALIGN_MASK ~(ARCH_DMA_MINALIGN - 1) +/* caam dma and pointer conversion for arm and arm64 architectures */ +#ifdef CONFIG_IMX_CONFIG + #define PTR2CAAMDMA(x) (u32)((uintptr_t)(x) & 0xffffffff) + #define CAAMDMA2PTR(x) (uintptr_t)((x) & 0xffffffff) +#else + #define PTR2CAAMDMA(x) (uintptr_t)(x) + #define CAAMDMA2PTR(x) (uintptr_t)(x) +#endif +#define RING_EARLY_INIT (0x01) +#define RING_RELOC_INIT (0x02) + +#define CAAM_HDR_CTYPE (0x16u << 27) +#define CAAM_HDR_ONE BIT(23) +#define CAAM_HDR_START_INDEX(x) (((x) & 0x3F) << 16) +#define CAAM_HDR_DESCLEN(x) ((x) & 0x3F) +#define CAAM_PROTOP_CTYPE (0x10u << 27) + +/* State Handle */ +#define BS_ALGO_RNG_SH (4) +#define BM_ALGO_RNG_SH (0x3 << BS_ALGO_RNG_SH) +#define ALGO_RNG_SH(id) (((id) << BS_ALGO_RNG_SH) & BM_ALGO_RNG_SH) + +/* Secure Key */ +#define BS_ALGO_RNG_SK (12) +#define BM_ALGO_RNG_SK BIT(BS_ALGO_RNG_SK) + +/* State */ +#define BS_ALGO_RNG_AS (2) +#define BM_ALGO_RNG_AS (0x3 << BS_ALGO_RNG_AS) +#define ALGO_RNG_GENERATE (0x0 << BS_ALGO_RNG_AS) +#define ALGO_RNG_INSTANTIATE BIT(BS_ALGO_RNG_AS) + +#define CAAM_C1_RNG ((0x50 << 16) | (2 << 24)) + +#define BS_JUMP_LOCAL_OFFSET (0) +#define BM_JUMP_LOCAL_OFFSET (0xFF << BS_JUMP_LOCAL_OFFSET) + +#define CAAM_C1_JUMP ((0x14u << 27) | (1 << 25)) +#define CAAM_JUMP_LOCAL (0 << 20) +#define CAAM_JUMP_TST_ALL_COND_TRUE (0 << 16) +#define CAAM_JUMP_OFFSET(off) (((off) << BS_JUMP_LOCAL_OFFSET) \ + & BM_JUMP_LOCAL_OFFSET) + +#define CAAM_C0_LOAD_IMM ((0x2 << 27) | (1 << 23)) +#define CAAM_DST_CLEAR_WRITTEN (0x8 << 16) + +#define RNG_DESC_SH0_SIZE (ARRAY_SIZE(rng_inst_sh0_desc)) +#define RNG_DESC_SH1_SIZE (ARRAY_SIZE(rng_inst_sh1_desc)) +#define RNG_DESC_KEYS_SIZE (ARRAY_SIZE(rng_inst_load_keys)) +#define RNG_DESC_MAX_SIZE (RNG_DESC_SH0_SIZE + \ + RNG_DESC_SH1_SIZE + \ + RNG_DESC_KEYS_SIZE) #endif /* __CAAM_INTERNAL_H__ */ |