summaryrefslogtreecommitdiffstats
path: root/drivers/crypto/ux500/hash/hash_alg.h
blob: cd9351cb24df938a6aa7538950bdd2708e8d0301 (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
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
/*
 * Copyright (C) ST-Ericsson SA 2010
 * Author: Shujuan Chen (shujuan.chen@stericsson.com)
 * Author: Joakim Bech (joakim.xx.bech@stericsson.com)
 * Author: Berne Hebark (berne.hebark@stericsson.com))
 * License terms: GNU General Public License (GPL) version 2
 */
#ifndef _HASH_ALG_H
#define _HASH_ALG_H

#include <linux/bitops.h>

#define HASH_BLOCK_SIZE			64
#define HASH_DMA_ALIGN_SIZE		4
#define HASH_DMA_PERFORMANCE_MIN_SIZE	1024
#define HASH_BYTES_PER_WORD		4

/* Maximum value of the length's high word */
#define HASH_HIGH_WORD_MAX_VAL		0xFFFFFFFFUL

/* Power on Reset values HASH registers */
#define HASH_RESET_CR_VALUE		0x0
#define HASH_RESET_STR_VALUE		0x0

/* Number of context swap registers */
#define HASH_CSR_COUNT			52

#define HASH_RESET_CSRX_REG_VALUE	0x0
#define HASH_RESET_CSFULL_REG_VALUE	0x0
#define HASH_RESET_CSDATAIN_REG_VALUE	0x0

#define HASH_RESET_INDEX_VAL		0x0
#define HASH_RESET_BIT_INDEX_VAL	0x0
#define HASH_RESET_BUFFER_VAL		0x0
#define HASH_RESET_LEN_HIGH_VAL		0x0
#define HASH_RESET_LEN_LOW_VAL		0x0

/* Control register bitfields */
#define HASH_CR_RESUME_MASK	0x11FCF

#define HASH_CR_SWITCHON_POS	31
#define HASH_CR_SWITCHON_MASK	BIT(31)

#define HASH_CR_EMPTYMSG_POS	20
#define HASH_CR_EMPTYMSG_MASK	BIT(20)

#define HASH_CR_DINF_POS	12
#define HASH_CR_DINF_MASK	BIT(12)

#define HASH_CR_NBW_POS		8
#define HASH_CR_NBW_MASK	0x00000F00UL

#define HASH_CR_LKEY_POS	16
#define HASH_CR_LKEY_MASK	BIT(16)

#define HASH_CR_ALGO_POS	7
#define HASH_CR_ALGO_MASK	BIT(7)

#define HASH_CR_MODE_POS	6
#define HASH_CR_MODE_MASK	BIT(6)

#define HASH_CR_DATAFORM_POS	4
#define HASH_CR_DATAFORM_MASK	(BIT(4) | BIT(5))

#define HASH_CR_DMAE_POS	3
#define HASH_CR_DMAE_MASK	BIT(3)

#define HASH_CR_INIT_POS	2
#define HASH_CR_INIT_MASK	BIT(2)

#define HASH_CR_PRIVN_POS	1
#define HASH_CR_PRIVN_MASK	BIT(1)

#define HASH_CR_SECN_POS	0
#define HASH_CR_SECN_MASK	BIT(0)

/* Start register bitfields */
#define HASH_STR_DCAL_POS	8
#define HASH_STR_DCAL_MASK	BIT(8)
#define HASH_STR_DEFAULT	0x0

#define HASH_STR_NBLW_POS	0
#define HASH_STR_NBLW_MASK	0x0000001FUL

#define HASH_NBLW_MAX_VAL	0x1F

/* PrimeCell IDs */
#define HASH_P_ID0		0xE0
#define HASH_P_ID1		0x05
#define HASH_P_ID2		0x38
#define HASH_P_ID3		0x00
#define HASH_CELL_ID0		0x0D
#define HASH_CELL_ID1		0xF0
#define HASH_CELL_ID2		0x05
#define HASH_CELL_ID3		0xB1

#define HASH_SET_BITS(reg_name, mask)	\
	writel_relaxed((readl_relaxed(reg_name) | mask), reg_name)

#define HASH_CLEAR_BITS(reg_name, mask)	\
	writel_relaxed((readl_relaxed(reg_name) & ~mask), reg_name)

#define HASH_PUT_BITS(reg, val, shift, mask)	\
	writel_relaxed(((readl(reg) & ~(mask)) |	\
		(((u32)val << shift) & (mask))), reg)

#define HASH_SET_DIN(val, len)	writesl(&device_data->base->din, (val), (len))

#define HASH_INITIALIZE			\
	HASH_PUT_BITS(			\
		&device_data->base->cr,	\
		0x01, HASH_CR_INIT_POS,	\
		HASH_CR_INIT_MASK)

#define HASH_SET_DATA_FORMAT(data_format)				\
		HASH_PUT_BITS(						\
			&device_data->base->cr,				\
			(u32) (data_format), HASH_CR_DATAFORM_POS,	\
			HASH_CR_DATAFORM_MASK)
#define HASH_SET_NBLW(val)					\
		HASH_PUT_BITS(					\
			&device_data->base->str,		\
			(u32) (val), HASH_STR_NBLW_POS,		\
			HASH_STR_NBLW_MASK)
#define HASH_SET_DCAL					\
		HASH_PUT_BITS(				\
			&device_data->base->str,	\
			0x01, HASH_STR_DCAL_POS,	\
			HASH_STR_DCAL_MASK)

/* Hardware access method */
enum hash_mode {
	HASH_MODE_CPU,
	HASH_MODE_DMA
};

/**
 * struct uint64 - Structure to handle 64 bits integers.
 * @high_word:	Most significant bits.
 * @low_word:	Least significant bits.
 *
 * Used to handle 64 bits integers.
 */
struct uint64 {
	u32 high_word;
	u32 low_word;
};

/**
 * struct hash_register - Contains all registers in ux500 hash hardware.
 * @cr:		HASH control register (0x000).
 * @din:	HASH data input register (0x004).
 * @str:	HASH start register (0x008).
 * @hx:		HASH digest register 0..7 (0x00c-0x01C).
 * @padding0:	Reserved (0x02C).
 * @itcr:	Integration test control register (0x080).
 * @itip:	Integration test input register (0x084).
 * @itop:	Integration test output register (0x088).
 * @padding1:	Reserved (0x08C).
 * @csfull:	HASH context full register (0x0F8).
 * @csdatain:	HASH context swap data input register (0x0FC).
 * @csrx:	HASH context swap register 0..51 (0x100-0x1CC).
 * @padding2:	Reserved (0x1D0).
 * @periphid0:	HASH peripheral identification register 0 (0xFE0).
 * @periphid1:	HASH peripheral identification register 1 (0xFE4).
 * @periphid2:	HASH peripheral identification register 2 (0xFE8).
 * @periphid3:	HASH peripheral identification register 3 (0xFEC).
 * @cellid0:	HASH PCell identification register 0 (0xFF0).
 * @cellid1:	HASH PCell identification register 1 (0xFF4).
 * @cellid2:	HASH PCell identification register 2 (0xFF8).
 * @cellid3:	HASH PCell identification register 3 (0xFFC).
 *
 * The device communicates to the HASH via 32-bit-wide control registers
 * accessible via the 32-bit width AMBA rev. 2.0 AHB Bus. Below is a structure
 * with the registers used.
 */
struct hash_register {
	u32 cr;
	u32 din;
	u32 str;
	u32 hx[8];

	u32 padding0[(0x080 - 0x02C) / sizeof(u32)];

	u32 itcr;
	u32 itip;
	u32 itop;

	u32 padding1[(0x0F8 - 0x08C) / sizeof(u32)];

	u32 csfull;
	u32 csdatain;
	u32 csrx[HASH_CSR_COUNT];

	u32 padding2[(0xFE0 - 0x1D0) / sizeof(u32)];

	u32 periphid0;
	u32 periphid1;
	u32 periphid2;
	u32 periphid3;

	u32 cellid0;
	u32 cellid1;
	u32 cellid2;
	u32 cellid3;
};

/**
 * struct hash_state - Hash context state.
 * @temp_cr:	Temporary HASH Control Register.
 * @str_reg:	HASH Start Register.
 * @din_reg:	HASH Data Input Register.
 * @csr[52]:	HASH Context Swap Registers 0-39.
 * @csfull:	HASH Context Swap Registers 40 ie Status flags.
 * @csdatain:	HASH Context Swap Registers 41 ie Input data.
 * @buffer:	Working buffer for messages going to the hardware.
 * @length:	Length of the part of message hashed so far (floor(N/64) * 64).
 * @index:	Valid number of bytes in buffer (N % 64).
 * @bit_index:	Valid number of bits in buffer (N % 8).
 *
 * This structure is used between context switches, i.e. when ongoing jobs are
 * interupted with new jobs. When this happens we need to store intermediate
 * results in software.
 *
 * WARNING: "index" is the  member of the structure, to be sure  that "buffer"
 * is aligned on a 4-bytes boundary. This is highly implementation dependent
 * and MUST be checked whenever this code is ported on new platforms.
 */
struct hash_state {
	u32		temp_cr;
	u32		str_reg;
	u32		din_reg;
	u32		csr[52];
	u32		csfull;
	u32		csdatain;
	u32		buffer[HASH_BLOCK_SIZE / sizeof(u32)];
	struct uint64	length;
	u8		index;
	u8		bit_index;
};

/**
 * enum hash_device_id - HASH device ID.
 * @HASH_DEVICE_ID_0: Hash hardware with ID 0
 * @HASH_DEVICE_ID_1: Hash hardware with ID 1
 */
enum hash_device_id {
	HASH_DEVICE_ID_0 = 0,
	HASH_DEVICE_ID_1 = 1
};

/**
 * enum hash_data_format - HASH data format.
 * @HASH_DATA_32_BITS:	32 bits data format
 * @HASH_DATA_16_BITS:	16 bits data format
 * @HASH_DATA_8_BITS:	8 bits data format.
 * @HASH_DATA_1_BITS:	1 bit data format.
 */
enum hash_data_format {
	HASH_DATA_32_BITS	= 0x0,
	HASH_DATA_16_BITS	= 0x1,
	HASH_DATA_8_BITS	= 0x2,
	HASH_DATA_1_BIT		= 0x3
};

/**
 * enum hash_algo - Enumeration for selecting between SHA1 or SHA2 algorithm.
 * @HASH_ALGO_SHA1: Indicates that SHA1 is used.
 * @HASH_ALGO_SHA2: Indicates that SHA2 (SHA256) is used.
 */
enum hash_algo {
	HASH_ALGO_SHA1		= 0x0,
	HASH_ALGO_SHA256	= 0x1
};

/**
 * enum hash_op - Enumeration for selecting between HASH or HMAC mode.
 * @HASH_OPER_MODE_HASH: Indicates usage of normal HASH mode.
 * @HASH_OPER_MODE_HMAC: Indicates usage of HMAC.
 */
enum hash_op {
	HASH_OPER_MODE_HASH = 0x0,
	HASH_OPER_MODE_HMAC = 0x1
};

/**
 * struct hash_config - Configuration data for the hardware.
 * @data_format:	Format of data entered into the hash data in register.
 * @algorithm:		Algorithm selection bit.
 * @oper_mode:		Operating mode selection bit.
 */
struct hash_config {
	int data_format;
	int algorithm;
	int oper_mode;
};

/**
 * struct hash_dma - Structure used for dma.
 * @mask:		DMA capabilities bitmap mask.
 * @complete:		Used to maintain state for a "completion".
 * @chan_mem2hash:	DMA channel.
 * @cfg_mem2hash:	DMA channel configuration.
 * @sg_len:		Scatterlist length.
 * @sg:			Scatterlist.
 * @nents:		Number of sg entries.
 */
struct hash_dma {
	dma_cap_mask_t		mask;
	struct completion	complete;
	struct dma_chan		*chan_mem2hash;
	void			*cfg_mem2hash;
	int			sg_len;
	struct scatterlist	*sg;
	int			nents;
};

/**
 * struct hash_ctx - The context used for hash calculations.
 * @key:	The key used in the operation.
 * @keylen:	The length of the key.
 * @state:	The state of the current calculations.
 * @config:	The current configuration.
 * @digestsize:	The size of current digest.
 * @device:	Pointer to the device structure.
 */
struct hash_ctx {
	u8			*key;
	u32			keylen;
	struct hash_config	config;
	int			digestsize;
	struct hash_device_data	*device;
};

/**
 * struct hash_ctx - The request context used for hash calculations.
 * @state:	The state of the current calculations.
 * @dma_mode:	Used in special cases (workaround), e.g. need to change to
 *		cpu mode, if not supported/working in dma mode.
 * @updated:	Indicates if hardware is initialized for new operations.
 */
struct hash_req_ctx {
	struct hash_state	state;
	bool			dma_mode;
	u8			updated;
};

/**
 * struct hash_device_data - structure for a hash device.
 * @base:		Pointer to the hardware base address.
 * @list_node:		For inclusion in klist.
 * @dev:		Pointer to the device dev structure.
 * @ctx_lock:		Spinlock for current_ctx.
 * @current_ctx:	Pointer to the currently allocated context.
 * @power_state:	TRUE = power state on, FALSE = power state off.
 * @power_state_lock:	Spinlock for power_state.
 * @regulator:		Pointer to the device's power control.
 * @clk:		Pointer to the device's clock control.
 * @restore_dev_state:	TRUE = saved state, FALSE = no saved state.
 * @dma:		Structure used for dma.
 */
struct hash_device_data {
	struct hash_register __iomem	*base;
	struct klist_node	list_node;
	struct device		*dev;
	struct spinlock		ctx_lock;
	struct hash_ctx		*current_ctx;
	bool			power_state;
	struct spinlock		power_state_lock;
	struct regulator	*regulator;
	struct clk		*clk;
	bool			restore_dev_state;
	struct hash_state	state; /* Used for saving and resuming state */
	struct hash_dma		dma;
};

int hash_check_hw(struct hash_device_data *device_data);

int hash_setconfiguration(struct hash_device_data *device_data,
		struct hash_config *config);

void hash_begin(struct hash_device_data *device_data, struct hash_ctx *ctx);

void hash_get_digest(struct hash_device_data *device_data,
		u8 *digest, int algorithm);

int hash_hw_update(struct ahash_request *req);

int hash_save_state(struct hash_device_data *device_data,
		struct hash_state *state);

int hash_resume_state(struct hash_device_data *device_data,
		const struct hash_state *state);

#endif
OpenPOWER on IntegriCloud