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