aboutsummaryrefslogtreecommitdiff
path: root/drivers/crypto/amcc/crypto4xx_core.h
blob: 2df6874edee107bdb6b129b7c300c710d44dab77 (plain)
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
/**
 * AMCC SoC PPC4xx Crypto Driver
 *
 * Copyright (c) 2008 Applied Micro Circuits Corporation.
 * All rights reserved. James Hsiao <jhsiao@amcc.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * This is the header file for AMCC Crypto offload Linux device driver for
 * use with Linux CryptoAPI.

 */

#ifndef __CRYPTO4XX_CORE_H__
#define __CRYPTO4XX_CORE_H__

#include <crypto/internal/hash.h>
#include "crypto4xx_reg_def.h"
#include "crypto4xx_sa.h"

#define MODULE_NAME "crypto4xx"

#define PPC460SX_SDR0_SRST                      0x201
#define PPC405EX_SDR0_SRST                      0x200
#define PPC460EX_SDR0_SRST                      0x201
#define PPC460EX_CE_RESET                       0x08000000
#define PPC460SX_CE_RESET                       0x20000000
#define PPC405EX_CE_RESET                       0x00000008

#define CRYPTO4XX_CRYPTO_PRIORITY		300
#define PPC4XX_NUM_PD				256
#define PPC4XX_LAST_PD				(PPC4XX_NUM_PD - 1)
#define PPC4XX_NUM_GD				1024
#define PPC4XX_LAST_GD				(PPC4XX_NUM_GD - 1)
#define PPC4XX_NUM_SD				256
#define PPC4XX_LAST_SD				(PPC4XX_NUM_SD - 1)
#define PPC4XX_SD_BUFFER_SIZE			2048

#define PD_ENTRY_BUSY				BIT(1)
#define PD_ENTRY_INUSE				BIT(0)
#define PD_ENTRY_FREE				0
#define ERING_WAS_FULL				0xffffffff

struct crypto4xx_device;

union shadow_sa_buf {
	struct dynamic_sa_ctl sa;

	/* alloc 256 bytes which is enough for any kind of dynamic sa */
	u8 buf[256];
} __packed;

struct pd_uinfo {
	struct crypto4xx_device *dev;
	u32   state;
	u32 using_sd;
	u32 first_gd;		/* first gather discriptor
				used by this packet */
	u32 num_gd;             /* number of gather discriptor
				used by this packet */
	u32 first_sd;		/* first scatter discriptor
				used by this packet */
	u32 num_sd;		/* number of scatter discriptors
				used by this packet */
	struct dynamic_sa_ctl *sa_va;	/* shadow sa */
	u32 sa_pa;
	struct sa_state_record *sr_va;	/* state record for shadow sa */
	u32 sr_pa;
	struct scatterlist *dest_va;
	struct crypto_async_request *async_req; 	/* base crypto request
							for this packet */
};

struct crypto4xx_device {
	struct crypto4xx_core_device *core_dev;
	char *name;
	void __iomem *ce_base;
	void __iomem *trng_base;

	struct ce_pd *pdr;	/* base address of packet descriptor ring */
	dma_addr_t pdr_pa;	/* physical address of pdr_base_register */
	struct ce_gd *gdr;	/* gather descriptor ring */
	dma_addr_t gdr_pa;	/* physical address of gdr_base_register */
	struct ce_sd *sdr;	/* scatter descriptor ring */
	dma_addr_t sdr_pa;	/* physical address of sdr_base_register */
	void *scatter_buffer_va;
	dma_addr_t scatter_buffer_pa;

	union shadow_sa_buf *shadow_sa_pool;
	dma_addr_t shadow_sa_pool_pa;
	struct sa_state_record *shadow_sr_pool;
	dma_addr_t shadow_sr_pool_pa;
	u32 pdr_tail;
	u32 pdr_head;
	u32 gdr_tail;
	u32 gdr_head;
	u32 sdr_tail;
	u32 sdr_head;
	struct pd_uinfo *pdr_uinfo;
	struct list_head alg_list;	/* List of algorithm supported
					by this device */
};

struct crypto4xx_core_device {
	struct device *device;
	struct platform_device *ofdev;
	struct crypto4xx_device *dev;
	struct hwrng *trng;
	u32 int_status;
	u32 irq;
	struct tasklet_struct tasklet;
	spinlock_t lock;
};

