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