diff options
Diffstat (limited to 'include/drivers/nxp/crypto')
-rw-r--r-- | include/drivers/nxp/crypto/caam/caam.h | 53 | ||||
-rw-r--r-- | include/drivers/nxp/crypto/caam/caam_io.h | 56 | ||||
-rw-r--r-- | include/drivers/nxp/crypto/caam/hash.h | 85 | ||||
-rw-r--r-- | include/drivers/nxp/crypto/caam/jobdesc.h | 56 | ||||
-rw-r--r-- | include/drivers/nxp/crypto/caam/jr_driver_config.h | 205 | ||||
-rw-r--r-- | include/drivers/nxp/crypto/caam/rsa.h | 40 | ||||
-rw-r--r-- | include/drivers/nxp/crypto/caam/sec_hw_specific.h | 503 | ||||
-rw-r--r-- | include/drivers/nxp/crypto/caam/sec_jr_driver.h | 178 |
8 files changed, 1176 insertions, 0 deletions
diff --git a/include/drivers/nxp/crypto/caam/caam.h b/include/drivers/nxp/crypto/caam/caam.h new file mode 100644 index 0000000..6cc1f3d --- /dev/null +++ b/include/drivers/nxp/crypto/caam/caam.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef CAAM_H +#define CAAM_H + +#include "caam_io.h" +#include "sec_jr_driver.h" + + +/* Job ring 3 is reserved for usage by sec firmware */ +#define DEFAULT_JR 3 + +#if defined(CONFIG_CHASSIS_3_2) || defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_2) +#define CAAM_JR0_OFFSET 0x10000 +#define CAAM_JR1_OFFSET 0x20000 +#define CAAM_JR2_OFFSET 0x30000 +#define CAAM_JR3_OFFSET 0x40000 +#endif + +enum sig_alg { + RSA, + ECC +}; + +/* This function does basic SEC Initialization */ +int sec_init(uintptr_t nxp_caam_addr); +int config_sec_block(void); +uintptr_t get_caam_addr(void); + +/* This function is used to submit jobs to JR */ +int run_descriptor_jr(struct job_descriptor *desc); + +/* This function is used to instatiate the HW RNG is already not instantiated */ +int hw_rng_instantiate(void); + +/* This function is used to return random bytes of byte_len from HW RNG */ +int get_rand_bytes_hw(uint8_t *bytes, int byte_len); + +/* This function is used to set the hw unique key from HW CAAM */ +int get_hw_unq_key_blob_hw(uint8_t *hw_key, int size); + +/* This function is used to fetch random number from + * CAAM of length either of 4 bytes or 8 bytes depending + * rngWidth value. + */ +unsigned long long get_random(int rngWidth); + +#endif /* CAAM_H */ diff --git a/include/drivers/nxp/crypto/caam/caam_io.h b/include/drivers/nxp/crypto/caam/caam_io.h new file mode 100644 index 0000000..b68f836 --- /dev/null +++ b/include/drivers/nxp/crypto/caam/caam_io.h @@ -0,0 +1,56 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef CAAM_IO_H +#define CAAM_IO_H + +#include <endian.h> +#include <lib/mmio.h> + +typedef unsigned long long phys_addr_t; +typedef unsigned long long phys_size_t; + +/* Return higher 32 bits of physical address */ +#define PHYS_ADDR_HI(phys_addr) \ + (uint32_t)(((uint64_t)phys_addr) >> 32) + +/* Return lower 32 bits of physical address */ +#define PHYS_ADDR_LO(phys_addr) \ + (uint32_t)(((uint64_t)phys_addr) & 0xFFFFFFFF) + +#ifdef NXP_SEC_BE +#define sec_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define sec_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#define sec_in64(addr) ( \ + ((uint64_t)sec_in32((uintptr_t)(addr)) << 32) | \ + (sec_in32(((uintptr_t)(addr)) + 4))) +#define sec_out64(addr, val) ({ \ + sec_out32(((uintptr_t)(addr)), (uint32_t)((val) >> 32)); \ + sec_out32(((uintptr_t)(addr)) + 4, (uint32_t)(val)); }) +#elif defined(NXP_SEC_LE) +#define sec_in32(a) mmio_read_32((uintptr_t)(a)) +#define sec_out32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#define sec_in64(addr) ( \ + ((uint64_t)sec_in32((uintptr_t)(addr) + 4) << 32) | \ + (sec_in32((uintptr_t)(addr)))) +#define sec_out64(addr, val) ({ \ + sec_out32(((uintptr_t)(addr)) + 4, (uint32_t)((val) >> 32)); \ + sec_out32(((uintptr_t)(addr)), (uint32_t)(val)); }) +#else +#error Please define CCSR SEC register endianness +#endif + +static inline void *ptov(phys_addr_t *ptr) +{ + return (void *)ptr; +} + +static inline phys_addr_t *vtop(void *ptr) +{ + return (phys_addr_t *)ptr; +} +#endif /* CAAM_IO_H */ diff --git a/include/drivers/nxp/crypto/caam/hash.h b/include/drivers/nxp/crypto/caam/hash.h new file mode 100644 index 0000000..9136dca --- /dev/null +++ b/include/drivers/nxp/crypto/caam/hash.h @@ -0,0 +1,85 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __HASH_H__ +#define __HASH_H__ + +#include <stdbool.h> + +/* List of hash algorithms */ +enum hash_algo { + SHA1 = 0, + SHA256 +}; + +/* number of bytes in the SHA256-256 digest */ +#define SHA256_DIGEST_SIZE 32 + +/* + * number of words in the digest - Digest is kept internally + * as 8 32-bit words + */ +#define _SHA256_DIGEST_LENGTH 8 + +/* + * block length - A block, treated as a sequence of + * 32-bit words + */ +#define SHA256_BLOCK_LENGTH 16 + +/* number of bytes in the block */ +#define SHA256_DATA_SIZE 64 + +#define MAX_SG 12 + +struct sg_entry { +#if defined(NXP_SEC_LE) + uint32_t addr_lo; /* Memory Address - lo */ + uint32_t addr_hi; /* Memory Address of start of buffer - hi */ +#else + uint32_t addr_hi; /* Memory Address of start of buffer - hi */ + uint32_t addr_lo; /* Memory Address - lo */ +#endif + + uint32_t len_flag; /* Length of the data in the frame */ +#define SG_ENTRY_LENGTH_MASK 0x3FFFFFFF +#define SG_ENTRY_EXTENSION_BIT 0x80000000 +#define SG_ENTRY_FINAL_BIT 0x40000000 + uint32_t bpid_offset; +#define SG_ENTRY_BPID_MASK 0x00FF0000 +#define SG_ENTRY_BPID_SHIFT 16 +#define SG_ENTRY_OFFSET_MASK 0x00001FFF +#define SG_ENTRY_OFFSET_SHIFT 0 +}; + +/* + * SHA256-256 context + * contain the following fields + * State + * count low + * count high + * block data buffer + * index to the buffer + */ +struct hash_ctx { + struct sg_entry sg_tbl[MAX_SG]; + uint32_t hash_desc[64]; + uint8_t hash[SHA256_DIGEST_SIZE]; + uint32_t sg_num; + uint32_t len; + uint8_t *data; + enum hash_algo algo; + bool active; +}; + +int hash_init(enum hash_algo algo, void **ctx); +int hash_update(enum hash_algo algo, void *context, void *data_ptr, + unsigned int data_len); +int hash_final(enum hash_algo algo, void *context, void *hash_ptr, + unsigned int hash_len); + +#endif diff --git a/include/drivers/nxp/crypto/caam/jobdesc.h b/include/drivers/nxp/crypto/caam/jobdesc.h new file mode 100644 index 0000000..efef228 --- /dev/null +++ b/include/drivers/nxp/crypto/caam/jobdesc.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __JOBDESC_H +#define __JOBDESC_H + +#include <rsa.h> + +#define DESC_LEN_MASK 0x7f +#define DESC_START_SHIFT 16 + +#define KEY_BLOB_SIZE 32 +#define MAC_SIZE 16 + +#define KEY_IDNFR_SZ_BYTES 16 +#define CLASS_SHIFT 25 +#define CLASS_2 (0x02 << CLASS_SHIFT) + +#define CMD_SHIFT 27 +#define CMD_OPERATION (U(0x10) << CMD_SHIFT) + +#define OP_TYPE_SHIFT 24 +#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT) + +/* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */ +#define OP_PCLID_SHIFT 16 +#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT) + +#define BLOB_PROTO_INFO 0x00000002 + +uint32_t desc_length(uint32_t *desc); + +int cnstr_rng_jobdesc(uint32_t *desc, uint32_t state_handle, + uint32_t *add_inp, uint32_t add_ip_len, + uint8_t *out_data, uint32_t len); + +int cnstr_rng_instantiate_jobdesc(uint32_t *desc); + +/* Construct descriptor to generate hw key blob */ +int cnstr_hw_encap_blob_jobdesc(uint32_t *desc, + uint8_t *key_idnfr, uint32_t key_sz, + uint32_t key_class, uint8_t *plain_txt, + uint32_t in_sz, uint8_t *enc_blob, + uint32_t out_sz, uint32_t operation); + +void cnstr_hash_jobdesc(uint32_t *desc, uint8_t *msg, uint32_t msgsz, + uint8_t *digest); + +void cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, + struct pk_in_params *pkin, uint8_t *out, + uint32_t out_siz); +#endif diff --git a/include/drivers/nxp/crypto/caam/jr_driver_config.h b/include/drivers/nxp/crypto/caam/jr_driver_config.h new file mode 100644 index 0000000..1b3c447 --- /dev/null +++ b/include/drivers/nxp/crypto/caam/jr_driver_config.h @@ -0,0 +1,205 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _JR_DRIVER_CONFIG_H_ +#define _JR_DRIVER_CONFIG_H_ + +/* Helper defines */ + + /* Define used for setting a flag on */ +#define ON 1 + /* Define used for setting a flag off */ +#define OFF 0 + + /* SEC is configured to start work in polling mode, */ +#define SEC_STARTUP_POLLING_MODE 0 +/* + * SEC is configured to start work in interrupt mode, + * when configured for NAPI notification style. + */ +#define SEC_STARTUP_INTERRUPT_MODE 1 + +/* + * SEC driver will use ONLY interrupts to receive notifications + * for processed packets from SEC engine hardware. + */ +#define SEC_NOTIFICATION_TYPE_IRQ 1 +/* + * SEC driver will use ONLY polling to receive notifications + * for processed packets from SEC engine hardware. + */ +#define SEC_NOTIFICATION_TYPE_POLL 2 + +/* + * Determines how SEC user space driver will receive notifications + * for processed packets from SEC engine. + * Valid values are: #SEC_NOTIFICATION_TYPE_POLL, #SEC_NOTIFICATION_TYPE_IRQ + */ +#define SEC_NOTIFICATION_TYPE SEC_NOTIFICATION_TYPE_POLL + + /* Maximum number of job rings supported by SEC hardware */ +#define MAX_SEC_JOB_RINGS 1 + +/* + * Size of cryptographic context that is used directly in communicating + * with SEC device. + * SEC device works only with physical addresses. This is the maximum size + * for a SEC descriptor ( = 64 words). + */ + +#define SEC_CRYPTO_DESCRIPTOR_SIZE 256 + +/* + * Size of job descriptor submitted to SEC device for each packet to be + * processed. + * Job descriptor contains 3 DMA address pointers: + * - to shared descriptor, to input buffer and to output buffer. + * The job descriptor contains other SEC specific commands as well: + * - HEADER command, SEQ IN PTR command SEQ OUT PTR command and opaque + * data, each measuring 4 bytes. + * Job descriptor size, depending on physical address representation: + * - 32 bit - size is 28 bytes - cacheline-aligned size is 64 bytes + * - 36 bit - size is 40 bytes - cacheline-aligned size is 64 bytes + * @note: Job descriptor must be cacheline-aligned to ensure efficient memory + * access. + * @note: If other format is used for job descriptor, then the size must be + * revised. + */ + +#define SEC_JOB_DESCRIPTOR_SIZE 64 + +/* + * Size of one entry in the input ring of a job ring. + * Input ring contains pointers to job descriptors. + * The memory used for an input ring and output ring must be physically + * contiguous. + */ + +#define SEC_JOB_INPUT_RING_ENTRY_SIZE sizeof(phys_addr_t) + +/* + * Size of one entry in the output ring of a job ring. + * Output ring entry is a pointer to a job descriptor followed by a 4 byte + * status word. + * The memory used for an input ring and output ring must be physically + * contiguous. + * @note If desired to use also the optional SEQ OUT indication in output + * ring entries, then 4 more bytes must be added to the size. + */ + +#define SEC_JOB_OUTPUT_RING_ENTRY_SIZE (SEC_JOB_INPUT_RING_ENTRY_SIZE + 4) + + /* DMA memory required for an input ring of a job ring. */ +#define SEC_DMA_MEM_INPUT_RING_SIZE \ + ((SEC_JOB_INPUT_RING_ENTRY_SIZE) * (SEC_JOB_RING_SIZE)) + +/* + * DMA memory required for an output ring of a job ring. + * Required extra 4 byte for status word per each entry. + */ +#define SEC_DMA_MEM_OUTPUT_RING_SIZE \ + ((SEC_JOB_OUTPUT_RING_ENTRY_SIZE) * (SEC_JOB_RING_SIZE)) + + /* DMA memory required for descriptors of a job ring. */ +#define SEC_DMA_MEM_DESCRIPTORS \ + ((SEC_CRYPTO_DESCRIPTOR_SIZE)*(SEC_JOB_RING_SIZE)) + + /* DMA memory required for a job ring, including both input output rings. */ +#define SEC_DMA_MEM_JOB_RING_SIZE \ + ((SEC_DMA_MEM_INPUT_RING_SIZE) + \ + (SEC_DMA_MEM_OUTPUT_RING_SIZE)) + +/* + * When calling sec_init() UA will provide an area of virtual memory + * of size #SEC_DMA_MEMORY_SIZE to be used internally by the driver + * to allocate data (like SEC descriptors) that needs to be passed to + * SEC device in physical addressing and later on retrieved from SEC device. + * At initialization the UA provides specialized ptov/vtop functions/macros to + * translate addresses allocated from this memory area. + */ +#define SEC_DMA_MEMORY_SIZE \ + ((SEC_DMA_MEM_JOB_RING_SIZE) * (MAX_SEC_JOB_RINGS)) + +/* + * SEC DEVICE related configuration. + + * Enable/Disable logging support at compile time. + * Valid values: + * ON - enable logging + * OFF - disable logging + * The messages are logged at stdout. + */ + +#define SEC_DRIVER_LOGGING OFF + +/* + * Configure logging level at compile time. + * Valid values: + * SEC_DRIVER_LOG_ERROR - log only errors + * SEC_DRIVER_LOG_INFO - log errors and info messages + * SEC_DRIVER_LOG_DEBUG - log errors, info and debug messages + */ + +#define SEC_DRIVER_LOGGING_LEVEL SEC_DRIVER_LOG_DEBUG + +/* + * SEC JOB RING related configuration. + + * Configure the size of the JOB RING. + * The maximum size of the ring is hardware limited to 1024. + * However the number of packets in flight in a time interval of + * 1ms can be calculated + * from the traffic rate (Mbps) and packet size. + * Here it was considered a packet size of 40 bytes. + * @note Round up to nearest power of 2 for optimized update + * of producer/consumer indexes of each job ring + * \todo Should set to 750, according to the calculation above, but + * the JR size must be power of 2, thus the next closest value must + * be chosen (i.e. 512 since 1024 is not available) + * For firmware choose this to be 16 + */ + +#define SEC_JOB_RING_SIZE 16 + +/* + * Interrupt coalescing related configuration. + * NOTE: SEC hardware enabled interrupt + * coalescing is not supported on SEC version 3.1! + * SEC version 4.4 has support for interrupt + * coalescing. + */ + +#if SEC_NOTIFICATION_TYPE != SEC_NOTIFICATION_TYPE_POLL + +#define SEC_INT_COALESCING_ENABLE ON +/* + * Interrupt Coalescing Descriptor Count Threshold. + * While interrupt coalescing is enabled (ICEN=1), this value determines + * how many Descriptors are completed before raising an interrupt. + * Valid values for this field are from 0 to 255. + * Note that a value of 1 functionally defeats the advantages of interrupt + * coalescing since the threshold value is reached each time that a + * Job Descriptor is completed. A value of 0 is treated in the same + * manner as a value of 1. + * + */ +#define SEC_INTERRUPT_COALESCING_DESCRIPTOR_COUNT_THRESH 10 + +/* + * Interrupt Coalescing Timer Threshold. + * While interrupt coalescing is enabled (ICEN=1), this value determines the + * maximum amount of time after processing a Descriptor before raising an + * interrupt. + * The threshold value is represented in units equal to 64 CAAM interface + * clocks. Valid values for this field are from 1 to 65535. + * A value of 0 results in behavior identical to that when interrupt + * coalescing is disabled. + */ +#define SEC_INTERRUPT_COALESCING_TIMER_THRESH 100 +#endif /* SEC_NOTIFICATION_TYPE_POLL */ + +#endif /* _JR_DRIVER_CONFIG_H_ */ diff --git a/include/drivers/nxp/crypto/caam/rsa.h b/include/drivers/nxp/crypto/caam/rsa.h new file mode 100644 index 0000000..dd9ecdc --- /dev/null +++ b/include/drivers/nxp/crypto/caam/rsa.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _RSA_H__ +#define _RSA_H__ + +/* RSA key size defines */ +#define RSA_4K_KEY_SZ 4096 +#define RSA_4K_KEY_SZ_BYTES (RSA_4K_KEY_SZ/8) +#define RSA_2K_KEY_SZ 2048 +#define RSA_2K_KEY_SZ_BYTES (RSA_2K_KEY_SZ/8) +#define RSA_1K_KEY_SZ 1024 +#define RSA_1K_KEY_SZ_BYTES (RSA_1K_KEY_SZ/8) + +#define SHA256_BYTES (256/8) + +struct pk_in_params { + uint8_t *e; + uint32_t e_siz; + uint8_t *n; + uint32_t n_siz; + uint8_t *a; + uint32_t a_siz; + uint8_t *b; + uint32_t b_siz; +}; + +struct rsa_context { + struct pk_in_params pkin; +}; + +int rsa_verify_signature(void *hash_ptr, unsigned int hash_len, + void *sig_ptr, unsigned int sig_len, + void *pk_ptr, unsigned int pk_len); + +#endif diff --git a/include/drivers/nxp/crypto/caam/sec_hw_specific.h b/include/drivers/nxp/crypto/caam/sec_hw_specific.h new file mode 100644 index 0000000..9800793 --- /dev/null +++ b/include/drivers/nxp/crypto/caam/sec_hw_specific.h @@ -0,0 +1,503 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _SEC_HW_SPECIFIC_H_ +#define _SEC_HW_SPECIFIC_H_ + +#include "caam.h" +#include "sec_jr_driver.h" + + /* DEFINES AND MACROS */ + +/* Used to retry resetting a job ring in SEC hardware. */ +#define SEC_TIMEOUT 100000 + +/* + * Offset to the registers of a job ring. + *Is different for each job ring. + */ +#define CHAN_BASE(jr) ((phys_addr_t)(jr)->register_base_addr) + +#define unlikely(x) __builtin_expect(!!(x), 0) + +#define SEC_JOB_RING_IS_FULL(pi, ci, ring_max_size, ring_threshold) \ + ((((pi) + 1 + ((ring_max_size) - (ring_threshold))) & \ + (ring_max_size - 1)) == ((ci))) + +#define SEC_CIRCULAR_COUNTER(x, max) (((x) + 1) & (max - 1)) + + /* Struct representing various job ring registers */ +struct jobring_regs { +#ifdef NXP_SEC_BE + unsigned int irba_h; + unsigned int irba_l; +#else + unsigned int irba_l; + unsigned int irba_h; +#endif + unsigned int rsvd1; + unsigned int irs; + unsigned int rsvd2; + unsigned int irsa; + unsigned int rsvd3; + unsigned int irja; +#ifdef NXP_SEC_BE + unsigned int orba_h; + unsigned int orba_l; +#else + unsigned int orba_l; + unsigned int orba_h; +#endif + unsigned int rsvd4; + unsigned int ors; + unsigned int rsvd5; + unsigned int orjr; + unsigned int rsvd6; + unsigned int orsf; + unsigned int rsvd7; + unsigned int jrsta; + unsigned int rsvd8; + unsigned int jrint; + unsigned int jrcfg0; + unsigned int jrcfg1; + unsigned int rsvd9; + unsigned int irri; + unsigned int rsvd10; + unsigned int orwi; + unsigned int rsvd11; + unsigned int jrcr; +}; + + /* Offsets representing common SEC Registers */ +#define SEC_REG_MCFGR_OFFSET 0x0004 +#define SEC_REG_SCFGR_OFFSET 0x000C +#define SEC_REG_JR0ICIDR_MS_OFFSET 0x0010 +#define SEC_REG_JR0ICIDR_LS_OFFSET 0x0014 +#define SEC_REG_JR1ICIDR_MS_OFFSET 0x0018 +#define SEC_REG_JR1ICIDR_LS_OFFSET 0x001C +#define SEC_REG_JR2ICIDR_MS_OFFSET 0x0020 +#define SEC_REG_JR2ICIDR_LS_OFFSET 0x0024 +#define SEC_REG_JR3ICIDR_MS_OFFSET 0x0028 +#define SEC_REG_JR3ICIDR_LS_OFFSET 0x002C +#define SEC_REG_JRSTARTR_OFFSET 0x005C +#define SEC_REG_CTPR_MS_OFFSET 0x0FA8 + + /* Offsets representing various RNG registers */ +#define RNG_REG_RTMCTL_OFFSET 0x0600 +#define RNG_REG_RTSDCTL_OFFSET 0x0610 +#define RNG_REG_RTFRQMIN_OFFSET 0x0618 +#define RNG_REG_RTFRQMAX_OFFSET 0x061C +#define RNG_REG_RDSTA_OFFSET 0x06C0 +#define ALG_AAI_SH_SHIFT 4 + + /* SEC Registers Bitmasks */ +#define MCFGR_PS_SHIFT 16 +#define MCFGR_AWCACHE_SHIFT 8 +#define MCFGR_AWCACHE_MASK (0xF << MCFGR_AWCACHE_SHIFT) +#define MCFGR_ARCACHE_SHIFT 12 +#define MCFGR_ARCACHE_MASK (0xF << MCFGR_ARCACHE_SHIFT) + +#define SCFGR_RNGSH0 0x00000200 +#define SCFGR_VIRT_EN 0x00008000 + +#define JRICID_MS_LICID 0x80000000 +#define JRICID_MS_LAMTD 0x00020000 +#define JRICID_MS_AMTDT 0x00010000 +#define JRICID_MS_TZ 0x00008000 +#define JRICID_LS_SDID_MASK 0x00000FFF +#define JRICID_LS_NSEQID_MASK 0x0FFF0000 +#define JRICID_LS_NSEQID_SHIFT 16 +#define JRICID_LS_SEQID_MASK 0x00000FFF + +#define JRSTARTR_STARTJR0 0x00000001 +#define JRSTARTR_STARTJR1 0x00000002 +#define JRSTARTR_STARTJR2 0x00000004 +#define JRSTARTR_STARTJR3 0x00000008 + +#define CTPR_VIRT_EN_POR 0x00000002 +#define CTPR_VIRT_EN_INC 0x00000001 + + /* RNG RDSTA bitmask */ +#define RNG_STATE0_HANDLE_INSTANTIATED 0x00000001 +#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */ + /* use von Neumann data in both entropy shifter and statistical checker */ +#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_SC 0 + /* use raw data in both entropy shifter and statistical checker */ +#define RTMCTL_SAMP_MODE_RAW_ES_SC 1 + /* use von Neumann data in entropy shifter, raw data in statistical checker */ +#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_RAW_SC 2 + /* invalid combination */ +#define RTMCTL_SAMP_MODE_INVALID 3 +#define RTSDCTL_ENT_DLY_MIN 3200 +#define RTSDCTL_ENT_DLY_MAX 12800 +#define RTSDCTL_ENT_DLY_SHIFT 16 +#define RTSDCTL_ENT_DLY_MASK (U(0xffff) << RTSDCTL_ENT_DLY_SHIFT) +#define RTFRQMAX_DISABLE (1 << 20) + + /* Constants for error handling on job ring */ +#define JR_REG_JRINT_ERR_TYPE_SHIFT 8 +#define JR_REG_JRINT_ERR_ORWI_SHIFT 16 +#define JR_REG_JRINIT_JRE_SHIFT 1 + +#define JRINT_JRE (1 << JR_REG_JRINIT_JRE_SHIFT) +#define JRINT_ERR_WRITE_STATUS (1 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_BAD_INPUT_BASE (3 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_BAD_OUTPUT_BASE (4 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_WRITE_2_IRBA (5 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_WRITE_2_ORBA (6 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_RES_B4_HALT (7 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_REM_TOO_MANY (8 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_ADD_TOO_MANY (9 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_HALT_MASK 0x0C +#define JRINT_ERR_HALT_INPROGRESS 0x04 +#define JRINT_ERR_HALT_COMPLETE 0x08 + +#define JR_REG_JRCR_VAL_RESET 0x00000001 + +#define JR_REG_JRCFG_LO_ICTT_SHIFT 0x10 +#define JR_REG_JRCFG_LO_ICDCT_SHIFT 0x08 +#define JR_REG_JRCFG_LO_ICEN_EN 0x02 +#define JR_REG_JRCFG_LO_IMSK_EN 0x01 + + /* Constants for Descriptor Processing errors */ +#define SEC_HW_ERR_SSRC_NO_SRC 0x00 +#define SEC_HW_ERR_SSRC_CCB_ERR 0x02 +#define SEC_HW_ERR_SSRC_JMP_HALT_U 0x03 +#define SEC_HW_ERR_SSRC_DECO 0x04 +#define SEC_HW_ERR_SSRC_JR 0x06 +#define SEC_HW_ERR_SSRC_JMP_HALT_COND 0x07 + +#define SEC_HW_ERR_DECO_HFN_THRESHOLD 0xF1 +#define SEC_HW_ERR_CCB_ICV_CHECK_FAIL 0x0A + + /* Macros for extracting error codes for the job ring */ + +#define JR_REG_JRINT_ERR_TYPE_EXTRACT(value) \ + ((value) & 0x00000F00) + +#define JR_REG_JRINT_ERR_ORWI_EXTRACT(value) \ + (((value) & 0x3FFF0000) >> \ + JR_REG_JRINT_ERR_ORWI_SHIFT) + +#define JR_REG_JRINT_JRE_EXTRACT(value) \ + ((value) & JRINT_JRE) + + /* Macros for manipulating JR registers */ +typedef struct { +#ifdef NXP_SEC_BE + uint32_t high; + uint32_t low; +#else + uint32_t low; + uint32_t high; +#endif +} ptr_addr_t; + +#if defined(CONFIG_PHYS_64BIT) +#define sec_read_addr(a) sec_in64((a)) +#define sec_write_addr(a, v) sec_out64((a), (v)) +#else +#define sec_read_addr(a) sec_in32((a)) +#define sec_write_addr(a, v) sec_out32((a), (v)) +#endif + +#define JR_REG(name, jr) (CHAN_BASE(jr) + JR_REG_##name##_OFFSET) +#define JR_REG_LO(name, jr) (CHAN_BASE(jr) + JR_REG_##name##_OFFSET_LO) + +#define GET_JR_REG(name, jr) (sec_in32(JR_REG(name, (jr)))) +#define GET_JR_REG_LO(name, jr) (sec_in32(JR_REG_LO(name, (jr)))) + +#define SET_JR_REG(name, jr, val) \ + (sec_out32(JR_REG(name, (jr)), (val))) + +#define SET_JR_REG_LO(name, jr, val) \ + (sec_out32(JR_REG_LO(name, (jr)), (val))) + + /* STRUCTURES AND OTHER TYPEDEFS */ + /* Lists the possible states for a job ring. */ +typedef enum sec_job_ring_state_e { + SEC_JOB_RING_STATE_STARTED, /* Job ring is initialized */ + SEC_JOB_RING_STATE_RESET, /* Job ring reset is in progres */ +} sec_job_ring_state_t; + +struct sec_job_ring_t { + /* + * Consumer index for job ring (jobs array). + * @note: cidx and pidx are accessed from + * different threads. + * Place the cidx and pidx inside the structure + * so that they lay on different cachelines, to + * avoid false sharing between threads when the + * threads run on different cores! + */ + uint32_t cidx; + + /* Producer index for job ring (jobs array) */ + uint32_t pidx; + + /* Ring of input descriptors. Size of array is power of 2 to allow + * fast update of producer/consumer indexes with bitwise operations. + */ + phys_addr_t *input_ring; + + /* Ring of output descriptors. */ + struct sec_outring_entry *output_ring; + + /* The file descriptor used for polling for interrupts notifications */ + uint32_t irq_fd; + + /* Model used by SEC Driver to receive notifications from SEC. + * Can be either of the three: + * #SEC_NOTIFICATION_TYPE_IRQ or + * #SEC_NOTIFICATION_TYPE_POLL + */ + uint32_t jr_mode; + /* Base address for SEC's register memory for this job ring. */ + void *register_base_addr; + /* notifies if coelescing is enabled for the job ring */ + uint8_t coalescing_en; + /* The state of this job ring */ + sec_job_ring_state_t jr_state; +}; + + /* Forward structure declaration */ +typedef struct sec_job_ring_t sec_job_ring_t; + +struct sec_outring_entry { + phys_addr_t desc; /* Pointer to completed descriptor */ + uint32_t status; /* Status for completed descriptor */ +} __packed; + + /* Lists the states possible for the SEC user space driver. */ +typedef enum sec_driver_state_e { + SEC_DRIVER_STATE_IDLE, /*< Driver not initialized */ + SEC_DRIVER_STATE_STARTED, /*< Driver initialized and */ + SEC_DRIVER_STATE_RELEASE, /*< Driver release is in progress */ +} sec_driver_state_t; + + /* Union describing the possible error codes that */ + /* can be set in the descriptor status word */ + +union hw_error_code { + uint32_t error; + union { + struct { + uint32_t ssrc:4; + uint32_t ssed_val:28; + } __packed value; + struct { + uint32_t ssrc:4; + uint32_t res:28; + } __packed no_status_src; + struct { + uint32_t ssrc:4; + uint32_t jmp:1; + uint32_t res:11; + uint32_t desc_idx:8; + uint32_t cha_id:4; + uint32_t err_id:4; + } __packed ccb_status_src; + struct { + uint32_t ssrc:4; + uint32_t jmp:1; + uint32_t res:11; + uint32_t desc_idx:8; + uint32_t offset:8; + } __packed jmp_halt_user_src; + struct { + uint32_t ssrc:4; + uint32_t jmp:1; + uint32_t res:11; + uint32_t desc_idx:8; + uint32_t desc_err:8; + } __packed deco_src; + struct { + uint32_t ssrc:4; + uint32_t res:17; + uint32_t naddr:3; + uint32_t desc_err:8; + } __packed jr_src; + struct { + uint32_t ssrc:4; + uint32_t jmp:1; + uint32_t res:11; + uint32_t desc_idx:8; + uint32_t cond:8; + } __packed jmp_halt_cond_src; + } __packed error_desc; +} __packed; + + /* FUNCTION PROTOTYPES */ + +/* + * @brief Initialize a job ring/channel in SEC device. + * Write configuration register/s to properly initialize a job ring. + * + * @param [in] job_ring The job ring + * + * @retval 0 for success + * @retval other for error + */ +int hw_reset_job_ring(sec_job_ring_t *job_ring); + +/* + * @brief Reset a job ring/channel in SEC device. + * Write configuration register/s to reset a job ring. + * + * @param [in] job_ring The job ring + * + * @retval 0 for success + * @retval -1 in case job ring reset failed + */ +int hw_shutdown_job_ring(sec_job_ring_t *job_ring); + +/* + * @brief Handle a job ring/channel error in SEC device. + * Identify the error type and clear error bits if required. + * + * @param [in] job_ring The job ring + * @param [in] sec_error_code error code as first read from SEC engine + */ + +void hw_handle_job_ring_error(sec_job_ring_t *job_ring, + uint32_t sec_error_code); +/* + * @brief Handle a job ring error in the device. + * Identify the error type and printout a explanatory + * messages. + * + * @param [in] job_ring The job ring + * + */ + +int hw_job_ring_error(sec_job_ring_t *job_ring); + +/* @brief Set interrupt coalescing parameters on the Job Ring. + * @param [in] job_ring The job ring + * @param [in] irq_coalesing_timer + * Interrupt coalescing timer threshold. + * This value determines the maximum + * amount of time after processing a descriptor + * before raising an interrupt. + * @param [in] irq_coalescing_count + * Interrupt coalescing count threshold. + * This value determines how many descriptors + * are completed before raising an interrupt. + */ + +int hw_job_ring_set_coalescing_param(sec_job_ring_t *job_ring, + uint16_t irq_coalescing_timer, + uint8_t irq_coalescing_count); + +/* @brief Enable interrupt coalescing on a job ring + * @param [in] job_ring The job ring + */ + +int hw_job_ring_enable_coalescing(sec_job_ring_t *job_ring); + +/* + * @brief Disable interrupt coalescing on a job ring + * @param [in] job_ring The job ring + */ + +int hw_job_ring_disable_coalescing(sec_job_ring_t *job_ring); + +/* + * @brief Poll the HW for already processed jobs in the JR + * and notify the available jobs to UA. + * + * @param [in] job_ring The job ring to poll. + * @param [in] limit The maximum number of jobs to notify. + * If set to negative value, all available + * jobs are notified. + * + * @retval >=0 for No of jobs notified to UA. + * @retval -1 for error + */ + +int hw_poll_job_ring(struct sec_job_ring_t *job_ring, int32_t limit); + +/* @brief Poll the HW for already processed jobs in the JR + * and silently discard the available jobs or notify them to UA + * with indicated error code. + + * @param [in,out] job_ring The job ring to poll. + * @param [in] do_notify Can be #TRUE or #FALSE. + * Indicates if descriptors to be discarded + * or notified to UA with given error_code. + * @param [in] error_code The detailed SEC error code. + * @param [out] notified_descs Number of notified descriptors. + * Can be NULL if do_notify is #FALSE + */ +void hw_flush_job_ring(struct sec_job_ring_t *job_ring, + uint32_t do_notify, + uint32_t error_code, uint32_t *notified_descs); + +/* + * @brief Flush job rings of any processed descs. + * The processed descs are silently dropped, + * WITHOUT being notified to UA. + */ +void flush_job_rings(void); + +/* + * @brief Handle desc that generated error in SEC engine. + * Identify the exact type of error and handle the error. + * Depending on the error type, the job ring could be reset. + * All descs that are submitted for processing on this job ring + * are notified to User Application with error status and detailed error code. + + * @param [in] job_ring Job ring + * @param [in] sec_error_code Error code read from job ring's Channel + * Status Register + * @param [out] notified_descs Number of notified descs. Can be NULL if + * do_notify is #FALSE + * @param [out] do_driver_shutdown If set to #TRUE, then UA is returned code + * #SEC_PROCESSING_ERROR + * which is indication that UA must call + * sec_release() after this. + */ +void sec_handle_desc_error(struct sec_job_ring_t *job_ring, + uint32_t sec_error_code, + uint32_t *notified_descs, + uint32_t *do_driver_shutdown); + +/* + * @brief Release the software and hardware resources tied to a job ring. + * @param [in] job_ring The job ring + * @retval 0 for success + * @retval -1 for error + */ +int shutdown_job_ring(struct sec_job_ring_t *job_ring); + +/* + * @brief Enable irqs on associated job ring. + * @param [in] job_ring The job ring + * @retval 0 for success + * @retval -1 for error + */ +int jr_enable_irqs(struct sec_job_ring_t *job_ring); + +/* + * @brief Disable irqs on associated job ring. + * @param [in] job_ring The job ring + * @retval 0 for success + * @retval -1 for error + */ +int jr_disable_irqs(struct sec_job_ring_t *job_ring); + + /* + * IRJA - Input Ring Jobs Added Register shows + * how many new jobs were added to the Input Ring. + */ +static inline void hw_enqueue_desc_on_job_ring(struct jobring_regs *regs, + int num) +{ + sec_out32(®s->irja, num); +} + +#endif /* _SEC_HW_SPECIFIC_H_ */ diff --git a/include/drivers/nxp/crypto/caam/sec_jr_driver.h b/include/drivers/nxp/crypto/caam/sec_jr_driver.h new file mode 100644 index 0000000..57e0fa0 --- /dev/null +++ b/include/drivers/nxp/crypto/caam/sec_jr_driver.h @@ -0,0 +1,178 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _JR_DRIVER_H_ +#define _JR_DRIVER_H_ + +#include "jr_driver_config.h" + +/* The maximum size of a SEC descriptor, in WORDs (32 bits). */ +#define MAX_DESC_SIZE_WORDS 64 + +#define CAAM_TIMEOUT 200000 /* ms */ + +/* Return codes for JR user space driver APIs */ +typedef enum sec_return_code_e { + SEC_SUCCESS = 0, + SEC_INVALID_INPUT_PARAM, + SEC_OUT_OF_MEMORY, + SEC_DESCRIPTOR_IN_FLIGHT, + SEC_LAST_DESCRIPTOR_IN_FLIGHT, + SEC_PROCESSING_ERROR, + SEC_DESC_PROCESSING_ERROR, + SEC_JR_IS_FULL, + SEC_DRIVER_RELEASE_IN_PROGRESS, + SEC_DRIVER_ALREADY_INITIALIZED, + SEC_DRIVER_NOT_INITIALIZED, + SEC_JOB_RING_RESET_IN_PROGRESS, + SEC_RESET_ENGINE_FAILED, + SEC_ENABLE_IRQS_FAILED, + SEC_DISABLE_IRQS_FAILED, + SEC_RETURN_CODE_MAX_VALUE, +} sec_return_code_t; + +/* STRUCTURES AND OTHER TYPEDEFS */ + +/* + * @brief Function called by JR User Space driver to notify every processed + * descriptor. + * + * Callback provided by the User Application. + * Callback is invoked by JR User Space driver for each descriptor processed by + * SEC + * @param [in] status Status word indicating processing result for + * this descriptor. + * @param [in] arg Opaque data passed by User Application + * It is opaque from JR driver's point of view. + * @param [in] job_ring The job ring handle on which the processed + * descriptor word was enqueued + */ +typedef void (*user_callback) (uint32_t *desc, uint32_t status, + void *arg, void *job_ring); + +/* + * Structure encompassing a job descriptor which is to be processed + * by SEC. User should also initialise this structure with the callback + * function pointer which will be called by driver after recieving proccessed + * descriptor from SEC. User data is also passed in this data structure which + * will be sent as an argument to the user callback function. + */ +struct job_descriptor { + uint32_t desc[MAX_DESC_SIZE_WORDS]; + void *arg; + user_callback callback; +}; + +/* + * @brief Initialize the JR User Space driver. + * This function will handle initialization of sec library + * along with registering platform specific callbacks, + * as well as local data initialization. + * Call once during application startup. + * @note Global SEC initialization is done in SEC kernel driver. + * @note The hardware IDs of the initialized Job Rings are opaque to the UA. + * The exact Job Rings used by this library are decided between SEC user + * space driver and SEC kernel driver. A static partitioning of Job Rings is + * assumed, configured in DTS(device tree specification) file. + * @param [in] platform_cb Registering the platform specific + * callbacks with driver + * @retval ::0 for successful execution + * @retval ::-1 failure + */ +int sec_jr_lib_init(void); + +/* + * @brief Initialize the software and hardware resources tied to a job ring. + * @param [in] jr_mode; Model to be used by SEC Driver to receive + * notifications from SEC. Can be either + * SEC_NOTIFICATION_TYPE_IRQ or + * SEC_NOTIFICATION_TYPE_POLL + * @param [in] irq_coalescing_timer This value determines the maximum + * amount of time after processing a + * descriptor before raising an interrupt. + * @param [in] irq_coalescing_count This value determines how many + * descriptors are completed before + * raising an interrupt. + * @param [in] reg_base_addr The job ring base address register + * @param [in] irq_id The job ring interrupt identification number. + * @retval job_ring_handle for successful job ring configuration + * @retval NULL on error + */ +void *init_job_ring(uint8_t jr_mode, + uint16_t irq_coalescing_timer, + uint8_t irq_coalescing_count, + void *reg_base_addr, uint32_t irq_id); + +/* + * @brief Release the resources used by the JR User Space driver. + * Reset and release SEC's job rings indicated by the User Application at + * init_job_ring() and free any memory allocated internally. + * Call once during application tear down. + * @note In case there are any descriptors in-flight (descriptors received by + * JR driver for processing and for which no response was yet provided to UA), + * the descriptors are discarded without any notifications to User Application. + * @retval ::0 is returned for a successful execution + * @retval ::-1 is returned if JR driver release is in progress + */ +int sec_release(void); + +/* + * @brief Submit a descriptor for SEC processing. + * This function creates a "job" which is meant to instruct SEC HW + * to perform the processing on the input buffer. The "job" is enqueued + * in the Job Ring associated. The function will return after the "job" + * enqueue is finished. The function will not wait for SEC to + * start or/and finish the "job" processing. + * After the processing is finished the SEC HW writes the processing result + * to the provided output buffer. + * The Caller must poll JR driver using jr_dequeue() + * to receive notifications of the processing completion + * status. The notifications are received by caller by means of callback + * (see ::user_callback). + * @param [in] job_ring_handle The handle of the job ring on which + * descriptor is to be enqueued + * @param [in] job_descriptor The job descriptor structure of type + * struct job_descriptor. This structure + * should be filled with job descriptor along + * with callback function to be called after + * processing of descriptor and some + * opaque data passed to be passed to the + * callback function + * + * @retval ::0 is returned for successful execution + * @retval ::-1 is returned if there is some enqueue failure + */ +int enq_jr_desc(void *job_ring_handle, struct job_descriptor *jobdescr); + +/* + * @brief Polls for available descriptors processed by SEC on a specific + * Job Ring + * This function polls the SEC Job Rings and delivers processed descriptors + * Each processed descriptor has a user_callback registered. + * This user_callback is invoked for each processed descriptor. + * The polling is stopped when "limit" descriptors are notified or when + * there are no more descriptors to notify. + * @note The dequeue_jr() API cannot be called from within a user_callback + * function + * @param [in] job_ring_handle The Job Ring handle. + * @param [in] limit This value represents the maximum number + * of processed descriptors that can be + * notified API call on this Job Ring. + * Note that fewer descriptors may be notified + * if enough processed descriptors are not + * available. + * If limit has a negative value, then all + * ready descriptors will be notified. + * + * @retval :: >=0 is returned where retval is the total + * Number of descriptors notified + * during this function call. + * @retval :: -1 is returned in case of some error + */ +int dequeue_jr(void *job_ring_handle, int32_t limit); + +#endif /* _JR_DRIVER_H_ */ |