1 #include <linux/config.h>
2 #include <linux/kernel.h>
3 #include <linux/sched.h>
4 #include <linux/types.h>
5 #include <linux/slab.h>
6 #include <linux/delay.h>
7 #include <asm/system.h>
8 #include <asm/io.h> // readl, writel
11 #include <asm/arch/irq.h>
12 #include <asm/arch/cpe/cpe.h> //All register definition
13 #include <asm/arch/cpe_int.h> //Interrupt definition
14 #include <asm/arch/cpe/a320c.h>
15 #include <asm-generic/errno-base.h>
17 #include "mxhw_crypto_engine.h"
19 /* memory and register information */
20 #define CPE_WMAC_BASE 0x90F00000 /* physical base address */
21 #define REGS_SIZE 0x90 /* physical area */
22 static void *base
=NULL
; /* base address of the io memory assigned to the engine */
23 #define REGWRL(off,v) writel(v,base+off)
24 #define REGRDL(off) readl(base+off)
26 #define PERFORM_WAIT_TIME 50
27 #define MAX_WAIT_TIMES 200
30 #define IRQ_WMAC 29 /* trq number */
31 wait_queue_head_t dmawq
; /* a waiting queue that the engine wakes up the dispatcher */
32 static u32 IRQ_INT_FLAG
=0;
37 read_registers(u32 a
, u32 b
)
39 if (a
==0 && b
==0) b
= REGS_SIZE
;
42 printk("\n-------------- addresses --------------%d\n", 0);
44 printk("0x%02x = 0x%08x\n", a
, REGRDL(a
));
45 printk("\n-------------- addresses --------------%d\n", 9);
49 #define read_registers(a,b)
53 mxhw_crypto_engine_dma_malloc(IOMBUF
*mbuf
, u32 size
)
55 IOMBUF_OFFS(mbuf
) = 0;
56 IOMBUF_SIZE(mbuf
) = size
; /* memory space for data */
58 IOMBUF_VIRT(mbuf) = consistent_alloc( GFP_DMA|GFP_KERNEL, size,
59 &(IOMBUF_PHYS(mbuf)));
62 IOMBUF_VIRT(mbuf
) = dma_alloc_coherent(NULL
, size
,&(IOMBUF_PHYS(mbuf
)), GFP_DMA
|GFP_KERNEL
);
65 if (IOMBUF_VIRT(mbuf
)==NULL
)
71 mxhw_crypto_engine_dma_mfree(IOMBUF
*mbuf
)
73 if (mbuf
&& IOMBUF_VIRT(mbuf
))
75 consistent_free((u32 *)IOMBUF_VIRT(mbuf), IOMBUF_SIZE(mbuf)+IOMBUF_OFFS(mbuf), IOMBUF_PHYS(mbuf));
78 dma_free_coherent(NULL
, IOMBUF_SIZE(mbuf
)+IOMBUF_OFFS(mbuf
),(u32
*)IOMBUF_VIRT(mbuf
),IOMBUF_PHYS(mbuf
));
82 typedef struct _CTXPARAM
90 static CTXPARAM CtxParams
[] =
92 {MXCIPHER_ALGO_DES
, _BIT_RW_MXCIPHER_ALGO_DES
, 8, 8},
93 {MXCIPHER_ALGO_3DES
, _BIT_RW_MXCIPHER_ALGO_3DES
, 8, 24},
94 {MXCIPHER_ALGO_AES128
, _BIT_RW_MXCIPHER_ALGO_AES128
, 16, 16},
95 {MXCIPHER_ALGO_AES192
, _BIT_RW_MXCIPHER_ALGO_AES192
, 16, 24},
96 {MXCIPHER_ALGO_AES256
, _BIT_RW_MXCIPHER_ALGO_AES256
, 16, 32}
99 static u32 CtxParams_Size
=(sizeof(CtxParams
)/sizeof(CtxParams
[0]));
102 #define SWAP32(v) ((v>>24)|((v&0x00ff0000)>>8)|((v&0x0000ff00)<<8)|(v<<24))
108 swap(u8
*data
, u32 len
)
112 for (i
=0; i
< len
; i
+=4, data
+= 4)
115 *(u32
*)data
= SWAP32(v
);
119 #define mswap32(data,l) \
121 u32 i, v, len=l>>2; \
122 u32 *d = (u32*) data; \
123 for (i=0; i < len; i++, d++) \
131 mxhw_crypto_engine_register(CIPHER
*info
, u32
*ctrl
)
135 if (info
->mode
==MXCIPHER_MODE_ECB
) *ctrl
= _BIT_RW_MXCIPHER_MODE_ECB
;
136 else if (info
->mode
==MXCIPHER_MODE_CBC
) *ctrl
= _BIT_RW_MXCIPHER_MODE_CBC
;
137 else if (info
->mode
==MXCIPHER_MODE_CTR
) *ctrl
= _BIT_RW_MXCIPHER_MODE_CTR
;
138 else if (info
->mode
==MXCIPHER_MODE_OFB
) *ctrl
= _BIT_RW_MXCIPHER_MODE_OFB
;
139 else if (info
->mode
==MXCIPHER_MODE_CFB
)
143 *ctrl
= _BIT_RW_MXCIPHER_MODE_CFB
;
148 *ctrl
|= (info
->type
==0)? _BIT_RW_MXCIPHER_TYPE_DEC
:_BIT_RW_MXCIPHER_TYPE_ENC
;
150 info
->blen
= info
->klen
= 0;
151 for (i
=0; i
< CtxParams_Size
;i
++)
153 if (info
->algo
==CtxParams
[i
].algo
)
155 info
->blen
= CtxParams
[i
].blen
;
156 info
->klen
= CtxParams
[i
].klen
;
157 *ctrl
|= CtxParams
[i
].ctrl
;
158 swap(info
->keys
, info
->klen
);
166 mxhw_crypto_engine_unregister(u32 ctrl
)
171 #define IRQ_LEVEL LEVEL
172 #define IRQ_ACTIVE L_ACTIVE
173 #define INTRPT_ENBL_BIT 1
174 #define INTRPT_DSBL_BIT 0
177 1. IOMBUF_DLEN(imbuf) covers the IV if there is
178 2. remember to set IOMBUF_DLEN(ombuf) = IOMBUF_DLEN(imbuf)
181 mxhw_crypto_engine_perform(u32 ctrl
, CIPHER
*info
, IOMBUF
*imbuf
, IOMBUF
*ombuf
, u32
*exited
)
188 if (info
->mode
!=MXCIPHER_MODE_ECB
)
189 dlen
= IOMBUF_DLEN(imbuf
)-info
->blen
;
192 dlen
= IOMBUF_DLEN(imbuf
);
193 if (info
->mode
!=MXCIPHER_MODE_CFB
&& dlen
%info
->blen
)
197 DBG(KERN_INFO
"mxhw_engine: engine_perform = %d %d 0x%x\n", 11, info
->type
, ctrl
);
199 /* step 0: disable all interrupts: stop, err, done */
200 REGWRL(_REG_WO_INTRPT_CLEAR
, 1);
202 /* step 1: set cipher control */
203 REGWRL(_REG_RW_MXCIPHER_CTRL
, ctrl
);
205 /* step 2: set IVs if there are, 4 bytes each */
206 if (info
->mode
!=MXCIPHER_MODE_ECB
)
208 dlen
= IOMBUF_DLEN(imbuf
)-info
->blen
;
209 ivec
= IOMBUF_DATA(imbuf
)+dlen
;
210 for (i
=0,offs
=_REG_RW_MXCIPHER_IVIN0
; i
< info
->blen
; i
+=4, offs
+=4)
212 tmpv
= *(u32
*)(ivec
+i
);
218 /* step 3: set keys, 4 bytes each, swap already */
219 for (i
=0,offs
=_REG_RW_MXCIPHER_KEY0
; i
< info
->klen
; i
+=4, offs
+=4)
220 REGWRL(offs
,*(u32
*)(info
->keys
+i
));
222 /* step 4: set DMA controls */
223 REGWRL( _REG_RW_DMA_ADDR_SURC
, IOMBUF_PHYS(imbuf
));
224 REGWRL( _REG_RW_DMA_ADDR_DEST
, IOMBUF_PHYS(ombuf
));
225 REGWRL( _REG_RW_DMA_DATA_SIZE
, dlen
);
227 /* step 5: enable transfer done */
228 REGWRL(_REG_RW_INTRPT_ENBL
, INTRPT_ENBL_BIT
);
230 DBG(KERN_INFO
"mxhw_engine: engine_perform = %d\n", 66);
232 /* step 6: enable DMA engine */
233 REGWRL(_REG_RW_DMA_ENGN_CTRL
, _BIT_RW_DMA_ENGN_ENBL
);
234 //read_registers(_REG_RW_DMA_ENGN_CTRL,0x70);
236 /* step 7: wait for data of the size is transferred. if it waits for
237 a stop at DMA, the data might not be completely transferred */
239 DBG(KERN_INFO
"mxhw_engine: interrupt = %d %d\n", 77, dlen
);
241 wait_event_interruptible(&dmawq
, (REGRDL(_REG_RO_INTRPT_POST
)&_BIT_RO_INTRPT_DONE
)!=0);
243 while(IRQ_INT_FLAG
==0 && num
++ < MAX_WAIT_TIMES
)
245 udelay(PERFORM_WAIT_TIME
); // current->state = TASK_INTERRUPTIBLE; schedule_timeout(HZ);
253 DBG(KERN_INFO
"mxhw_engine: poll =%d %d\n", 77, dlen
);
255 while(num
++ < MAX_WAIT_TIMES
)
257 udelay(PERFORM_WAIT_TIME
);
258 if ((REGRDL(_REG_RO_INTRPT_POST
)&_BIT_RO_INTRPT_DONE
)!=0)
262 /* set output length */
263 IOMBUF_DLEN(ombuf
) = IOMBUF_DLEN(imbuf
);
265 if (num
>= MAX_WAIT_TIMES
)
267 printk("mxhw_engine: timeout!! data length= %d\n",dlen
);
271 /* step 8: get IVs if there are, 4 bytes each */
272 if (info
->mode
!= MXCIPHER_MODE_ECB
)
274 ivec
= IOMBUF_DATA(ombuf
)+dlen
;
275 for (i
=0,offs
=_REG_RO_MXCIPHER_IVOUT0
; i
< info
->blen
; i
+=4, offs
+=4)
278 *(u32
*)(ivec
+i
) = SWAP32(tmpv
);
285 /* hw interrupt notifies a complete of packet,
286 this interrupt handler represents no process, so can't sleep,
287 no kmalloc, current->pid, copy_from_user, ..., and etc
290 mxhw_crypto_engine_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs_base
)
292 // printk(KERN_INFO "mxhw_crypto_engine_interrupt irq = %d\n", irq);
294 /* check if it is what the engine says */
295 if (IRQ_INT_FLAG
==0 && (REGRDL(_REG_RO_INTRPT_POST
)&_BIT_RO_INTRPT_DONE
)!=0)
297 wake_up_interruptible(&dmawq
);
298 REGWRL(_REG_WO_INTRPT_CLEAR
, 1);
305 mxhw_crypto_engine_up(void)
307 /* get the base mapping address to the engine */
308 if ((base
=(void*)ioremap_nocache(CPE_WMAC_BASE
, REGS_SIZE
))==NULL
)
310 printk("Fail to io map\n");
313 memset_io(base
, 0, REGS_SIZE
);
315 /* set initial FIFO configuration for the crypto engine */
316 REGWRL(_REG_RW_IOFIFO_THRD
, 0x101);
319 /* set up interrupt mechanism */
320 cpe_int_set_irq(IRQ_WMAC
, LEVEL
, H_ACTIVE
);
321 if (request_irq(IRQ_WMAC
, (void*) mxhw_crypto_engine_interrupt
, SA_INTERRUPT
,
322 "mxcrypto", NULL
)!=0)
323 { /* it return -EBUSY */
324 printk("Some other device may take this line of IRQ\n");
327 /* bring up the waiting queue for engine and the dispatcher */
328 init_waitqueue_head(&dmawq
);
329 printk("setup IRQ\n");
335 mxhw_crypto_engine_down(void)
337 REGWRL(_REG_RW_DMA_ENGN_CTRL
,_BIT_RW_DMA_ENGN_DSBL
);
339 /* the thread might sleep on waiting for DMA */
340 wake_up_interruptible(&dmawq
);
341 free_irq(IRQ_WMAC
, NULL
);
342 unregister_chrdev(CRYPTO_MAJOR
, CRYPTO_DEVNAME
);
345 if (base
) iounmap(base
);
346 /* disable DMA and security engines */