1227730Sraj/*-
2227730Sraj * Copyright (C) 2009-2011 Semihalf.
3227730Sraj * All rights reserved.
4227730Sraj *
5227730Sraj * Redistribution and use in source and binary forms, with or without
6227730Sraj * modification, are permitted provided that the following conditions
7227730Sraj * are met:
8227730Sraj * 1. Redistributions of source code must retain the above copyright
9227730Sraj *    notice, this list of conditions and the following disclaimer.
10227730Sraj * 2. Redistributions in binary form must reproduce the above copyright
11227730Sraj *    notice, this list of conditions and the following disclaimer in the
12227730Sraj *    documentation and/or other materials provided with the distribution.
13227730Sraj *
14227730Sraj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15227730Sraj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16227730Sraj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17227730Sraj * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18227730Sraj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19227730Sraj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20227730Sraj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21227730Sraj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22227730Sraj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23227730Sraj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24227730Sraj * SUCH DAMAGE.
25227730Sraj *
26227730Sraj * $FreeBSD$
27227730Sraj */
28227730Sraj
29227730Sraj#ifndef _DEV_CESA_H_
30227730Sraj#define _DEV_CESA_H_
31227730Sraj
32227730Sraj/* Maximum number of allocated sessions */
33227730Sraj#define CESA_SESSIONS			64
34227730Sraj
35227730Sraj/* Maximum number of queued requests */
36227730Sraj#define CESA_REQUESTS			256
37227730Sraj
38227730Sraj/*
39227730Sraj * CESA is able to process data only in CESA SRAM, which is quite small (2 kB).
40227730Sraj * We have to fit a packet there, which contains SA descriptor, keys, IV
41227730Sraj * and data to be processed. Every request must be converted into chain of
42227730Sraj * packets and each packet can hold about 1.75 kB of data.
43227730Sraj *
44227730Sraj * To process each packet we need at least 1 SA descriptor and at least 4 TDMA
45227730Sraj * descriptors. However there are cases when we use 2 SA and 8 TDMA descriptors
46227730Sraj * per packet. Number of used TDMA descriptors can increase beyond given values
47227730Sraj * if data in the request is fragmented in physical memory.
48227730Sraj *
49227730Sraj * The driver uses preallocated SA and TDMA descriptors pools to get best
50227730Sraj * performace. Size of these pools should match expected request size. Example:
51227730Sraj *
52227730Sraj * Expected average request size:			1.5 kB (Ethernet MTU)
53227730Sraj * Packets per average request:				(1.5 kB / 1.75 kB) = 1
54227730Sraj * SA decriptors per average request (worst case):	1 * 2 = 2
55227730Sraj * TDMA desctiptors per average request (worst case):	1 * 8 = 8
56227730Sraj *
57227730Sraj * More TDMA descriptors should be allocated, if data fragmentation is expected
58227730Sraj * (for example while processing mbufs larger than MCLBYTES). The driver may use
59227730Sraj * 2 additional TDMA descriptors per each discontinuity in the physical data
60227730Sraj * layout.
61227730Sraj */
62227730Sraj
63227730Sraj/* Values below are optimized for requests containing about 1.5 kB of data */
64227730Sraj#define CESA_SA_DESC_PER_REQ		2
65227730Sraj#define CESA_TDMA_DESC_PER_REQ		8
66227730Sraj
67227730Sraj#define CESA_SA_DESCRIPTORS		(CESA_SA_DESC_PER_REQ * CESA_REQUESTS)
68227730Sraj#define CESA_TDMA_DESCRIPTORS		(CESA_TDMA_DESC_PER_REQ * CESA_REQUESTS)
69227730Sraj
70227730Sraj/* Useful constants */
71301223Szbb#define CESA_HMAC_TRUNC_LEN		12
72227730Sraj#define CESA_MAX_FRAGMENTS		64
73227730Sraj#define CESA_SRAM_SIZE			2048
74227730Sraj
75227730Sraj/*
76227730Sraj * CESA_MAX_HASH_LEN is maximum length of hash generated by CESA.
77301224Szbb * As CESA supports MD5, SHA1 and SHA-256 this equals to 32 bytes.
78227730Sraj */
79301224Szbb#define CESA_MAX_HASH_LEN		32
80227730Sraj#define CESA_MAX_KEY_LEN		32
81227730Sraj#define CESA_MAX_IV_LEN			16
82227730Sraj#define CESA_MAX_HMAC_BLOCK_LEN		64
83227730Sraj#define CESA_MAX_MKEY_LEN		CESA_MAX_HMAC_BLOCK_LEN
84227730Sraj#define CESA_MAX_PACKET_SIZE		(CESA_SRAM_SIZE - CESA_DATA(0))
85227730Sraj#define CESA_MAX_REQUEST_SIZE		65535
86227730Sraj
87227730Sraj/* Locking macros */
88227730Sraj#define CESA_LOCK(sc, what)		mtx_lock(&(sc)->sc_ ## what ## _lock)
89227730Sraj#define CESA_UNLOCK(sc, what)		mtx_unlock(&(sc)->sc_ ## what ## _lock)
90227730Sraj#define CESA_LOCK_ASSERT(sc, what)	\
91227730Sraj	mtx_assert(&(sc)->sc_ ## what ## _lock, MA_OWNED)
92227730Sraj
93227730Sraj/* Registers read/write macros */
94301222Szbb#define CESA_REG_READ(sc, reg)		\
95301222Szbb	bus_read_4((sc)->sc_res[RES_CESA_REGS], (reg))
96301222Szbb#define CESA_REG_WRITE(sc, reg, val)	\
97301222Szbb	bus_write_4((sc)->sc_res[RES_CESA_REGS], (reg), (val))
98227730Sraj
99301222Szbb#define CESA_TDMA_READ(sc, reg)		\
100301222Szbb	bus_read_4((sc)->sc_res[RES_TDMA_REGS], (reg))
101301222Szbb#define CESA_TDMA_WRITE(sc, reg, val)	\
102301222Szbb	bus_write_4((sc)->sc_res[RES_TDMA_REGS], (reg), (val))
103301222Szbb
104227730Sraj/* Generic allocator for objects */
105227730Sraj#define CESA_GENERIC_ALLOC_LOCKED(sc, obj, pool) do {		\
106227730Sraj	CESA_LOCK(sc, pool);					\
107227730Sraj								\
108227730Sraj	if (STAILQ_EMPTY(&(sc)->sc_free_ ## pool))		\
109227730Sraj		obj = NULL;					\
110227730Sraj	else {							\
111227730Sraj		obj = STAILQ_FIRST(&(sc)->sc_free_ ## pool);	\
112227730Sraj		STAILQ_REMOVE_HEAD(&(sc)->sc_free_ ## pool,	\
113227730Sraj		    obj ## _stq);				\
114227730Sraj	}							\
115227730Sraj								\
116227730Sraj	CESA_UNLOCK(sc, pool);					\
117227730Sraj} while (0)
118227730Sraj
119227730Sraj#define CESA_GENERIC_FREE_LOCKED(sc, obj, pool) do {		\
120227730Sraj	CESA_LOCK(sc, pool);					\
121227730Sraj	STAILQ_INSERT_TAIL(&(sc)->sc_free_ ## pool, obj,	\
122227730Sraj	    obj ## _stq);					\
123227730Sraj	CESA_UNLOCK(sc, pool);					\
124227730Sraj} while (0)
125227730Sraj
126227730Sraj/* CESA SRAM offset calculation macros */
127227730Sraj#define CESA_SA_DATA(member)					\
128227730Sraj	(sizeof(struct cesa_sa_hdesc) + offsetof(struct cesa_sa_data, member))
129227730Sraj#define CESA_DATA(offset)					\
130227730Sraj	(sizeof(struct cesa_sa_hdesc) + sizeof(struct cesa_sa_data) + offset)
131227730Sraj
132301222Szbb/* CESA memory and IRQ resources */
133301222Szbbenum cesa_res_type {
134301222Szbb	RES_TDMA_REGS,
135301222Szbb	RES_CESA_REGS,
136301222Szbb	RES_CESA_IRQ,
137301222Szbb	RES_CESA_NUM
138301222Szbb};
139301222Szbb
140227730Srajstruct cesa_tdma_hdesc {
141227730Sraj	uint16_t	cthd_byte_count;
142227730Sraj	uint16_t	cthd_flags;
143227730Sraj	uint32_t	cthd_src;
144227730Sraj	uint32_t	cthd_dst;
145227730Sraj	uint32_t	cthd_next;
146227730Sraj};
147227730Sraj
148227730Srajstruct cesa_sa_hdesc {
149227730Sraj	uint32_t	cshd_config;
150227730Sraj	uint16_t	cshd_enc_src;
151227730Sraj	uint16_t	cshd_enc_dst;
152227730Sraj	uint32_t	cshd_enc_dlen;
153227730Sraj	uint32_t	cshd_enc_key;
154227730Sraj	uint16_t	cshd_enc_iv;
155227730Sraj	uint16_t	cshd_enc_iv_buf;
156227730Sraj	uint16_t	cshd_mac_src;
157227730Sraj	uint16_t	cshd_mac_total_dlen;
158227730Sraj	uint16_t	cshd_mac_dst;
159227730Sraj	uint16_t	cshd_mac_dlen;
160227730Sraj	uint16_t	cshd_mac_iv_in;
161227730Sraj	uint16_t	cshd_mac_iv_out;
162227730Sraj};
163227730Sraj
164227730Srajstruct cesa_sa_data {
165227730Sraj	uint8_t		csd_key[CESA_MAX_KEY_LEN];
166227730Sraj	uint8_t		csd_iv[CESA_MAX_IV_LEN];
167227730Sraj	uint8_t		csd_hiv_in[CESA_MAX_HASH_LEN];
168227730Sraj	uint8_t		csd_hiv_out[CESA_MAX_HASH_LEN];
169227730Sraj	uint8_t		csd_hash[CESA_MAX_HASH_LEN];
170227730Sraj};
171227730Sraj
172227730Srajstruct cesa_dma_mem {
173227730Sraj	void		*cdm_vaddr;
174227730Sraj	bus_addr_t	cdm_paddr;
175227730Sraj	bus_dma_tag_t	cdm_tag;
176227730Sraj	bus_dmamap_t	cdm_map;
177227730Sraj};
178227730Sraj
179227730Srajstruct cesa_tdma_desc {
180227730Sraj	struct cesa_tdma_hdesc		*ctd_cthd;
181227730Sraj	bus_addr_t			ctd_cthd_paddr;
182227730Sraj
183227730Sraj	STAILQ_ENTRY(cesa_tdma_desc)	ctd_stq;
184227730Sraj};
185227730Sraj
186227730Srajstruct cesa_sa_desc {
187227730Sraj	struct cesa_sa_hdesc		*csd_cshd;
188227730Sraj	bus_addr_t			csd_cshd_paddr;
189227730Sraj
190227730Sraj	STAILQ_ENTRY(cesa_sa_desc)	csd_stq;
191227730Sraj};
192227730Sraj
193227730Srajstruct cesa_session {
194227730Sraj	uint32_t			cs_sid;
195227730Sraj	uint32_t			cs_config;
196227730Sraj	unsigned int			cs_klen;
197227730Sraj	unsigned int			cs_ivlen;
198227730Sraj	unsigned int			cs_hlen;
199227730Sraj	unsigned int			cs_mblen;
200227730Sraj	uint8_t				cs_key[CESA_MAX_KEY_LEN];
201227730Sraj	uint8_t				cs_aes_dkey[CESA_MAX_KEY_LEN];
202227730Sraj	uint8_t				cs_hiv_in[CESA_MAX_HASH_LEN];
203227730Sraj	uint8_t				cs_hiv_out[CESA_MAX_HASH_LEN];
204227730Sraj
205227730Sraj	STAILQ_ENTRY(cesa_session)	cs_stq;
206227730Sraj};
207227730Sraj
208227730Srajstruct cesa_request {
209227730Sraj	struct cesa_sa_data		*cr_csd;
210227730Sraj	bus_addr_t			cr_csd_paddr;
211227730Sraj	struct cryptop			*cr_crp;
212227730Sraj	struct cryptodesc		*cr_enc;
213227730Sraj	struct cryptodesc		*cr_mac;
214227730Sraj	struct cesa_session		*cr_cs;
215227730Sraj	bus_dmamap_t			cr_dmap;
216227730Sraj	int				cr_dmap_loaded;
217227730Sraj
218227730Sraj	STAILQ_HEAD(, cesa_tdma_desc)	cr_tdesc;
219227730Sraj	STAILQ_HEAD(, cesa_sa_desc)	cr_sdesc;
220227730Sraj
221227730Sraj	STAILQ_ENTRY(cesa_request)	cr_stq;
222227730Sraj};
223227730Sraj
224227730Srajstruct cesa_packet {
225227730Sraj	STAILQ_HEAD(, cesa_tdma_desc)	cp_copyin;
226227730Sraj	STAILQ_HEAD(, cesa_tdma_desc)	cp_copyout;
227227730Sraj	unsigned int			cp_size;
228227730Sraj	unsigned int			cp_offset;
229227730Sraj};
230227730Sraj
231227730Srajstruct cesa_softc {
232227730Sraj	device_t			sc_dev;
233227730Sraj	int32_t				sc_cid;
234301222Szbb	struct resource			*sc_res[RES_CESA_NUM];
235227730Sraj	void				*sc_icookie;
236227730Sraj	bus_dma_tag_t			sc_data_dtag;
237227730Sraj	int				sc_error;
238227730Sraj	int				sc_tperr;
239227730Sraj
240227730Sraj	struct mtx			sc_sc_lock;
241227730Sraj	int				sc_blocked;
242227730Sraj
243227730Sraj	/* TDMA descriptors pool */
244227730Sraj	struct mtx			sc_tdesc_lock;
245227730Sraj	struct cesa_tdma_desc		sc_tdesc[CESA_TDMA_DESCRIPTORS];
246227730Sraj	struct cesa_dma_mem		sc_tdesc_cdm;
247227730Sraj	STAILQ_HEAD(, cesa_tdma_desc)	sc_free_tdesc;
248227730Sraj
249227730Sraj	/* SA descriptors pool */
250227730Sraj	struct mtx			sc_sdesc_lock;
251227730Sraj	struct cesa_sa_desc		sc_sdesc[CESA_SA_DESCRIPTORS];
252227730Sraj	struct cesa_dma_mem		sc_sdesc_cdm;
253227730Sraj	STAILQ_HEAD(, cesa_sa_desc)	sc_free_sdesc;
254227730Sraj
255227730Sraj	/* Requests pool */
256227730Sraj	struct mtx			sc_requests_lock;
257227730Sraj	struct cesa_request		sc_requests[CESA_REQUESTS];
258227730Sraj	struct cesa_dma_mem		sc_requests_cdm;
259227730Sraj	STAILQ_HEAD(, cesa_request)	sc_free_requests;
260227730Sraj	STAILQ_HEAD(, cesa_request)	sc_ready_requests;
261227730Sraj	STAILQ_HEAD(, cesa_request)	sc_queued_requests;
262227730Sraj
263227730Sraj	/* Sessions pool */
264227730Sraj	struct mtx			sc_sessions_lock;
265227730Sraj	struct cesa_session		sc_sessions[CESA_SESSIONS];
266227730Sraj	STAILQ_HEAD(, cesa_session)	sc_free_sessions;
267227730Sraj
268227730Sraj	/* CESA SRAM Address */
269301220Szbb	bus_addr_t			sc_sram_base_pa;
270301282Szbb	vm_offset_t			sc_sram_base_va;
271301220Szbb	bus_size_t			sc_sram_size;
272227730Sraj};
273227730Sraj
274227730Srajstruct cesa_chain_info {
275227730Sraj	struct cesa_softc		*cci_sc;
276227730Sraj	struct cesa_request		*cci_cr;
277227730Sraj	struct cryptodesc		*cci_enc;
278227730Sraj	struct cryptodesc		*cci_mac;
279227730Sraj	uint32_t			cci_config;
280227730Sraj	int				cci_error;
281227730Sraj};
282227730Sraj
283227730Sraj/* CESA descriptors flags definitions */
284227730Sraj#define CESA_CTHD_OWNED			(1 << 15)
285227730Sraj
286227730Sraj#define CESA_CSHD_MAC			(0 << 0)
287227730Sraj#define CESA_CSHD_ENC			(1 << 0)
288227730Sraj#define CESA_CSHD_MAC_AND_ENC		(2 << 0)
289227730Sraj#define CESA_CSHD_ENC_AND_MAC		(3 << 0)
290227730Sraj#define CESA_CSHD_OP_MASK		(3 << 0)
291227730Sraj
292227730Sraj#define CESA_CSHD_MD5			(4 << 4)
293227730Sraj#define CESA_CSHD_SHA1			(5 << 4)
294301224Szbb#define CESA_CSHD_SHA2_256		(1 << 4)
295301223Szbb#define CESA_CSHD_MD5_HMAC		(6 << 4)
296301223Szbb#define CESA_CSHD_SHA1_HMAC		(7 << 4)
297301224Szbb#define CESA_CSHD_SHA2_256_HMAC		(3 << 4)
298227730Sraj
299301223Szbb#define CESA_CSHD_96_BIT_HMAC		(1 << 7)
300301223Szbb
301227730Sraj#define CESA_CSHD_DES			(1 << 8)
302227730Sraj#define CESA_CSHD_3DES			(2 << 8)
303227730Sraj#define CESA_CSHD_AES			(3 << 8)
304227730Sraj
305227730Sraj#define CESA_CSHD_DECRYPT		(1 << 12)
306227730Sraj#define CESA_CSHD_CBC			(1 << 16)
307227730Sraj#define CESA_CSHD_3DES_EDE		(1 << 20)
308227730Sraj
309227730Sraj#define CESA_CSH_AES_KLEN_128		(0 << 24)
310227730Sraj#define CESA_CSH_AES_KLEN_192		(1 << 24)
311227730Sraj#define CESA_CSH_AES_KLEN_256		(2 << 24)
312227730Sraj#define CESA_CSH_AES_KLEN_MASK		(3 << 24)
313227730Sraj
314227730Sraj#define CESA_CSHD_FRAG_FIRST		(1 << 30)
315258779Seadler#define CESA_CSHD_FRAG_LAST		(2U << 30)
316258779Seadler#define CESA_CSHD_FRAG_MIDDLE		(3U << 30)
317227730Sraj
318227730Sraj/* CESA registers definitions */
319301222Szbb#define CESA_ICR			0x0E20
320227730Sraj#define CESA_ICR_ACCTDMA		(1 << 7)
321227730Sraj#define CESA_ICR_TPERR			(1 << 12)
322227730Sraj
323301222Szbb#define CESA_ICM			0x0E24
324227730Sraj#define CESA_ICM_ACCTDMA		CESA_ICR_ACCTDMA
325227730Sraj#define CESA_ICM_TPERR			CESA_ICR_TPERR
326227730Sraj
327227730Sraj/* CESA TDMA registers definitions */
328227730Sraj#define CESA_TDMA_ND			0x0830
329227730Sraj
330227730Sraj#define CESA_TDMA_CR			0x0840
331227730Sraj#define CESA_TDMA_CR_DBL128		(4 << 0)
332227730Sraj#define CESA_TDMA_CR_ORDEN		(1 << 4)
333227730Sraj#define CESA_TDMA_CR_SBL128		(4 << 6)
334227730Sraj#define CESA_TDMA_CR_NBS		(1 << 11)
335227730Sraj#define CESA_TDMA_CR_ENABLE		(1 << 12)
336227730Sraj#define CESA_TDMA_CR_FETCHND		(1 << 13)
337227730Sraj#define CESA_TDMA_CR_ACTIVE		(1 << 14)
338227730Sraj
339301224Szbb#if defined (SOC_MV_ARMADA38X)
340301224Szbb#define CESA_TDMA_NUM_OUTSTAND		(2 << 16)
341301224Szbb#endif
342301224Szbb
343227730Sraj#define CESA_TDMA_ECR			0x08C8
344227730Sraj#define CESA_TDMA_ECR_MISS		(1 << 0)
345227730Sraj#define CESA_TDMA_ECR_DOUBLE_HIT	(1 << 1)
346227730Sraj#define CESA_TDMA_ECR_BOTH_HIT		(1 << 2)
347227730Sraj#define CESA_TDMA_ECR_DATA_ERROR	(1 << 3)
348227730Sraj
349227730Sraj#define CESA_TDMA_EMR			0x08CC
350227730Sraj#define CESA_TDMA_EMR_MISS		CESA_TDMA_ECR_MISS
351227730Sraj#define CESA_TDMA_EMR_DOUBLE_HIT	CESA_TDMA_ECR_DOUBLE_HIT
352227730Sraj#define CESA_TDMA_EMR_BOTH_HIT		CESA_TDMA_ECR_BOTH_HIT
353227730Sraj#define CESA_TDMA_EMR_DATA_ERROR	CESA_TDMA_ECR_DATA_ERROR
354227730Sraj
355250291Sgber/*  CESA TDMA address decoding registers */
356250291Sgber#define MV_WIN_CESA_CTRL(n)		(0x8 * (n) + 0xA04)
357250291Sgber#define MV_WIN_CESA_BASE(n)		(0x8 * (n) + 0xA00)
358250291Sgber#define MV_WIN_CESA_MAX			4
359250291Sgber
360227730Sraj/* CESA SA registers definitions */
361301222Szbb#define CESA_SA_CMD			0x0E00
362227730Sraj#define CESA_SA_CMD_ACTVATE		(1 << 0)
363227730Sraj
364301224Szbb#if defined (SOC_MV_ARMADA38X)
365301224Szbb#define CESA_SA_CMD_SHA2		(1 << 31)
366301224Szbb#endif
367301224Szbb
368301222Szbb#define CESA_SA_DPR			0x0E04
369227730Sraj
370301222Szbb#define CESA_SA_CR			0x0E08
371227730Sraj#define CESA_SA_CR_WAIT_FOR_TDMA	(1 << 7)
372227730Sraj#define CESA_SA_CR_ACTIVATE_TDMA	(1 << 9)
373227730Sraj#define CESA_SA_CR_MULTI_MODE		(1 << 11)
374227730Sraj
375301222Szbb#define CESA_SA_SR			0x0E0C
376227730Sraj#define CESA_SA_SR_ACTIVE		(1 << 0)
377227730Sraj
378227730Sraj#endif
379