diff options
Diffstat (limited to '')
-rw-r--r-- | include/drivers/nxp/crypto/caam/sec_hw_specific.h | 503 |
1 files changed, 503 insertions, 0 deletions
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_ */ |