sec_hw_specific.h 14.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
/*
 * Copyright 2017-2020 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(&regs->irja, num);
}

#endif /* _SEC_HW_SPECIFIC_H_ */