kernel: move linux/ath9k_platform.h to generic files so that it can be reused from...
[openwrt.git] / target / linux / generic / files / crypto / ocf / kirkwood / cesa_ocf_drv.c
1 /*******************************************************************************
2 Copyright (C) Marvell International Ltd. and its affiliates
3
4 This software file (the "File") is owned and distributed by Marvell
5 International Ltd. and/or its affiliates ("Marvell") under the following
6 alternative licensing terms. Once you have made an election to distribute the
7 File under one of the following license alternatives, please (i) delete this
8 introductory statement regarding license alternatives, (ii) delete the two
9 license alternatives that you have not elected to use and (iii) preserve the
10 Marvell copyright notice above.
11
12
13 ********************************************************************************
14 Marvell GPL License Option
15
16 If you received this File from Marvell, you may opt to use, redistribute and/or
17 modify this File in accordance with the terms and conditions of the General
18 Public License Version 2, June 1991 (the "GPL License"), a copy of which is
19 available along with the File in the license.txt file or by writing to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
21 on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
22
23 THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
24 WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
25 DISCLAIMED. The GPL License provides additional details about this warranty
26 disclaimer.
27 *******************************************************************************/
28
29 #include <linux/version.h>
30 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) && !defined(AUTOCONF_INCLUDED)
31 #include <linux/config.h>
32 #endif
33 #include <linux/module.h>
34 #include <linux/init.h>
35 #include <linux/list.h>
36 #include <linux/slab.h>
37 #include <linux/sched.h>
38 #include <linux/wait.h>
39 #include <linux/crypto.h>
40 #include <linux/mm.h>
41 #include <linux/skbuff.h>
42 #include <linux/random.h>
43 #include <linux/platform_device.h>
44 #include <asm/scatterlist.h>
45 #include <linux/spinlock.h>
46 #include "ctrlEnv/sys/mvSysCesa.h"
47 #include "cesa/mvCesa.h" /* moved here before cryptodev.h due to include dependencies */
48 #include <cryptodev.h>
49 #include <uio.h>
50 #include <plat/mv_cesa.h>
51 #include <linux/mbus.h>
52 #include "mvDebug.h"
53
54 #include "cesa/mvMD5.h"
55 #include "cesa/mvSHA1.h"
56
57 #include "cesa/mvCesaRegs.h"
58 #include "cesa/AES/mvAes.h"
59 #include "cesa/mvLru.h"
60
61 #undef RT_DEBUG
62 #ifdef RT_DEBUG
63 static int debug = 1;
64 module_param(debug, int, 1);
65 MODULE_PARM_DESC(debug, "Enable debug");
66 #undef dprintk
67 #define dprintk(a...) if (debug) { printk(a); } else
68 #else
69 static int debug = 0;
70 #undef dprintk
71 #define dprintk(a...)
72 #endif
73
74
75 /* TDMA Regs */
76 #define WINDOW_BASE(i) 0xA00 + (i << 3)
77 #define WINDOW_CTRL(i) 0xA04 + (i << 3)
78
79 /* interrupt handling */
80 #undef CESA_OCF_POLLING
81 #undef CESA_OCF_TASKLET
82
83 #if defined(CESA_OCF_POLLING) && defined(CESA_OCF_TASKLET)
84 #error "don't use both tasklet and polling mode"
85 #endif
86
87 extern int cesaReqResources;
88 /* support for spliting action into 2 actions */
89 #define CESA_OCF_SPLIT
90
91 /* general defines */
92 #define CESA_OCF_MAX_SES 128
93 #define CESA_Q_SIZE 64
94
95
96 /* data structures */
97 struct cesa_ocf_data {
98 int cipher_alg;
99 int auth_alg;
100 int encrypt_tn_auth;
101 #define auth_tn_decrypt encrypt_tn_auth
102 int ivlen;
103 int digestlen;
104 short sid_encrypt;
105 short sid_decrypt;
106 /* fragment workaround sessions */
107 short frag_wa_encrypt;
108 short frag_wa_decrypt;
109 short frag_wa_auth;
110 };
111
112 /* CESA device data */
113 struct cesa_dev {
114 void __iomem *sram;
115 void __iomem *reg;
116 struct mv_cesa_platform_data *plat_data;
117 int irq;
118 };
119
120 #define DIGEST_BUF_SIZE 32
121 struct cesa_ocf_process {
122 MV_CESA_COMMAND cesa_cmd;
123 MV_CESA_MBUF cesa_mbuf;
124 MV_BUF_INFO cesa_bufs[MV_CESA_MAX_MBUF_FRAGS];
125 char digest[DIGEST_BUF_SIZE];
126 int digest_len;
127 struct cryptop *crp;
128 int need_cb;
129 };
130
131 /* global variables */
132 static int32_t cesa_ocf_id = -1;
133 static struct cesa_ocf_data *cesa_ocf_sessions[CESA_OCF_MAX_SES];
134 static spinlock_t cesa_lock;
135 static struct cesa_dev cesa_device;
136
137 /* static APIs */
138 static int cesa_ocf_process (device_t, struct cryptop *, int);
139 static int cesa_ocf_newsession (device_t, u_int32_t *, struct cryptoini *);
140 static int cesa_ocf_freesession (device_t, u_int64_t);
141 static void cesa_callback (unsigned long);
142 static irqreturn_t cesa_interrupt_handler (int, void *);
143 #ifdef CESA_OCF_POLLING
144 static void cesa_interrupt_polling(void);
145 #endif
146 #ifdef CESA_OCF_TASKLET
147 static struct tasklet_struct cesa_ocf_tasklet;
148 #endif
149
150 static struct timeval tt_start;
151 static struct timeval tt_end;
152
153 /*
154 * dummy device structure
155 */
156
157 static struct {
158 softc_device_decl sc_dev;
159 } mv_cesa_dev;
160
161 static device_method_t mv_cesa_methods = {
162 /* crypto device methods */
163 DEVMETHOD(cryptodev_newsession, cesa_ocf_newsession),
164 DEVMETHOD(cryptodev_freesession,cesa_ocf_freesession),
165 DEVMETHOD(cryptodev_process, cesa_ocf_process),
166 DEVMETHOD(cryptodev_kprocess, NULL),
167 };
168
169
170
171 /* Add debug Trace */
172 #undef CESA_OCF_TRACE_DEBUG
173 #ifdef CESA_OCF_TRACE_DEBUG
174
175 #define MV_CESA_USE_TIMER_ID 0
176
177 typedef struct
178 {
179 int type; /* 0 - isrEmpty, 1 - cesaReadyGet, 2 - cesaAction */
180 MV_U32 timeStamp;
181 MV_U32 cause;
182 MV_U32 realCause;
183 MV_U32 dmaCause;
184 int resources;
185 MV_CESA_REQ* pReqReady;
186 MV_CESA_REQ* pReqEmpty;
187 MV_CESA_REQ* pReqProcess;
188 } MV_CESA_TEST_TRACE;
189
190 #define MV_CESA_TEST_TRACE_SIZE 50
191
192 static int cesaTestTraceIdx = 0;
193 static MV_CESA_TEST_TRACE cesaTestTrace[MV_CESA_TEST_TRACE_SIZE];
194
195 static void cesaTestTraceAdd(int type)
196 {
197 cesaTestTrace[cesaTestTraceIdx].type = type;
198 cesaTestTrace[cesaTestTraceIdx].realCause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG);
199 //cesaTestTrace[cesaTestTraceIdx].idmaCause = MV_REG_READ(IDMA_CAUSE_REG);
200 cesaTestTrace[cesaTestTraceIdx].resources = cesaReqResources;
201 cesaTestTrace[cesaTestTraceIdx].pReqReady = pCesaReqReady;
202 cesaTestTrace[cesaTestTraceIdx].pReqEmpty = pCesaReqEmpty;
203 cesaTestTrace[cesaTestTraceIdx].pReqProcess = pCesaReqProcess;
204 cesaTestTrace[cesaTestTraceIdx].timeStamp = mvCntmrRead(MV_CESA_USE_TIMER_ID);
205 cesaTestTraceIdx++;
206 if(cesaTestTraceIdx == MV_CESA_TEST_TRACE_SIZE)
207 cesaTestTraceIdx = 0;
208 }
209
210 #else /* CESA_OCF_TRACE_DEBUG */
211
212 #define cesaTestTraceAdd(x)
213
214 #endif /* CESA_OCF_TRACE_DEBUG */
215
216 unsigned int
217 get_usec(unsigned int start)
218 {
219 if(start) {
220 do_gettimeofday (&tt_start);
221 return 0;
222 }
223 else {
224 do_gettimeofday (&tt_end);
225 tt_end.tv_sec -= tt_start.tv_sec;
226 tt_end.tv_usec -= tt_start.tv_usec;
227 if (tt_end.tv_usec < 0) {
228 tt_end.tv_usec += 1000 * 1000;
229 tt_end.tv_sec -= 1;
230 }
231 }
232 printk("time taken is %d\n", (unsigned int)(tt_end.tv_usec + tt_end.tv_sec * 1000000));
233 return (tt_end.tv_usec + tt_end.tv_sec * 1000000);
234 }
235
236 #ifdef RT_DEBUG
237 /*
238 * check that the crp action match the current session
239 */
240 static int
241 ocf_check_action(struct cryptop *crp, struct cesa_ocf_data *cesa_ocf_cur_ses) {
242 int count = 0;
243 int encrypt = 0, decrypt = 0, auth = 0;
244 struct cryptodesc *crd;
245
246 /* Go through crypto descriptors, processing as we go */
247 for (crd = crp->crp_desc; crd; crd = crd->crd_next, count++) {
248 if(count > 2) {
249 printk("%s,%d: session mode is not supported.\n", __FILE__, __LINE__);
250 return 1;
251 }
252
253 /* Encryption /Decryption */
254 if(crd->crd_alg == cesa_ocf_cur_ses->cipher_alg) {
255 /* check that the action is compatible with session */
256 if(encrypt || decrypt) {
257 printk("%s,%d: session mode is not supported.\n", __FILE__, __LINE__);
258 return 1;
259 }
260
261 if(crd->crd_flags & CRD_F_ENCRYPT) { /* encrypt */
262 if( (count == 2) && (cesa_ocf_cur_ses->encrypt_tn_auth) ) {
263 printk("%s,%d: sequence isn't supported by this session.\n", __FILE__, __LINE__);
264 return 1;
265 }
266 encrypt++;
267 }
268 else { /* decrypt */
269 if( (count == 2) && !(cesa_ocf_cur_ses->auth_tn_decrypt) ) {
270 printk("%s,%d: sequence isn't supported by this session.\n", __FILE__, __LINE__);
271 return 1;
272 }
273 decrypt++;
274 }
275
276 }
277 /* Authentication */
278 else if(crd->crd_alg == cesa_ocf_cur_ses->auth_alg) {
279 /* check that the action is compatible with session */
280 if(auth) {
281 printk("%s,%d: session mode is not supported.\n", __FILE__, __LINE__);
282 return 1;
283 }
284 if( (count == 2) && (decrypt) && (cesa_ocf_cur_ses->auth_tn_decrypt)) {
285 printk("%s,%d: sequence isn't supported by this session.\n", __FILE__, __LINE__);
286 return 1;
287 }
288 if( (count == 2) && (encrypt) && !(cesa_ocf_cur_ses->encrypt_tn_auth)) {
289 printk("%s,%d: sequence isn't supported by this session.\n", __FILE__, __LINE__);
290 return 1;
291 }
292 auth++;
293 }
294 else {
295 printk("%s,%d: Alg isn't supported by this session.\n", __FILE__, __LINE__);
296 return 1;
297 }
298 }
299 return 0;
300
301 }
302 #endif
303
304 /*
305 * Process a request.
306 */
307 static int
308 cesa_ocf_process(device_t dev, struct cryptop *crp, int hint)
309 {
310 struct cesa_ocf_process *cesa_ocf_cmd = NULL;
311 struct cesa_ocf_process *cesa_ocf_cmd_wa = NULL;
312 MV_CESA_COMMAND *cesa_cmd;
313 struct cryptodesc *crd;
314 struct cesa_ocf_data *cesa_ocf_cur_ses;
315 int sid = 0, temp_len = 0, i;
316 int encrypt = 0, decrypt = 0, auth = 0;
317 int status;
318 struct sk_buff *skb = NULL;
319 struct uio *uiop = NULL;
320 unsigned char *ivp;
321 MV_BUF_INFO *p_buf_info;
322 MV_CESA_MBUF *p_mbuf_info;
323 unsigned long flags;
324
325 dprintk("%s()\n", __FUNCTION__);
326
327 if( cesaReqResources <= 1 ) {
328 dprintk("%s,%d: ERESTART\n", __FILE__, __LINE__);
329 return ERESTART;
330 }
331
332 #ifdef RT_DEBUG
333 /* Sanity check */
334 if (crp == NULL) {
335 printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
336 return EINVAL;
337 }
338
339 if (crp->crp_desc == NULL || crp->crp_buf == NULL ) {
340 printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
341 crp->crp_etype = EINVAL;
342 return EINVAL;
343 }
344
345 sid = crp->crp_sid & 0xffffffff;
346 if ((sid >= CESA_OCF_MAX_SES) || (cesa_ocf_sessions[sid] == NULL)) {
347 crp->crp_etype = ENOENT;
348 printk("%s,%d: ENOENT session %d \n", __FILE__, __LINE__, sid);
349 return EINVAL;
350 }
351 #endif
352
353 sid = crp->crp_sid & 0xffffffff;
354 crp->crp_etype = 0;
355 cesa_ocf_cur_ses = cesa_ocf_sessions[sid];
356
357 #ifdef RT_DEBUG
358 if(ocf_check_action(crp, cesa_ocf_cur_ses)){
359 goto p_error;
360 }
361 #endif
362
363 /* malloc a new cesa process */
364 cesa_ocf_cmd = kmalloc(sizeof(struct cesa_ocf_process), GFP_ATOMIC);
365
366 if (cesa_ocf_cmd == NULL) {
367 printk("%s,%d: ENOBUFS \n", __FILE__, __LINE__);
368 goto p_error;
369 }
370 memset(cesa_ocf_cmd, 0, sizeof(struct cesa_ocf_process));
371
372 /* init cesa_process */
373 cesa_ocf_cmd->crp = crp;
374 /* always call callback */
375 cesa_ocf_cmd->need_cb = 1;
376
377 /* init cesa_cmd for usage of the HALs */
378 cesa_cmd = &cesa_ocf_cmd->cesa_cmd;
379 cesa_cmd->pReqPrv = (void *)cesa_ocf_cmd;
380 cesa_cmd->sessionId = cesa_ocf_cur_ses->sid_encrypt; /* defualt use encrypt */
381
382 /* prepare src buffer */
383 /* we send the entire buffer to the HAL, even if only part of it should be encrypt/auth. */
384 /* if not using seesions for both encrypt and auth, then it will be wiser to to copy only */
385 /* from skip to crd_len. */
386 p_buf_info = cesa_ocf_cmd->cesa_bufs;
387 p_mbuf_info = &cesa_ocf_cmd->cesa_mbuf;
388
389 p_buf_info += 2; /* save 2 first buffers for IV and digest -
390 we won't append them to the end since, they
391 might be places in an unaligned addresses. */
392
393 p_mbuf_info->pFrags = p_buf_info;
394 temp_len = 0;
395
396 /* handle SKB */
397 if (crp->crp_flags & CRYPTO_F_SKBUF) {
398
399 dprintk("%s,%d: handle SKB.\n", __FILE__, __LINE__);
400 skb = (struct sk_buff *) crp->crp_buf;
401
402 if (skb_shinfo(skb)->nr_frags >= (MV_CESA_MAX_MBUF_FRAGS - 1)) {
403 printk("%s,%d: %d nr_frags > MV_CESA_MAX_MBUF_FRAGS", __FILE__, __LINE__, skb_shinfo(skb)->nr_frags);
404 goto p_error;
405 }
406
407 p_mbuf_info->mbufSize = skb->len;
408 temp_len = skb->len;
409 /* first skb fragment */
410 p_buf_info->bufSize = skb_headlen(skb);
411 p_buf_info->bufVirtPtr = skb->data;
412 p_buf_info++;
413
414 /* now handle all other skb fragments */
415 for ( i = 0; i < skb_shinfo(skb)->nr_frags; i++ ) {
416 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
417 p_buf_info->bufSize = frag->size;
418 p_buf_info->bufVirtPtr = page_address(frag->page) + frag->page_offset;
419 p_buf_info++;
420 }
421 p_mbuf_info->numFrags = skb_shinfo(skb)->nr_frags + 1;
422 }
423 /* handle UIO */
424 else if(crp->crp_flags & CRYPTO_F_IOV) {
425
426 dprintk("%s,%d: handle UIO.\n", __FILE__, __LINE__);
427 uiop = (struct uio *) crp->crp_buf;
428
429 if (uiop->uio_iovcnt > (MV_CESA_MAX_MBUF_FRAGS - 1)) {
430 printk("%s,%d: %d uio_iovcnt > MV_CESA_MAX_MBUF_FRAGS \n", __FILE__, __LINE__, uiop->uio_iovcnt);
431 goto p_error;
432 }
433
434 p_mbuf_info->mbufSize = crp->crp_ilen;
435 p_mbuf_info->numFrags = uiop->uio_iovcnt;
436 for(i = 0; i < uiop->uio_iovcnt; i++) {
437 p_buf_info->bufVirtPtr = uiop->uio_iov[i].iov_base;
438 p_buf_info->bufSize = uiop->uio_iov[i].iov_len;
439 temp_len += p_buf_info->bufSize;
440 dprintk("%s,%d: buf %x-> addr %x, size %x \n"
441 , __FILE__, __LINE__, i, (unsigned int)p_buf_info->bufVirtPtr, p_buf_info->bufSize);
442 p_buf_info++;
443 }
444
445 }
446 /* handle CONTIG */
447 else {
448 dprintk("%s,%d: handle CONTIG.\n", __FILE__, __LINE__);
449 p_mbuf_info->numFrags = 1;
450 p_mbuf_info->mbufSize = crp->crp_ilen;
451 p_buf_info->bufVirtPtr = crp->crp_buf;
452 p_buf_info->bufSize = crp->crp_ilen;
453 temp_len = crp->crp_ilen;
454 p_buf_info++;
455 }
456
457 /* Support up to 64K why? cause! */
458 if(crp->crp_ilen > 64*1024) {
459 printk("%s,%d: buf too big %x \n", __FILE__, __LINE__, crp->crp_ilen);
460 goto p_error;
461 }
462
463 if( temp_len != crp->crp_ilen ) {
464 printk("%s,%d: warning size don't match.(%x %x) \n", __FILE__, __LINE__, temp_len, crp->crp_ilen);
465 }
466
467 cesa_cmd->pSrc = p_mbuf_info;
468 cesa_cmd->pDst = p_mbuf_info;
469
470 /* restore p_buf_info to point to first available buf */
471 p_buf_info = cesa_ocf_cmd->cesa_bufs;
472 p_buf_info += 1;
473
474
475 /* Go through crypto descriptors, processing as we go */
476 for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
477
478 /* Encryption /Decryption */
479 if(crd->crd_alg == cesa_ocf_cur_ses->cipher_alg) {
480
481 dprintk("%s,%d: cipher", __FILE__, __LINE__);
482
483 cesa_cmd->cryptoOffset = crd->crd_skip;
484 cesa_cmd->cryptoLength = crd->crd_len;
485
486 if(crd->crd_flags & CRD_F_ENCRYPT) { /* encrypt */
487 dprintk(" encrypt \n");
488 encrypt++;
489
490 /* handle IV */
491 if (crd->crd_flags & CRD_F_IV_EXPLICIT) { /* IV from USER */
492 dprintk("%s,%d: IV from USER (offset %x) \n", __FILE__, __LINE__, crd->crd_inject);
493 cesa_cmd->ivFromUser = 1;
494 ivp = crd->crd_iv;
495
496 /*
497 * do we have to copy the IV back to the buffer ?
498 */
499 if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
500 dprintk("%s,%d: copy the IV back to the buffer\n", __FILE__, __LINE__);
501 cesa_cmd->ivOffset = crd->crd_inject;
502 crypto_copyback(crp->crp_flags, crp->crp_buf, crd->crd_inject, cesa_ocf_cur_ses->ivlen, ivp);
503 }
504 else {
505 dprintk("%s,%d: don't copy the IV back to the buffer \n", __FILE__, __LINE__);
506 p_mbuf_info->numFrags++;
507 p_mbuf_info->mbufSize += cesa_ocf_cur_ses->ivlen;
508 p_mbuf_info->pFrags = p_buf_info;
509
510 p_buf_info->bufVirtPtr = ivp;
511 p_buf_info->bufSize = cesa_ocf_cur_ses->ivlen;
512 p_buf_info--;
513
514 /* offsets */
515 cesa_cmd->ivOffset = 0;
516 cesa_cmd->cryptoOffset += cesa_ocf_cur_ses->ivlen;
517 if(auth) {
518 cesa_cmd->macOffset += cesa_ocf_cur_ses->ivlen;
519 cesa_cmd->digestOffset += cesa_ocf_cur_ses->ivlen;
520 }
521 }
522 }
523 else { /* random IV */
524 dprintk("%s,%d: random IV \n", __FILE__, __LINE__);
525 cesa_cmd->ivFromUser = 0;
526
527 /*
528 * do we have to copy the IV back to the buffer ?
529 */
530 /* in this mode the HAL will always copy the IV */
531 /* given by the session to the ivOffset */
532 if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
533 cesa_cmd->ivOffset = crd->crd_inject;
534 }
535 else {
536 /* if IV isn't copy, then how will the user know which IV did we use??? */
537 printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
538 goto p_error;
539 }
540 }
541 }
542 else { /* decrypt */
543 dprintk(" decrypt \n");
544 decrypt++;
545 cesa_cmd->sessionId = cesa_ocf_cur_ses->sid_decrypt;
546
547 /* handle IV */
548 if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
549 dprintk("%s,%d: IV from USER \n", __FILE__, __LINE__);
550 /* append the IV buf to the mbuf */
551 cesa_cmd->ivFromUser = 1;
552 p_mbuf_info->numFrags++;
553 p_mbuf_info->mbufSize += cesa_ocf_cur_ses->ivlen;
554 p_mbuf_info->pFrags = p_buf_info;
555
556 p_buf_info->bufVirtPtr = crd->crd_iv;
557 p_buf_info->bufSize = cesa_ocf_cur_ses->ivlen;
558 p_buf_info--;
559
560 /* offsets */
561 cesa_cmd->ivOffset = 0;
562 cesa_cmd->cryptoOffset += cesa_ocf_cur_ses->ivlen;
563 if(auth) {
564 cesa_cmd->macOffset += cesa_ocf_cur_ses->ivlen;
565 cesa_cmd->digestOffset += cesa_ocf_cur_ses->ivlen;
566 }
567 }
568 else {
569 dprintk("%s,%d: IV inside the buffer \n", __FILE__, __LINE__);
570 cesa_cmd->ivFromUser = 0;
571 cesa_cmd->ivOffset = crd->crd_inject;
572 }
573 }
574
575 }
576 /* Authentication */
577 else if(crd->crd_alg == cesa_ocf_cur_ses->auth_alg) {
578 dprintk("%s,%d: Authentication \n", __FILE__, __LINE__);
579 auth++;
580 cesa_cmd->macOffset = crd->crd_skip;
581 cesa_cmd->macLength = crd->crd_len;
582
583 /* digest + mac */
584 cesa_cmd->digestOffset = crd->crd_inject;
585 }
586 else {
587 printk("%s,%d: Alg isn't supported by this session.\n", __FILE__, __LINE__);
588 goto p_error;
589 }
590 }
591
592 dprintk("\n");
593 dprintk("%s,%d: Sending Action: \n", __FILE__, __LINE__);
594 dprintk("%s,%d: IV from user: %d. IV offset %x \n", __FILE__, __LINE__, cesa_cmd->ivFromUser, cesa_cmd->ivOffset);
595 dprintk("%s,%d: crypt offset %x len %x \n", __FILE__, __LINE__, cesa_cmd->cryptoOffset, cesa_cmd->cryptoLength);
596 dprintk("%s,%d: Auth offset %x len %x \n", __FILE__, __LINE__, cesa_cmd->macOffset, cesa_cmd->macLength);
597 dprintk("%s,%d: set digest in offset %x . \n", __FILE__, __LINE__, cesa_cmd->digestOffset);
598 if(debug) {
599 mvCesaDebugMbuf("SRC BUFFER", cesa_cmd->pSrc, 0, cesa_cmd->pSrc->mbufSize);
600 }
601
602
603 /* send action to HAL */
604 spin_lock_irqsave(&cesa_lock, flags);
605 status = mvCesaAction(cesa_cmd);
606 spin_unlock_irqrestore(&cesa_lock, flags);
607
608 /* action not allowed */
609 if(status == MV_NOT_ALLOWED) {
610 #ifdef CESA_OCF_SPLIT
611 /* if both encrypt and auth try to split */
612 if(auth && (encrypt || decrypt)) {
613 MV_CESA_COMMAND *cesa_cmd_wa;
614
615 /* malloc a new cesa process and init it */
616 cesa_ocf_cmd_wa = kmalloc(sizeof(struct cesa_ocf_process), GFP_ATOMIC);
617
618 if (cesa_ocf_cmd_wa == NULL) {
619 printk("%s,%d: ENOBUFS \n", __FILE__, __LINE__);
620 goto p_error;
621 }
622 memcpy(cesa_ocf_cmd_wa, cesa_ocf_cmd, sizeof(struct cesa_ocf_process));
623 cesa_cmd_wa = &cesa_ocf_cmd_wa->cesa_cmd;
624 cesa_cmd_wa->pReqPrv = (void *)cesa_ocf_cmd_wa;
625 cesa_ocf_cmd_wa->need_cb = 0;
626
627 /* break requests to two operation, first operation completion won't call callback */
628 if((decrypt) && (cesa_ocf_cur_ses->auth_tn_decrypt)) {
629 cesa_cmd_wa->sessionId = cesa_ocf_cur_ses->frag_wa_auth;
630 cesa_cmd->sessionId = cesa_ocf_cur_ses->frag_wa_decrypt;
631 }
632 else if((decrypt) && !(cesa_ocf_cur_ses->auth_tn_decrypt)) {
633 cesa_cmd_wa->sessionId = cesa_ocf_cur_ses->frag_wa_decrypt;
634 cesa_cmd->sessionId = cesa_ocf_cur_ses->frag_wa_auth;
635 }
636 else if((encrypt) && (cesa_ocf_cur_ses->encrypt_tn_auth)) {
637 cesa_cmd_wa->sessionId = cesa_ocf_cur_ses->frag_wa_encrypt;
638 cesa_cmd->sessionId = cesa_ocf_cur_ses->frag_wa_auth;
639 }
640 else if((encrypt) && !(cesa_ocf_cur_ses->encrypt_tn_auth)){
641 cesa_cmd_wa->sessionId = cesa_ocf_cur_ses->frag_wa_auth;
642 cesa_cmd->sessionId = cesa_ocf_cur_ses->frag_wa_encrypt;
643 }
644 else {
645 printk("%s,%d: Unsupporterd fragment wa mode \n", __FILE__, __LINE__);
646 goto p_error;
647 }
648
649 /* send the 2 actions to the HAL */
650 spin_lock_irqsave(&cesa_lock, flags);
651 status = mvCesaAction(cesa_cmd_wa);
652 spin_unlock_irqrestore(&cesa_lock, flags);
653
654 if((status != MV_NO_MORE) && (status != MV_OK)) {
655 printk("%s,%d: cesa action failed, status = 0x%x\n", __FILE__, __LINE__, status);
656 goto p_error;
657 }
658 spin_lock_irqsave(&cesa_lock, flags);
659 status = mvCesaAction(cesa_cmd);
660 spin_unlock_irqrestore(&cesa_lock, flags);
661
662 }
663 /* action not allowed and can't split */
664 else
665 #endif
666 {
667 goto p_error;
668 }
669 }
670
671 /* Hal Q is full, send again. This should never happen */
672 if(status == MV_NO_RESOURCE) {
673 printk("%s,%d: cesa no more resources \n", __FILE__, __LINE__);
674 if(cesa_ocf_cmd)
675 kfree(cesa_ocf_cmd);
676 if(cesa_ocf_cmd_wa)
677 kfree(cesa_ocf_cmd_wa);
678 return ERESTART;
679 }
680 else if((status != MV_NO_MORE) && (status != MV_OK)) {
681 printk("%s,%d: cesa action failed, status = 0x%x\n", __FILE__, __LINE__, status);
682 goto p_error;
683 }
684
685
686 #ifdef CESA_OCF_POLLING
687 cesa_interrupt_polling();
688 #endif
689 cesaTestTraceAdd(5);
690
691 return 0;
692 p_error:
693 crp->crp_etype = EINVAL;
694 if(cesa_ocf_cmd)
695 kfree(cesa_ocf_cmd);
696 if(cesa_ocf_cmd_wa)
697 kfree(cesa_ocf_cmd_wa);
698 return EINVAL;
699 }
700
701 /*
702 * cesa callback.
703 */
704 static void
705 cesa_callback(unsigned long dummy)
706 {
707 struct cesa_ocf_process *cesa_ocf_cmd = NULL;
708 struct cryptop *crp = NULL;
709 MV_CESA_RESULT result[MV_CESA_MAX_CHAN];
710 int res_idx = 0,i;
711 MV_STATUS status;
712
713 dprintk("%s()\n", __FUNCTION__);
714
715 #ifdef CESA_OCF_TASKLET
716 disable_irq(cesa_device.irq);
717 #endif
718 while(MV_TRUE) {
719
720 /* Get Ready requests */
721 spin_lock(&cesa_lock);
722 status = mvCesaReadyGet(&result[res_idx]);
723 spin_unlock(&cesa_lock);
724
725 cesaTestTraceAdd(2);
726
727 if(status != MV_OK) {
728 #ifdef CESA_OCF_POLLING
729 if(status == MV_BUSY) { /* Fragment */
730 cesa_interrupt_polling();
731 return;
732 }
733 #endif
734 break;
735 }
736 res_idx++;
737 break;
738 }
739
740 for(i = 0; i < res_idx; i++) {
741
742 if(!result[i].pReqPrv) {
743 printk("%s,%d: warning private is NULL\n", __FILE__, __LINE__);
744 break;
745 }
746
747 cesa_ocf_cmd = result[i].pReqPrv;
748 crp = cesa_ocf_cmd->crp;
749
750 // ignore HMAC error.
751 //if(result->retCode)
752 // crp->crp_etype = EIO;
753
754 #if defined(CESA_OCF_POLLING)
755 if(!cesa_ocf_cmd->need_cb){
756 cesa_interrupt_polling();
757 }
758 #endif
759 if(cesa_ocf_cmd->need_cb) {
760 if(debug) {
761 mvCesaDebugMbuf("DST BUFFER", cesa_ocf_cmd->cesa_cmd.pDst, 0, cesa_ocf_cmd->cesa_cmd.pDst->mbufSize);
762 }
763 crypto_done(crp);
764 }
765 kfree(cesa_ocf_cmd);
766 }
767 #ifdef CESA_OCF_TASKLET
768 enable_irq(cesa_device.irq);
769 #endif
770
771 cesaTestTraceAdd(3);
772
773 return;
774 }
775
776 #ifdef CESA_OCF_POLLING
777 static void
778 cesa_interrupt_polling(void)
779 {
780 u32 cause;
781
782 dprintk("%s()\n", __FUNCTION__);
783
784 /* Read cause register */
785 do {
786 cause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG);
787 cause &= MV_CESA_CAUSE_ACC_DMA_ALL_MASK;
788
789 } while (cause == 0);
790
791 /* clear interrupts */
792 MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG, 0);
793
794 cesa_callback(0);
795
796 return;
797 }
798
799 #endif
800
801 /*
802 * cesa Interrupt polling routine.
803 */
804 static irqreturn_t
805 cesa_interrupt_handler(int irq, void *arg)
806 {
807 u32 cause;
808
809 dprintk("%s()\n", __FUNCTION__);
810
811 cesaTestTraceAdd(0);
812
813 /* Read cause register */
814 cause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG);
815
816 if( (cause & MV_CESA_CAUSE_ACC_DMA_ALL_MASK) == 0)
817 {
818 /* Empty interrupt */
819 dprintk("%s,%d: cesaTestReadyIsr: cause=0x%x\n", __FILE__, __LINE__, cause);
820 return IRQ_HANDLED;
821 }
822
823 /* clear interrupts */
824 MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG, 0);
825
826 cesaTestTraceAdd(1);
827 #ifdef CESA_OCF_TASKLET
828 tasklet_hi_schedule(&cesa_ocf_tasklet);
829 #else
830 cesa_callback(0);
831 #endif
832 return IRQ_HANDLED;
833 }
834
835 /*
836 * Open a session.
837 */
838 static int
839 /*cesa_ocf_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)*/
840 cesa_ocf_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
841 {
842 u32 status = 0, i;
843 u32 count = 0, auth = 0, encrypt =0;
844 struct cesa_ocf_data *cesa_ocf_cur_ses;
845 MV_CESA_OPEN_SESSION cesa_session;
846 MV_CESA_OPEN_SESSION *cesa_ses = &cesa_session;
847
848
849 dprintk("%s()\n", __FUNCTION__);
850 if (sid == NULL || cri == NULL) {
851 printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
852 return EINVAL;
853 }
854
855 /* leave first empty like in other implementations */
856 for (i = 1; i < CESA_OCF_MAX_SES; i++) {
857 if (cesa_ocf_sessions[i] == NULL)
858 break;
859 }
860
861 if(i >= CESA_OCF_MAX_SES) {
862 printk("%s,%d: no more sessions \n", __FILE__, __LINE__);
863 return EINVAL;
864 }
865
866 cesa_ocf_sessions[i] = (struct cesa_ocf_data *) kmalloc(sizeof(struct cesa_ocf_data), GFP_ATOMIC);
867 if (cesa_ocf_sessions[i] == NULL) {
868 cesa_ocf_freesession(NULL, i);
869 printk("%s,%d: ENOBUFS \n", __FILE__, __LINE__);
870 return ENOBUFS;
871 }
872 dprintk("%s,%d: new session %d \n", __FILE__, __LINE__, i);
873
874 *sid = i;
875 cesa_ocf_cur_ses = cesa_ocf_sessions[i];
876 memset(cesa_ocf_cur_ses, 0, sizeof(struct cesa_ocf_data));
877 cesa_ocf_cur_ses->sid_encrypt = -1;
878 cesa_ocf_cur_ses->sid_decrypt = -1;
879 cesa_ocf_cur_ses->frag_wa_encrypt = -1;
880 cesa_ocf_cur_ses->frag_wa_decrypt = -1;
881 cesa_ocf_cur_ses->frag_wa_auth = -1;
882
883 /* init the session */
884 memset(cesa_ses, 0, sizeof(MV_CESA_OPEN_SESSION));
885 count = 1;
886 while (cri) {
887 if(count > 2) {
888 printk("%s,%d: don't support more then 2 operations\n", __FILE__, __LINE__);
889 goto error;
890 }
891 switch (cri->cri_alg) {
892 case CRYPTO_AES_CBC:
893 dprintk("%s,%d: (%d) AES CBC \n", __FILE__, __LINE__, count);
894 cesa_ocf_cur_ses->cipher_alg = cri->cri_alg;
895 cesa_ocf_cur_ses->ivlen = MV_CESA_AES_BLOCK_SIZE;
896 cesa_ses->cryptoAlgorithm = MV_CESA_CRYPTO_AES;
897 cesa_ses->cryptoMode = MV_CESA_CRYPTO_CBC;
898 if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
899 printk("%s,%d: CRYPTO key too long.\n", __FILE__, __LINE__);
900 goto error;
901 }
902 memcpy(cesa_ses->cryptoKey, cri->cri_key, cri->cri_klen/8);
903 dprintk("%s,%d: key length %d \n", __FILE__, __LINE__, cri->cri_klen/8);
904 cesa_ses->cryptoKeyLength = cri->cri_klen/8;
905 encrypt += count;
906 break;
907 case CRYPTO_3DES_CBC:
908 dprintk("%s,%d: (%d) 3DES CBC \n", __FILE__, __LINE__, count);
909 cesa_ocf_cur_ses->cipher_alg = cri->cri_alg;
910 cesa_ocf_cur_ses->ivlen = MV_CESA_3DES_BLOCK_SIZE;
911 cesa_ses->cryptoAlgorithm = MV_CESA_CRYPTO_3DES;
912 cesa_ses->cryptoMode = MV_CESA_CRYPTO_CBC;
913 if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
914 printk("%s,%d: CRYPTO key too long.\n", __FILE__, __LINE__);
915 goto error;
916 }
917 memcpy(cesa_ses->cryptoKey, cri->cri_key, cri->cri_klen/8);
918 cesa_ses->cryptoKeyLength = cri->cri_klen/8;
919 encrypt += count;
920 break;
921 case CRYPTO_DES_CBC:
922 dprintk("%s,%d: (%d) DES CBC \n", __FILE__, __LINE__, count);
923 cesa_ocf_cur_ses->cipher_alg = cri->cri_alg;
924 cesa_ocf_cur_ses->ivlen = MV_CESA_DES_BLOCK_SIZE;
925 cesa_ses->cryptoAlgorithm = MV_CESA_CRYPTO_DES;
926 cesa_ses->cryptoMode = MV_CESA_CRYPTO_CBC;
927 if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
928 printk("%s,%d: CRYPTO key too long.\n", __FILE__, __LINE__);
929 goto error;
930 }
931 memcpy(cesa_ses->cryptoKey, cri->cri_key, cri->cri_klen/8);
932 cesa_ses->cryptoKeyLength = cri->cri_klen/8;
933 encrypt += count;
934 break;
935 case CRYPTO_MD5:
936 case CRYPTO_MD5_HMAC:
937 dprintk("%s,%d: (%d) %sMD5 CBC \n", __FILE__, __LINE__, count, (cri->cri_alg != CRYPTO_MD5)? "H-":" ");
938 cesa_ocf_cur_ses->auth_alg = cri->cri_alg;
939 cesa_ocf_cur_ses->digestlen = (cri->cri_alg == CRYPTO_MD5)? MV_CESA_MD5_DIGEST_SIZE : 12;
940 cesa_ses->macMode = (cri->cri_alg == CRYPTO_MD5)? MV_CESA_MAC_MD5 : MV_CESA_MAC_HMAC_MD5;
941 if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
942 printk("%s,%d: MAC key too long. \n", __FILE__, __LINE__);
943 goto error;
944 }
945 cesa_ses->macKeyLength = cri->cri_klen/8;
946 memcpy(cesa_ses->macKey, cri->cri_key, cri->cri_klen/8);
947 cesa_ses->digestSize = cesa_ocf_cur_ses->digestlen;
948 auth += count;
949 break;
950 case CRYPTO_SHA1:
951 case CRYPTO_SHA1_HMAC:
952 dprintk("%s,%d: (%d) %sSHA1 CBC \n", __FILE__, __LINE__, count, (cri->cri_alg != CRYPTO_SHA1)? "H-":" ");
953 cesa_ocf_cur_ses->auth_alg = cri->cri_alg;
954 cesa_ocf_cur_ses->digestlen = (cri->cri_alg == CRYPTO_SHA1)? MV_CESA_SHA1_DIGEST_SIZE : 12;
955 cesa_ses->macMode = (cri->cri_alg == CRYPTO_SHA1)? MV_CESA_MAC_SHA1 : MV_CESA_MAC_HMAC_SHA1;
956 if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
957 printk("%s,%d: MAC key too long. \n", __FILE__, __LINE__);
958 goto error;
959 }
960 cesa_ses->macKeyLength = cri->cri_klen/8;
961 memcpy(cesa_ses->macKey, cri->cri_key, cri->cri_klen/8);
962 cesa_ses->digestSize = cesa_ocf_cur_ses->digestlen;
963 auth += count;
964 break;
965 default:
966 printk("%s,%d: unknown algo 0x%x\n", __FILE__, __LINE__, cri->cri_alg);
967 goto error;
968 }
969 cri = cri->cri_next;
970 count++;
971 }
972
973 if((encrypt > 2) || (auth > 2)) {
974 printk("%s,%d: session mode is not supported.\n", __FILE__, __LINE__);
975 goto error;
976 }
977 /* create new sessions in HAL */
978 if(encrypt) {
979 cesa_ses->operation = MV_CESA_CRYPTO_ONLY;
980 /* encrypt session */
981 if(auth == 1) {
982 cesa_ses->operation = MV_CESA_MAC_THEN_CRYPTO;
983 }
984 else if(auth == 2) {
985 cesa_ses->operation = MV_CESA_CRYPTO_THEN_MAC;
986 cesa_ocf_cur_ses->encrypt_tn_auth = 1;
987 }
988 else {
989 cesa_ses->operation = MV_CESA_CRYPTO_ONLY;
990 }
991 cesa_ses->direction = MV_CESA_DIR_ENCODE;
992 status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->sid_encrypt);
993 if(status != MV_OK) {
994 printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
995 goto error;
996 }
997 /* decrypt session */
998 if( cesa_ses->operation == MV_CESA_MAC_THEN_CRYPTO ) {
999 cesa_ses->operation = MV_CESA_CRYPTO_THEN_MAC;
1000 }
1001 else if( cesa_ses->operation == MV_CESA_CRYPTO_THEN_MAC ) {
1002 cesa_ses->operation = MV_CESA_MAC_THEN_CRYPTO;
1003 }
1004 cesa_ses->direction = MV_CESA_DIR_DECODE;
1005 status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->sid_decrypt);
1006 if(status != MV_OK) {
1007 printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
1008 goto error;
1009 }
1010
1011 /* preapre one action sessions for case we will need to split an action */
1012 #ifdef CESA_OCF_SPLIT
1013 if(( cesa_ses->operation == MV_CESA_MAC_THEN_CRYPTO ) ||
1014 ( cesa_ses->operation == MV_CESA_CRYPTO_THEN_MAC )) {
1015 /* open one session for encode and one for decode */
1016 cesa_ses->operation = MV_CESA_CRYPTO_ONLY;
1017 cesa_ses->direction = MV_CESA_DIR_ENCODE;
1018 status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->frag_wa_encrypt);
1019 if(status != MV_OK) {
1020 printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
1021 goto error;
1022 }
1023
1024 cesa_ses->direction = MV_CESA_DIR_DECODE;
1025 status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->frag_wa_decrypt);
1026 if(status != MV_OK) {
1027 printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
1028 goto error;
1029 }
1030 /* open one session for auth */
1031 cesa_ses->operation = MV_CESA_MAC_ONLY;
1032 cesa_ses->direction = MV_CESA_DIR_ENCODE;
1033 status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->frag_wa_auth);
1034 if(status != MV_OK) {
1035 printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
1036 goto error;
1037 }
1038 }
1039 #endif
1040 }
1041 else { /* only auth */
1042 cesa_ses->operation = MV_CESA_MAC_ONLY;
1043 cesa_ses->direction = MV_CESA_DIR_ENCODE;
1044 status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->sid_encrypt);
1045 if(status != MV_OK) {
1046 printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
1047 goto error;
1048 }
1049 }
1050
1051 return 0;
1052 error:
1053 cesa_ocf_freesession(NULL, *sid);
1054 return EINVAL;
1055
1056 }
1057
1058
1059 /*
1060 * Free a session.
1061 */
1062 static int
1063 cesa_ocf_freesession(device_t dev, u_int64_t tid)
1064 {
1065 struct cesa_ocf_data *cesa_ocf_cur_ses;
1066 u_int32_t sid = CRYPTO_SESID2LID(tid);
1067 //unsigned long flags;
1068
1069 dprintk("%s() %d \n", __FUNCTION__, sid);
1070 if ( (sid >= CESA_OCF_MAX_SES) || (cesa_ocf_sessions[sid] == NULL) ) {
1071 printk("%s,%d: EINVAL can't free session %d \n", __FILE__, __LINE__, sid);
1072 return(EINVAL);
1073 }
1074
1075 /* Silently accept and return */
1076 if (sid == 0)
1077 return(0);
1078
1079 /* release session from HAL */
1080 cesa_ocf_cur_ses = cesa_ocf_sessions[sid];
1081 if (cesa_ocf_cur_ses->sid_encrypt != -1) {
1082 mvCesaSessionClose(cesa_ocf_cur_ses->sid_encrypt);
1083 }
1084 if (cesa_ocf_cur_ses->sid_decrypt != -1) {
1085 mvCesaSessionClose(cesa_ocf_cur_ses->sid_decrypt);
1086 }
1087 if (cesa_ocf_cur_ses->frag_wa_encrypt != -1) {
1088 mvCesaSessionClose(cesa_ocf_cur_ses->frag_wa_encrypt);
1089 }
1090 if (cesa_ocf_cur_ses->frag_wa_decrypt != -1) {
1091 mvCesaSessionClose(cesa_ocf_cur_ses->frag_wa_decrypt);
1092 }
1093 if (cesa_ocf_cur_ses->frag_wa_auth != -1) {
1094 mvCesaSessionClose(cesa_ocf_cur_ses->frag_wa_auth);
1095 }
1096
1097 kfree(cesa_ocf_cur_ses);
1098 cesa_ocf_sessions[sid] = NULL;
1099
1100 return 0;
1101 }
1102
1103
1104 /* TDMA Window setup */
1105
1106 static void __init
1107 setup_tdma_mbus_windows(struct cesa_dev *dev)
1108 {
1109 int i;
1110
1111 for (i = 0; i < 4; i++) {
1112 writel(0, dev->reg + WINDOW_BASE(i));
1113 writel(0, dev->reg + WINDOW_CTRL(i));
1114 }
1115
1116 for (i = 0; i < dev->plat_data->dram->num_cs; i++) {
1117 struct mbus_dram_window *cs = dev->plat_data->dram->cs + i;
1118 writel(
1119 ((cs->size - 1) & 0xffff0000) |
1120 (cs->mbus_attr << 8) |
1121 (dev->plat_data->dram->mbus_dram_target_id << 4) | 1,
1122 dev->reg + WINDOW_CTRL(i)
1123 );
1124 writel(cs->base, dev->reg + WINDOW_BASE(i));
1125 }
1126 }
1127
1128 /*
1129 * our driver startup and shutdown routines
1130 */
1131 static int
1132 mv_cesa_ocf_init(struct platform_device *pdev)
1133 {
1134 #if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
1135 if (MV_FALSE == mvSocUnitIsMappedToThisCpu(CESA))
1136 {
1137 dprintk("CESA is not mapped to this CPU\n");
1138 return -ENODEV;
1139 }
1140 #endif
1141
1142 dprintk("%s\n", __FUNCTION__);
1143 memset(&mv_cesa_dev, 0, sizeof(mv_cesa_dev));
1144 softc_device_init(&mv_cesa_dev, "MV CESA", 0, mv_cesa_methods);
1145 cesa_ocf_id = crypto_get_driverid(softc_get_device(&mv_cesa_dev),CRYPTOCAP_F_HARDWARE);
1146
1147 if (cesa_ocf_id < 0)
1148 panic("MV CESA crypto device cannot initialize!");
1149
1150 dprintk("%s,%d: cesa ocf device id is %d \n", __FILE__, __LINE__, cesa_ocf_id);
1151
1152 /* CESA unit is auto power on off */
1153 #if 0
1154 if (MV_FALSE == mvCtrlPwrClckGet(CESA_UNIT_ID,0))
1155 {
1156 printk("\nWarning CESA %d is Powered Off\n",0);
1157 return EINVAL;
1158 }
1159 #endif
1160
1161 memset(&cesa_device, 0, sizeof(struct cesa_dev));
1162 /* Get the IRQ, and crypto memory regions */
1163 {
1164 struct resource *res;
1165 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sram");
1166
1167 if (!res)
1168 return -ENXIO;
1169
1170 cesa_device.sram = ioremap(res->start, res->end - res->start + 1);
1171 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
1172
1173 if (!res) {
1174 iounmap(cesa_device.sram);
1175 return -ENXIO;
1176 }
1177 cesa_device.reg = ioremap(res->start, res->end - res->start + 1);
1178 cesa_device.irq = platform_get_irq(pdev, 0);
1179 cesa_device.plat_data = pdev->dev.platform_data;
1180 setup_tdma_mbus_windows(&cesa_device);
1181
1182 }
1183
1184
1185 if( MV_OK != mvCesaInit(CESA_OCF_MAX_SES*5, CESA_Q_SIZE, cesa_device.reg,
1186 NULL) ) {
1187 printk("%s,%d: mvCesaInit Failed. \n", __FILE__, __LINE__);
1188 return EINVAL;
1189 }
1190
1191 /* clear and unmask Int */
1192 MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
1193 #ifndef CESA_OCF_POLLING
1194 MV_REG_WRITE( MV_CESA_ISR_MASK_REG, MV_CESA_CAUSE_ACC_DMA_MASK);
1195 #endif
1196 #ifdef CESA_OCF_TASKLET
1197 tasklet_init(&cesa_ocf_tasklet, cesa_callback, (unsigned int) 0);
1198 #endif
1199 /* register interrupt */
1200 if( request_irq( cesa_device.irq, cesa_interrupt_handler,
1201 (IRQF_DISABLED) , "cesa", &cesa_ocf_id) < 0) {
1202 printk("%s,%d: cannot assign irq %x\n", __FILE__, __LINE__, cesa_device.reg);
1203 return EINVAL;
1204 }
1205
1206
1207 memset(cesa_ocf_sessions, 0, sizeof(struct cesa_ocf_data *) * CESA_OCF_MAX_SES);
1208
1209 #define REGISTER(alg) \
1210 crypto_register(cesa_ocf_id, alg, 0,0)
1211 REGISTER(CRYPTO_AES_CBC);
1212 REGISTER(CRYPTO_DES_CBC);
1213 REGISTER(CRYPTO_3DES_CBC);
1214 REGISTER(CRYPTO_MD5);
1215 REGISTER(CRYPTO_MD5_HMAC);
1216 REGISTER(CRYPTO_SHA1);
1217 REGISTER(CRYPTO_SHA1_HMAC);
1218 #undef REGISTER
1219
1220 return 0;
1221 }
1222
1223 static void
1224 mv_cesa_ocf_exit(struct platform_device *pdev)
1225 {
1226 dprintk("%s()\n", __FUNCTION__);
1227
1228 crypto_unregister_all(cesa_ocf_id);
1229 cesa_ocf_id = -1;
1230 iounmap(cesa_device.reg);
1231 iounmap(cesa_device.sram);
1232 free_irq(cesa_device.irq, NULL);
1233
1234 /* mask and clear Int */
1235 MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 0);
1236 MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
1237
1238
1239 if( MV_OK != mvCesaFinish() ) {
1240 printk("%s,%d: mvCesaFinish Failed. \n", __FILE__, __LINE__);
1241 return;
1242 }
1243 }
1244
1245
1246 void cesa_ocf_debug(void)
1247 {
1248
1249 #ifdef CESA_OCF_TRACE_DEBUG
1250 {
1251 int i, j;
1252 j = cesaTestTraceIdx;
1253 mvOsPrintf("No Type rCause iCause Proc Isr Res Time pReady pProc pEmpty\n");
1254 for(i=0; i<MV_CESA_TEST_TRACE_SIZE; i++)
1255 {
1256 mvOsPrintf("%02d. %d 0x%04x 0x%04x 0x%02x 0x%02x %02d 0x%06x %p %p %p\n",
1257 j, cesaTestTrace[j].type, cesaTestTrace[j].realCause,
1258 cesaTestTrace[j].idmaCause,
1259 cesaTestTrace[j].resources, cesaTestTrace[j].timeStamp,
1260 cesaTestTrace[j].pReqReady, cesaTestTrace[j].pReqProcess, cesaTestTrace[j].pReqEmpty);
1261 j++;
1262 if(j == MV_CESA_TEST_TRACE_SIZE)
1263 j = 0;
1264 }
1265 }
1266 #endif
1267
1268 }
1269
1270 static struct platform_driver marvell_cesa = {
1271 .probe = mv_cesa_ocf_init,
1272 .remove = mv_cesa_ocf_exit,
1273 .driver = {
1274 .owner = THIS_MODULE,
1275 .name = "mv_crypto",
1276 },
1277 };
1278
1279 MODULE_ALIAS("platform:mv_crypto");
1280
1281 static int __init mv_cesa_init(void)
1282 {
1283 return platform_driver_register(&marvell_cesa);
1284 }
1285
1286 module_init(mv_cesa_init);
1287
1288 static void __exit mv_cesa_exit(void)
1289 {
1290 platform_driver_unregister(&marvell_cesa);
1291 }
1292
1293 module_exit(mv_cesa_exit);
1294
1295 MODULE_LICENSE("GPL");
1296 MODULE_AUTHOR("Ronen Shitrit");
1297 MODULE_DESCRIPTION("OCF module for Orion CESA crypto");
This page took 0.136562 seconds and 5 git commands to generate.