struct crypto4xx_ctx {
	struct crypto4xx_device *dev;
	struct dynamic_sa_ctl *sa_in;
	dma_addr_t sa_in_dma_addr;
	struct dynamic_sa_ctl *sa_out;
	dma_addr_t sa_out_dma_addr;
	struct sa_state_record *state_record;
	dma_addr_t state_record_dma_addr;
	u32 sa_len;
	u32 offset_to_sr_ptr;           /* offset to state ptr, in dynamic sa */
	u32 direction;
	u32 save_iv;
	u32 pd_ctl;
	u32 is_hash;
};

struct crypto4xx_alg_common {
	u32 type;
	union {
		struct crypto_alg cipher;
		struct ahash_alg hash;
	} u;
};

struct crypto4xx_alg {
	struct list_head  entry;
	struct crypto4xx_alg_common alg;
	struct crypto4xx_device *dev;
};

static inline struct crypto4xx_alg *crypto_alg_to_crypto4xx_alg(
	struct crypto_alg *x)
{
	switch (x->cra_flags & CRYPTO_ALG_TYPE_MASK) {
	case CRYPTO_ALG_TYPE_AHASH:
		return container_of(__crypto_ahash_alg(x),
				    struct crypto4xx_alg, alg.u.hash);
	}

	return container_of(x, struct crypto4xx_alg, alg.u.cipher);
}

int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size);
void crypto4xx_free_sa(struct crypto4xx_ctx *ctx);
void crypto4xx_free_ctx(struct crypto4xx_ctx *ctx);
u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx);
int crypto4xx_build_pd(struct crypto_async_request *req,
		       struct crypto4xx_ctx *ctx,
		       struct scatterlist *src,
		       struct scatterlist *dst,
		       unsigned int datalen,
		       void *iv, u32 iv_len);
int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher *cipher,
			     const u8 *key, unsigned int keylen);
int crypto4xx_setkey_aes_cfb(struct crypto_ablkcipher *cipher,
			     const u8 *key, unsigned int keylen);
int crypto4xx_setkey_aes_ecb(struct crypto_ablkcipher *cipher,
			     const u8 *key, unsigned int keylen);
int crypto4xx_setkey_aes_ofb(struct crypto_ablkcipher *cipher,
			     const u8 *key, unsigned int keylen);
int crypto4xx_setkey_rfc3686(struct crypto_ablkcipher *cipher,
			     const u8 *key, unsigned int keylen);
int crypto4xx_encrypt(struct ablkcipher_request *req);
int crypto4xx_decrypt(struct ablkcipher_request *req);
int crypto4xx_rfc3686_encrypt(struct ablkcipher_request *req);
int crypto4xx_rfc3686_decrypt(struct ablkcipher_request *req);
int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm);
int crypto4xx_hash_digest(struct ahash_request *req);
int crypto4xx_hash_final(struct ahash_request *req);
int crypto4xx_hash_update(struct ahash_request *req);
int crypto4xx_hash_init(struct ahash_request *req);

/**
 * Note: Only use this function to copy items that is word aligned.
 */
static inline void crypto4xx_memcpy_swab32(u32 *dst, const void *buf,
					   size_t len)
{
	for (; len >= 4; buf += 4, len -= 4)
		*dst++ = __swab32p((u32 *) buf);

	if (len) {
		const u8 *tmp = (u8 *)buf;

		switch (len) {
		case 3:
			*dst = (tmp[2] << 16) |
			       (tmp[1] << 8) |
			       tmp[0];
			break;
		case 2:
			*dst = (tmp[1] << 8) |
			       tmp[0];
			break;
		case 1:
			*dst = tmp[0];
			break;
		default:
			break;
		}
	}
}

static inline void crypto4xx_memcpy_from_le32(u32 *dst, const void *buf,
					      size_t len)
{
	crypto4xx_memcpy_swab32(dst, buf, len);
}

static inline void crypto4xx_memcpy_to_le32(__le32 *dst, const void *buf,
					    size_t len)
{
	crypto4xx_memcpy_swab32((u32 *)dst, buf, len);
}
#endif