[U-Boot] [PATCH 3/3] crypto/fsl: SEC driver cleanup for 64 bit and endianness

Aneesh Bansal aneesh.bansal at freescale.com
Fri Jul 31 11:55:45 CEST 2015


The SEC driver code has been cleaned up to work for 64 bit
physical addresses and systems where endianess of SEC block
is different from the Core.
Changes:
1. Descriptor created on Core is modified as per SEC block
   endianness before the job is submitted.
2. The read/write to Job Rings are done using I/O functions
   defined for SEC which will take care of the endianness.
3. The 32 bit low and high part of the 64 bit address in
   descriptor will vary depending on endianness of SEC.

Signed-off-by: Aneesh Bansal <aneesh.bansal at freescale.com>
---
 drivers/crypto/fsl/desc_constr.h | 24 ++++++++++++++++++++++++
 drivers/crypto/fsl/fsl_hash.c    |  7 +------
 drivers/crypto/fsl/jr.c          | 40 ++++++++++++++++++++++++++--------------
 drivers/crypto/fsl/jr.h          | 19 +++++++++----------
 include/fsl_sec.h                | 24 ++++++++++++++----------
 5 files changed, 74 insertions(+), 40 deletions(-)

diff --git a/drivers/crypto/fsl/desc_constr.h b/drivers/crypto/fsl/desc_constr.h
index f9cae91..ac4a933 100644
--- a/drivers/crypto/fsl/desc_constr.h
+++ b/drivers/crypto/fsl/desc_constr.h
@@ -36,6 +36,21 @@
 			       LDST_SRCDST_WORD_DECOCTRL | \
 			       (LDOFF_ENABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
 
+#ifdef CONFIG_PHYS_64BIT
+union ptr_addr_t {
+	u64 m_whole;
+	struct {
+#ifdef CONFIG_SYS_FSL_SEC_LE
+		u32 low;
+		u32 high;
+#else
+		u32 high;
+		u32 low;
+#endif
+	} m_halfs;
+};
+#endif
+
 static inline int desc_len(u32 *desc)
 {
 	return *desc & HDR_DESCLEN_MASK;
@@ -65,7 +80,16 @@ static inline void append_ptr(u32 *desc, dma_addr_t ptr)
 {
 	dma_addr_t *offset = (dma_addr_t *)desc_end(desc);
 
+#ifdef CONFIG_PHYS_64BIT
+	/* The Position of low and high part of 64 bit address
+	 * will depend on the endianness of CAAM Block */
+	union ptr_addr_t ptr_addr;
+	ptr_addr.m_halfs.high = (u32)(ptr >> 32);
+	ptr_addr.m_halfs.low = (u32)ptr;
+	*offset = ptr_addr.m_whole;
+#else
 	*offset = ptr;
+#endif
 
 	(*desc) += CAAM_PTR_SZ / CAAM_CMD_SZ;
 }
diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c
index c298404..9b243f6 100644
--- a/drivers/crypto/fsl/fsl_hash.c
+++ b/drivers/crypto/fsl/fsl_hash.c
@@ -92,12 +92,7 @@ static int caam_hash_update(void *hash_ctx, const void *buf,
 		return -EINVAL;
 	}
 
-#ifdef CONFIG_PHYS_64BIT
-	ctx->sg_tbl[ctx->sg_num].addr_hi = addr >> 32;
-#else
-	ctx->sg_tbl[ctx->sg_num].addr_hi = 0x0;
-#endif
-	ctx->sg_tbl[ctx->sg_num].addr_lo = addr;
+	sec_out64(&ctx->sg_tbl[ctx->sg_num].addr, addr);
 
 	sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag,
 		  (size & SG_ENTRY_LENGTH_MASK));
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index f99d594..fcc8a5a 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -11,6 +11,7 @@
 #include "fsl_sec.h"
 #include "jr.h"
 #include "jobdesc.h"
+#include "desc_constr.h"
 
 #define CIRC_CNT(head, tail, size)	(((head) - (tail)) & (size - 1))
 #define CIRC_SPACE(head, tail, size)	CIRC_CNT((tail), (head) + 1, (size))
@@ -154,11 +155,25 @@ static int jr_hw_reset(void)
 
 /* -1 --- error, can't enqueue -- no space available */
 static int jr_enqueue(uint32_t *desc_addr,
-	       void (*callback)(uint32_t desc, uint32_t status, void *arg),
+	       void (*callback)(uint32_t status, void *arg),
 	       void *arg)
 {
 	struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
-	int head = jr.head;
+	uint32_t head = jr.head;
+	uint32_t desc_word;
+	int length = desc_len(desc_addr);
+	int i;
+
+	/* The descriptor must be submitted to SEC block as per endianness
+	 * of the SEC Block.
+	 * So, if the endianness of Core and SEC block is different, each word
+	 * of the descriptor will be byte-swapped.
+	 */
+	for (i = 0; i < length; i++) {
+		desc_word = desc_addr[i];
+		sec_out32((uint32_t *)&desc_addr[i], desc_word);
+	}
+
 	dma_addr_t desc_phys_addr = virt_to_phys(desc_addr);
 
 	if (sec_in32(&regs->irsa) == 0 ||
@@ -166,7 +181,6 @@ static int jr_enqueue(uint32_t *desc_addr,
 		return -1;
 
 	jr.info[head].desc_phys_addr = desc_phys_addr;
-	jr.info[head].desc_addr = (uint32_t)desc_addr;
 	jr.info[head].callback = (void *)callback;
 	jr.info[head].arg = arg;
 	jr.info[head].op_done = 0;
@@ -177,7 +191,7 @@ static int jr_enqueue(uint32_t *desc_addr,
 					ARCH_DMA_MINALIGN);
 	flush_dcache_range(start, end);
 
-	jr.input_ring[head] = desc_phys_addr;
+	sec_out_phys(&jr.input_ring[head], desc_phys_addr);
 	start = (unsigned long)&jr.input_ring[head] & ~(ARCH_DMA_MINALIGN - 1);
 	end = ALIGN(start + sizeof(dma_addr_t), ARCH_DMA_MINALIGN);
 	flush_dcache_range(start, end);
@@ -192,10 +206,10 @@ static int jr_enqueue(uint32_t *desc_addr,
 static int jr_dequeue(void)
 {
 	struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
-	int head = jr.head;
-	int tail = jr.tail;
-	int idx, i, found;
-	void (*callback)(uint32_t desc, uint32_t status, void *arg);
+	uint32_t head = jr.head;
+	uint32_t tail = jr.tail;
+	uint32_t idx, i, found;
+	void (*callback)(uint32_t status, void *arg);
 	void *arg = NULL;
 
 	while (sec_in32(&regs->orsf) && CIRC_CNT(jr.head, jr.tail, jr.size)) {
@@ -208,14 +222,12 @@ static int jr_dequeue(void)
 
 		found = 0;
 
-		dma_addr_t op_desc = jr.output_ring[jr.tail].desc;
-		uint32_t status = jr.output_ring[jr.tail].status;
-		uint32_t desc_virt;
+		dma_addr_t op_desc = sec_in_phys(&jr.output_ring[jr.tail].desc);
+		uint32_t status = sec_in32(&jr.output_ring[jr.tail].status);
 
 		for (i = 0; CIRC_CNT(head, tail + i, jr.size) >= 1; i++) {
 			idx = (tail + i) & (jr.size - 1);
 			if (op_desc == jr.info[idx].desc_phys_addr) {
-				desc_virt = jr.info[idx].desc_addr;
 				found = 1;
 				break;
 			}
@@ -244,13 +256,13 @@ static int jr_dequeue(void)
 		sec_out32(&regs->orjr, 1);
 		jr.info[idx].op_done = 0;
 
-		callback(desc_virt, status, arg);
+		callback(status, arg);
 	}
 
 	return 0;
 }
 
-static void desc_done(uint32_t desc, uint32_t status, void *arg)
+static void desc_done(uint32_t status, void *arg)
 {
 	struct result *x = arg;
 	x->status = status;
diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h
index cce2c58..b630590 100644
--- a/drivers/crypto/fsl/jr.h
+++ b/drivers/crypto/fsl/jr.h
@@ -40,37 +40,36 @@ struct op_ring {
 } __packed;
 
 struct jr_info {
-	void (*callback)(dma_addr_t desc, uint32_t status, void *arg);
+	void (*callback)(uint32_t status, void *arg);
 	dma_addr_t desc_phys_addr;
-	uint32_t desc_addr;
 	uint32_t desc_len;
 	uint32_t op_done;
 	void *arg;
 };
 
 struct jobring {
-	int jq_id;
-	int irq;
-	int liodn;
+	uint32_t jq_id;
+	uint32_t irq;
+	uint32_t liodn;
 	/* Head is the index where software would enq the descriptor in
 	 * the i/p ring
 	 */
-	int head;
+	uint32_t head;
 	/* Tail index would be used by s/w ehile enqueuing to determine if
 	 * there is any space left in the s/w maintained i/p rings
 	 */
 	/* Also in case of deq tail will be incremented only in case of
 	 * in-order job completion
 	 */
-	int tail;
+	uint32_t tail;
 	/* Read index of the output ring. It may not match with tail in case
 	 * of out of order completetion
 	 */
-	int read_idx;
+	uint32_t read_idx;
 	/* Write index to input ring. Would be always equal to head */
-	int write_idx;
+	uint32_t write_idx;
 	/* Size of the rings. */
-	int size;
+	uint32_t size;
 	/* The ip and output rings have to be accessed by SEC. So the
 	 * pointers will ahve to point to the housekeeping region provided
 	 * by SEC
diff --git a/include/fsl_sec.h b/include/fsl_sec.h
index ebb1ac6..39c9b3c 100644
--- a/include/fsl_sec.h
+++ b/include/fsl_sec.h
@@ -12,12 +12,16 @@
 #include <asm/io.h>
 
 #ifdef CONFIG_SYS_FSL_SEC_LE
+#define sec_in64(a)       in_le64(a)
+#define sec_out64(a, v)   out_le64(a, v)
 #define sec_in32(a)       in_le32(a)
 #define sec_out32(a, v)   out_le32(a, v)
 #define sec_in16(a)       in_le16(a)
 #define sec_clrbits32     clrbits_le32
 #define sec_setbits32     setbits_le32
 #elif defined(CONFIG_SYS_FSL_SEC_BE)
+#define sec_in64(a)       in_be64(a)
+#define sec_out64(a, v)   out_be64(a, v)
 #define sec_in32(a)       in_be32(a)
 #define sec_out32(a, v)   out_be32(a, v)
 #define sec_in16(a)       in_be16(a)
@@ -27,6 +31,15 @@
 #error Neither CONFIG_SYS_FSL_SEC_LE nor CONFIG_SYS_FSL_SEC_BE is defined
 #endif
 
+#ifdef CONFIG_PHYS_64BIT
+#define sec_out_phys	sec_out64
+#define sec_in_phys	sec_in64
+#else
+#define sec_out_phys	sec_out32
+#define sec_in_phys	sec_in32
+#endif
+
+
 /* Security Engine Block (MS = Most Sig., LS = Least Sig.) */
 #if CONFIG_SYS_FSL_SEC_COMPAT >= 4
 /* RNG4 TRNG test registers */
@@ -180,16 +193,7 @@ struct jr_regs {
  * related information
  */
 struct sg_entry {
-#if defined(CONFIG_SYS_FSL_SEC_LE) && !defined(CONFIG_MX6)
-	uint32_t addr_lo;	/* Memory Address - lo */
-	uint16_t addr_hi;	/* Memory Address of start of buffer - hi */
-	uint16_t reserved_zero;
-#else
-	uint16_t reserved_zero;
-	uint16_t addr_hi;	/* Memory Address of start of buffer - hi */
-	uint32_t addr_lo;	/* Memory Address - lo */
-#endif
-
+	uint64_t addr;
 	uint32_t len_flag;	/* Length of the data in the frame */
 #define SG_ENTRY_LENGTH_MASK	0x3FFFFFFF
 #define SG_ENTRY_EXTENSION_BIT	0x80000000
-- 
1.8.1.4



More information about the U-Boot mailing list