mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-24 22:05:40 +00:00

NXP drivers header files are moved: - from: drivers/nxp/<xx>/*.h - to : include/drivers/nxp/<xx>/*.h To accommodate these changes each drivers makefiles drivers/nxp/<xx>/xx.mk, are updated. Signed-off-by: Pankaj Gupta <pankaj.gupta@nxp.com> Change-Id: I3979c509724d87e3d631a03dbafda1ee5ef07d21
506 lines
15 KiB
C
506 lines
15 KiB
C
/*
|
|
* 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 union {
|
|
uint64_t m_whole;
|
|
struct {
|
|
#ifdef NXP_SEC_BE
|
|
uint32_t high;
|
|
uint32_t low;
|
|
#else
|
|
uint32_t low;
|
|
uint32_t high;
|
|
#endif
|
|
} m_halves;
|
|
} 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_ */
|