| #ifndef ASR_SHA_H |
| #define ASR_SHA_H |
| |
| #include <linux/scatterlist.h> |
| #include <linux/crypto.h> |
| #include <crypto/sha.h> |
| #include <crypto/hash.h> |
| #include <crypto/internal/hash.h> |
| |
| #define ASR_SHA_BUFFER_ORDER 2 |
| #define ASR_SHA_BUFFER_SIZE (PAGE_SIZE << ASR_SHA_BUFFER_ORDER) |
| |
| /* SHA flags */ |
| #define SHA_FLAGS_BUSY BIT(0) |
| #define SHA_FLAGS_INIT BIT(1) |
| #define SHA_FLAGS_FINAL BIT(2) |
| #define SHA_FLAGS_FINUP BIT(3) |
| #define SHA_FLAGS_OUTPUT_READY BIT(4) |
| #define SHA_FLAGS_ALGO_MASK GENMASK(10, 5) |
| #define SHA_FLAGS_SHA1 BIT(5) |
| #define SHA_FLAGS_SHA224 BIT(6) |
| #define SHA_FLAGS_SHA256 BIT(7) |
| #define SHA_FLAGS_HMAC BIT(8) |
| #define SHA_FLAGS_PAD BIT(9) |
| #define SHA_FLAGS_ERROR BIT(10) |
| |
| #define SHA_OP_INIT 1 |
| #define SHA_OP_UPDATE 2 |
| #define SHA_OP_FINAL 3 |
| |
| #define HASH_BUF_LEN 64 |
| |
| typedef enum { |
| HASH_SHA1 = 0x0, |
| HASH_SHA224 = 0X2, |
| HASH_SHA256 = 0x3, |
| } HASH_ALGO_T; |
| |
| struct asr_te200_sha; |
| |
| typedef int (*asr_sha_fn_t)(struct asr_te200_sha *); |
| typedef irqreturn_t (*asr_sha_irq_t)(void *); |
| |
| struct asr_te200_sha { |
| unsigned long phys_base; |
| struct device *dev; |
| struct clk *iclk; |
| int irq; |
| void __iomem *io_base; |
| |
| spinlock_t lock; |
| struct mutex sha_lock; |
| |
| int err; |
| struct tasklet_struct done_task; |
| struct tasklet_struct queue_task; |
| |
| unsigned long flags; |
| struct crypto_queue queue; |
| struct ahash_request *req; |
| bool is_async; |
| bool force_complete; |
| asr_sha_fn_t resume; |
| |
| int alg; |
| }; |
| |
| typedef struct te200_hash_context { |
| volatile uint32_t count; /* Used to store the extra data count */ |
| unsigned char extra_data[HASH_BUF_LEN]; /* Buffer to store the extra data*/ |
| volatile uint64_t total_bits_num; /* Total process data bits number */ |
| unsigned char |
| hash_temp[64 / 2]; /* Buffer to store hash temp value */ |
| int alg; |
| uint32_t hash_temp_valid; |
| uint32_t finish_flag; /* This flag indicates if the context need to finish. |
| * 0 not, 1 need to do. */ |
| } te200_hash_context_t; |
| |
| /* |
| * .statesize = sizeof(struct asr_sha_reqctx) must be <= PAGE_SIZE / 8 as |
| * tested by the ahash_prepare_alg() function. |
| */ |
| |
| struct asr_sha_reqctx { |
| struct asr_te200_sha *dd; |
| unsigned long op; |
| |
| u8 digest[SHA512_DIGEST_SIZE] __aligned(sizeof(u32)); |
| u64 digcnt[2]; |
| void *buffer; |
| size_t bufcnt; |
| size_t buflen; |
| |
| /* walk state */ |
| struct scatterlist *sg; |
| unsigned int offset; /* offset in current sg */ |
| unsigned int total; /* total request */ |
| |
| int alg; |
| unsigned long flags; |
| |
| te200_hash_context_t hash_ctx; |
| }; |
| |
| struct asr_sha_ctx { |
| struct asr_te200_sha *dd; |
| asr_sha_fn_t start; |
| |
| unsigned long flags; |
| }; |
| |
| #define ASR_SHA_QUEUE_LENGTH 50 |
| |
| int asr_te200_hash_init(struct asr_sha_reqctx *reqctx, int alg); |
| int asr_te200_hash_proc(struct asr_sha_reqctx *reqctx, const uint8_t *src, size_t size); |
| int asr_te200_hash_finish(struct asr_sha_reqctx *reqctx, uint8_t *out, uint32_t out_size); |
| #endif |