use broken-out patches for the coldfire to make it easier to follow differences again...
[openwrt/svn-archive/archive.git] / target / linux / coldfire / patches / 015-m5445x_cau_crypto.patch
diff --git a/target/linux/coldfire/patches/015-m5445x_cau_crypto.patch b/target/linux/coldfire/patches/015-m5445x_cau_crypto.patch
new file mode 100644 (file)
index 0000000..dac62e2
--- /dev/null
@@ -0,0 +1,1937 @@
+From 67e24d4008a39fa02a4748a3abf54410b15262b3 Mon Sep 17 00:00:00 2001
+From: Kurt Mahan <kmahan@freescale.com>
+Date: Tue, 20 Nov 2007 10:02:16 -0700
+Subject: [PATCH] Add Coldfire CAU crypto support for DES/3DES/AES/MD5/AES.
+
+LTIBName: m5445x-cau-crypto
+Signed-off-by: Kurt Mahan <kmahan@freescale.com>
+---
+ drivers/crypto/Kconfig       |   63 ++++
+ drivers/crypto/Makefile      |    5 +
+ drivers/crypto/mcfcau-aes.c  |  311 ++++++++++++++++++++
+ drivers/crypto/mcfcau-des.c  |  437 ++++++++++++++++++++++++++++
+ drivers/crypto/mcfcau-md5.c  |  654 ++++++++++++++++++++++++++++++++++++++++++
+ drivers/crypto/mcfcau-sha1.c |  280 ++++++++++++++++++
+ drivers/crypto/mcfcau.c      |   32 ++
+ drivers/crypto/mcfcau.h      |   98 +++++++
+ 8 files changed, 1880 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/crypto/mcfcau-aes.c
+ create mode 100644 drivers/crypto/mcfcau-des.c
+ create mode 100644 drivers/crypto/mcfcau-md5.c
+ create mode 100644 drivers/crypto/mcfcau-sha1.c
+ create mode 100644 drivers/crypto/mcfcau.c
+ create mode 100644 drivers/crypto/mcfcau.h
+
+--- a/drivers/crypto/Kconfig
++++ b/drivers/crypto/Kconfig
+@@ -60,6 +60,69 @@ config CRYPTO_DEV_GEODE
+         To compile this driver as a module, choose M here: the module
+         will be called geode-aes.
++config CRYPTO_DEV_MCFCAU
++      bool "Support for Freescale Coldfire Cryptographic Acceleration Unit (CAU)"
++      depends on M54455
++      select CRYPTO_ALGAPI
++      help
++        The cryptographic acceleration unit (CAU) is a ColdFire coprocessor
++        implementing a set of specialized operations in hardware. For example, you can
++        find it on MCF54455.
++
++config CRYPTO_DEV_MCFCAU_DES
++      tristate "DES and Triple DES cipher algorithms (MCF54455)"
++      depends on CRYPTO_DEV_MCFCAU
++      select CRYPTO_ALGAPI
++      select CRYPTO_BLKCIPHER
++      help
++        DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
++        
++        Say 'Y' here to use the CAU coprocessor for 
++        the CryptoAPI DES and 3DES alogrithms.
++                
++        To compile this driver as a module, choose M here: the module
++        will be called mcfcau-des.
++
++config CRYPTO_DEV_MCFCAU_AES
++      tristate "AES cipher algorithm (MCF54455)"
++      depends on CRYPTO_DEV_MCFCAU
++      select CRYPTO_ALGAPI
++      select CRYPTO_BLKCIPHER
++      help
++        AES cipher algorithm (FIPS 197).
++
++        Say 'Y' here to use the CAU coprocessor for
++        the CryptoAPI AES alogrithm.
++
++        To compile this driver as a module, choose M here: the module
++        will be called mcfcau-aes.
++
++config CRYPTO_DEV_MCFCAU_MD5
++      tristate "MD5 digest algorithm (MCF54455)"
++      depends on CRYPTO_DEV_MCFCAU
++      select CRYPTO_ALGAPI
++      help
++        MD5 message digest algorithm (RFC1321).
++
++        Say 'Y' here to use the CAU coprocessor for
++        the CryptoAPI MD5 alogrithm.
++
++        To compile this driver as a module, choose M here: the module
++        will be called mcfcau-md5.
++
++config CRYPTO_DEV_MCFCAU_SHA1
++      tristate "SHA1 digest algorithm (MCF54455)"
++      depends on CRYPTO_DEV_MCFCAU
++      select CRYPTO_ALGAPI
++      help
++        SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
++
++        Say 'Y' here to use the CAU coprocessor for
++        the CryptoAPI SHA1 alogrithm.
++
++        To compile this driver as a module, choose M here: the module
++        will be called mcfcau-sha1.
++
+ config ZCRYPT
+       tristate "Support for PCI-attached cryptographic adapters"
+       depends on S390
+--- a/drivers/crypto/Makefile
++++ b/drivers/crypto/Makefile
+@@ -2,3 +2,8 @@ obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += 
+ obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
+ obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
+ obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o
++obj-$(CONFIG_CRYPTO_DEV_MCFCAU) += mcfcau.o
++obj-$(CONFIG_CRYPTO_DEV_MCFCAU_DES) += mcfcau-des.o
++obj-$(CONFIG_CRYPTO_DEV_MCFCAU_AES) += mcfcau-aes.o
++obj-$(CONFIG_CRYPTO_DEV_MCFCAU_MD5) += mcfcau-md5.o
++obj-$(CONFIG_CRYPTO_DEV_MCFCAU_SHA1) += mcfcau-sha1.o
+--- /dev/null
++++ b/drivers/crypto/mcfcau-aes.c
+@@ -0,0 +1,311 @@
++ /***************************************************************************
++ * mcfcau-aes.c - Implementation of AES Cipher Algorithm
++ *                for Freescale ColdFire Cryptographic Acceleration Unit (CAU).
++ *
++ * Author: Andrey Butok
++ * Copyright Freescale Semiconductor Inc.  2007
++ *
++ * NOTE: You can find the ColdFire CAU module on MCF54455 and MCF52235.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ ***************************************************************************
++ * Changes:
++ * v0.01      17 September 2007       Andrey Butok
++ *            Initial Release - developed on 2.6.20 Linux kernel.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/crypto.h>
++
++/*
++#undef DEBUG
++#define DEBUG 1
++*/
++
++#include "mcfcau.h"
++
++#define MCFCAU_AES_MIN_KEY_SIZE       (16)
++#define MCFCAU_AES_MAX_KEY_SIZE       (32)
++#define MCFCAU_AES_BLOCK_SIZE (16)
++
++#define       MCFCAU_AES_DRIVER_DESC          "AES ColdFire CAU driver"
++#define       MCFCAU_AES_DRIVER_VERSION       "v0.01"
++
++struct mcfcau_aes_ctx {
++      int Nr_1;
++      u32 buf[120];
++      u32 buf_tmp[16];
++};
++
++static u32 mcfcau_rco_tab[10]={ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
++                              0x10000000, 0x20000000, 0x40000000, 0x80000000,
++                              0x1b000000, 0x36000000};
++
++int mcfcau_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key,
++                     unsigned int key_len)
++{
++      struct mcfcau_aes_ctx *ctx = crypto_tfm_ctx(tfm);
++      const u32 * key = (const u32 *)in_key;
++      u32 *flags = &tfm->crt_flags;
++      u32 i;
++      u32* key_sch = (&ctx->buf[0]);
++      u32 * temp_p, * rcon_p;
++      u32 Nx;
++      u32 Nk;
++      unsigned long iflags;
++
++      DBG("\n");
++
++      if (key_len % 8) {
++              *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
++              return -EINVAL;
++      }
++
++      Nk = key_len>>2;
++
++      for(i=0;i<Nk;i++){
++              key_sch[i] = key[i];
++      }
++
++      ctx->Nr_1 = Nk+5;
++
++      /* Key Expansion */
++      temp_p=&key_sch[Nk-1];
++      rcon_p=&mcfcau_rco_tab[0];
++
++      spin_lock_irqsave(&mcfcau_lock, iflags);
++
++      asm volatile ("move.l   %0, %%a1"::"m"(temp_p):"a1");
++      asm volatile ("move.l   %0, %%a3"::"m"(rcon_p):"a3");
++      asm volatile ("move.l   %0, %%a4"::"m"(key_sch):"a4");
++
++      Nx=(Nk+7)<<2; /* (Nr+1)*Nb */
++
++      for(i=Nk; i<Nx; i++)
++      {
++              /* temp = key_sch[Nk-1] */
++              asm volatile ("cp0ld.l  (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CAA):"a1");
++
++              if(i%Nk==0){
++                      asm volatile ("moveq    #8, %%d0":::"d0");
++                      /* CAA=RotWord(temp) */
++                      asm volatile ("cp0ld.l  %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA):"d0");
++                      /* SubWord(CAA) */
++                      asm volatile ("cp0ld.l  %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_AESS+MCFCAU_CAA));
++                      /* ACC xor rcon[i/Nk] */
++                      asm volatile ("cp0ld.l  (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CAA):"a3");
++
++              }else if((Nk>6) && (i%Nk ==4)){
++                      /* SubWord(ACC) */
++                      asm volatile ("cp0ld.l  %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_AESS+MCFCAU_CAA));
++              }
++
++              /* key_sch[i]^=key_sch[i-Nk]; store ACC to key_sch[i] */
++              asm volatile ("cp0ld.l  (%%a4)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CAA):"a4");
++              asm volatile ("cp0st.l  %%d0,(%%a1),#1,%0"      ::"n"(MCFCAU_STR+MCFCAU_CAA));
++      }
++      spin_unlock_irqrestore(&mcfcau_lock, iflags);
++
++      return 0;
++}
++
++
++/* encrypt a block of text */
++static void mcfcau_aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
++{
++      struct mcfcau_aes_ctx *ctx = crypto_tfm_ctx(tfm);
++      const int Nr_1 = ctx->Nr_1;
++
++      u32* key_sch = &(ctx->buf[0]);
++      u32 i;
++      unsigned long iflags;
++
++      DBG("\n");
++
++      spin_lock_irqsave(&mcfcau_lock, iflags);
++      asm("move.l     %0, %%a1"::"m"(in):"a1");
++      asm("move.l     %0, %%a0"::"m"(key_sch):"a0");
++      /* state=in */
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA1):"a1");
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a1");
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA3):"a1");
++      /* AddRoundKey() */
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA0):"a0");
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA1):"a0");
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA2):"a0");
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA3):"a0");
++
++      for(i=Nr_1;i>0;i--){
++              /* SubBytes(state) */
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA0));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA1));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA2));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA3));
++              /* ShiftRows(state) */
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESR));
++              /* MixColumns(state); AddRoundKey() */
++              asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_AESC+MCFCAU_CA0):"a0");
++              asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_AESC+MCFCAU_CA1):"a0");
++              asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_AESC+MCFCAU_CA2):"a0");
++              asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_AESC+MCFCAU_CA3):"a0");
++      }
++      /* SubBytes(state)*/
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA0));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA3));
++      /* ShiftRows(state) */
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESR));
++      /* AddRoundKey() */
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA0):"a0");
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA1):"a0");
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA2):"a0");
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA3):"a0");
++      /* out = state */
++      asm("move.l     %0, %%a1"               ::"m"(out):"a1");
++      asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA0):"d0");
++      asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA1):"d1");
++
++      asm("move.l     %%d0,(%%a1)+":::"a1");
++      asm("move.l     %%d1,(%%a1)+":::"a1");
++
++      asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA2):"d0");
++      asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA3):"d1");
++
++      asm("move.l     %%d0,(%%a1)+":::"a1");
++      asm("move.l     %%d1,(%%a1)+":::"a1");
++      spin_unlock_irqrestore(&mcfcau_lock, iflags);
++}
++
++
++/* decrypt a block of text */
++static void mcfcau_aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
++{
++      struct mcfcau_aes_ctx *ctx = crypto_tfm_ctx(tfm);
++      u32* key_sch = &(ctx->buf[0]);
++      u32 i;
++      unsigned long iflags;
++      const int Nr_1 = ctx->Nr_1;
++      key_sch=&key_sch[(Nr_1+2)*4];
++
++      DBG("\n");
++
++      spin_lock_irqsave(&mcfcau_lock, iflags);
++
++      asm("move.l     %0, %%a1"::"m"(in):"a1");
++      asm("move.l     %0, %%a0"::"m"(key_sch):"a0");
++      /* state=in */
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA1):"a1");
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a1");
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA3):"a1");
++      /* AddRoundKey() */
++      asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA3):"a0");
++      asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA2):"a0");
++      asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA1):"a0");
++      asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA0):"a0");
++
++      for(i=Nr_1;i>0;i--){
++              /* InvShiftRows(state) */
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIR));
++              /* InvSubBytes(state) */
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA3));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA2));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA1));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA0));
++              /* InvMixColumns(state); AddRoundKey() */
++              asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_AESIC+MCFCAU_CA3):"a0");
++              asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_AESIC+MCFCAU_CA2):"a0");
++              asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_AESIC+MCFCAU_CA1):"a0");
++              asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_AESIC+MCFCAU_CA0):"a0");
++      }
++      /* InvShiftRows(state) */
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIR));
++      /* InvSubBytes(state)*/
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA3));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA0));
++      /* AddRoundKey() */
++      asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA3):"a0");
++      asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA2):"a0");
++      asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA1):"a0");
++      asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA0):"a0");
++      /* out = state */
++      asm("move.l     %0, %%a1"               ::"m"(out):"a1");
++      asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA0):"d0");
++      asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA1):"d1");
++
++      asm("move.l     %%d0,(%%a1)+":::"a1");
++      asm("move.l     %%d1,(%%a1)+":::"a1");
++
++      asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA2):"d0");
++      asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA3):"d1");
++
++      asm("move.l     %%d0,(%%a1)+":::"a1");
++      asm("move.l     %%d1,(%%a1)+":::"a1");
++      spin_unlock_irqrestore(&mcfcau_lock, iflags);
++
++}
++
++
++static struct crypto_alg mcfcau_aes_alg = {
++      .cra_name               =       "aes",
++      .cra_driver_name        =       "aes-mcfcau",
++      .cra_priority           =       MCFCAU_CRA_PRIORITY,
++      .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
++      .cra_blocksize          =       MCFCAU_AES_BLOCK_SIZE,
++      .cra_ctxsize            =       sizeof(struct mcfcau_aes_ctx),
++      .cra_alignmask          =       3,
++      .cra_module             =       THIS_MODULE,
++      .cra_list               =       LIST_HEAD_INIT(mcfcau_aes_alg.cra_list),
++      .cra_u                  =       {
++              .cipher = {
++                      .cia_min_keysize        =       MCFCAU_AES_MIN_KEY_SIZE,
++                      .cia_max_keysize        =       MCFCAU_AES_MAX_KEY_SIZE,
++                      .cia_setkey             =       mcfcau_aes_setkey,
++                      .cia_encrypt            =       mcfcau_aes_encrypt,
++                      .cia_decrypt            =       mcfcau_aes_decrypt
++              }
++      }
++};
++
++static int __init mcfcau_aes_init(void)
++{
++      int ret = crypto_register_alg(&mcfcau_aes_alg);
++
++      printk(KERN_INFO MCFCAU_AES_DRIVER_DESC " "
++              MCFCAU_AES_DRIVER_VERSION " %s.\n",ret?"failed":"registered");
++      return ret;
++}
++
++static void __exit mcfcau_aes_fini(void)
++{
++      crypto_unregister_alg(&mcfcau_aes_alg);
++      printk(KERN_INFO MCFCAU_AES_DRIVER_DESC " "
++              MCFCAU_AES_DRIVER_VERSION " unregistered.\n");
++}
++
++module_init(mcfcau_aes_init);
++module_exit(mcfcau_aes_fini);
++
++MODULE_DESCRIPTION(MCFCAU_AES_DRIVER_DESC);
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_AUTHOR("Andrey Butok");
+--- /dev/null
++++ b/drivers/crypto/mcfcau-des.c
+@@ -0,0 +1,437 @@
++/***************************************************************************
++ * mcfcau-des.c - Implementation of DES & Triple DES EDE Cipher Algorithms
++ *                for Freescale ColdFire Cryptographic Acceleration Unit (CAU).
++ *
++ * Author: Andrey Butok
++ * Copyright Freescale Semiconductor Inc.  2007
++ *
++ * NOTE: You can find the ColdFire CAU module on MCF54455 and MCF52235.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ ***************************************************************************
++ * Changes:
++ * v0.01      14 August 2007  Andrey Butok
++ *            Initial Release - developed on 2.6.20 Linux kernel.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/crypto.h>
++#include <linux/types.h>
++
++/*
++#undef DEBUG
++#define DEBUG 1
++*/
++
++#include "mcfcau.h"
++
++#define MCFCAU_DES_KEY_SIZE           (8)
++#define MCFCAU_DES_EXPKEY_WORDS               (32)
++#define MCFCAU_DES_BLOCK_SIZE         (8)
++
++#define MCFCAU_DES3_EDE_KEY_SIZE      (3 * MCFCAU_DES_KEY_SIZE)
++#define MCFCAU_DES3_EDE_EXPKEY_WORDS  (3 * MCFCAU_DES_EXPKEY_WORDS)
++#define MCFCAU_DES3_EDE_BLOCK_SIZE    (MCFCAU_DES_BLOCK_SIZE)
++
++#define       MCFCAU_DES_DRIVER_DESC          "DES & 3DES ColdFire CAU driver"
++#define       MCFCAU_DES_DRIVER_VERSION       "v0.01"
++
++struct mcfcau_des_ctx {
++      u32 expkey[MCFCAU_DES_EXPKEY_WORDS];
++};
++
++struct mcfcau_des3_ede_ctx {
++      u32 expkey[MCFCAU_DES3_EDE_EXPKEY_WORDS];
++};
++
++/* DES round operations */
++static inline void mcfcau_des_encipher(void)
++{
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESK));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_IP+MCFCAU_KSL1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_FP+MCFCAU_KSL1));
++}
++
++static inline void mcfcau_des_decipher(void)
++{
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESK+MCFCAU_DC));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_IP+MCFCAU_KSR1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_FP+MCFCAU_KSL1));
++}
++
++
++static int mcfcau_des_setkey(struct crypto_tfm *tfm, const u8 *key_p,
++                    unsigned int keylen)
++{
++      struct mcfcau_des_ctx *dctx = crypto_tfm_ctx(tfm);
++      u32 *flags = &tfm->crt_flags;
++      u32 * key = (u32 *) key_p;
++
++      DBG("\n");
++
++      /*
++      * RFC2451: Weak key checks SHOULD be performed.
++      *
++      * FIPS 74:
++      *   Keys having duals are keys which produce all zeros, all ones, or
++      *   alternating zero-one patterns in the C and D registers after Permuted
++      *   Choice 1 has operated on the key.
++      *
++      */
++      if(*flags & CRYPTO_TFM_REQ_WEAK_KEY){ /* FIPS 74 */
++              if(key[0]<0xE001E00l){
++                      if(key[0]<0x1FE01FE0){
++                              if(key[0]<0x01E001E0){
++                                      if(((key[0]==0x01010101)&&(key[1]==0x01010101))||
++                                              ((key[0]==0x011F011F)&&(key[1]==0x010E010E)) )
++                                              goto WEAK_KEY;
++                              }
++                              else{
++                                      if(((key[0]==0x01E001E0)&&(key[1]==0x01F101F1))||
++                                              ((key[0]==0x01FE01FE)&&(key[1]==0x01FE01FE)) )
++                                              goto WEAK_KEY;
++                              }
++                      }
++                      else{
++                              if(key[0]<0x1F1F1F1F){
++                                      if(((key[0]==0x1FE01FE0)&&(key[1]==0x0EF10EF1))||
++                                              ((key[0]==0x1F011F0l)&&(key[1]==0x0E010E01)) )
++                                              goto WEAK_KEY;
++                              }
++                              else{
++                                      if(((key[0]==0x1F1F1F1F)&&(key[1]==0x0E0E0E0E))||
++                                              ((key[0]==0x1FFE1FFE)&&(key[1]==0x0EFE0EFE)) )
++                                              goto WEAK_KEY;
++                              }
++                      }
++              } else {
++                      if(key[0]<0xFE01FE01){
++                              if(key[0]<0xE0E0E0E0){
++                                      if(((key[0]==0xE001E00l)&&(key[1]==0xF101F101))||
++                                              ((key[0]==0xE01FE01F)&&(key[1]==0xF10EF10E)) )
++                                              goto WEAK_KEY;
++                              }
++                              else{
++                                      if(((key[0]==0xE0E0E0E0)&&(key[1]==0xF1F1F1F1))||
++                                              ((key[0]==0xE0FEE0FE)&&(key[1]==0xF1FEF1FE)) )
++                                              goto WEAK_KEY;
++                              }
++                      }
++                      else{
++                              if(key[0]<0xFEE0FEE0){
++                                      if(((key[0]==0xFE01FE01)&&(key[1]==0xFE01FE01))||
++                                              ((key[0]==0xFE1FFE1F)&&(key[1]==0xFE0EFE0E)) )
++                                              goto WEAK_KEY;
++                              }
++                              else{
++                                      if(((key[0]==0xFEE0FEE0)&&(key[1]==0xFEF1FEF1))||
++                                              ((key[0]==0xFEFEFEFE)&&(key[1]==0xFEFEFEFE)) )
++                                              goto WEAK_KEY;
++                              }
++                      }
++              }
++      }
++      memcpy(dctx->expkey, key_p, keylen);
++      return 0;
++WEAK_KEY:
++      *flags |= CRYPTO_TFM_RES_WEAK_KEY;
++      return -EINVAL;
++}
++
++
++void mcfcau_des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
++{
++      struct mcfcau_des_ctx *ctx = crypto_tfm_ctx(tfm);
++      u32 * des_key_tmp = ctx->expkey;
++      unsigned long iflags;
++
++      DBG("\n");
++
++      spin_lock_irqsave(&mcfcau_lock, iflags);
++
++      asm("move.l     %0, %%a0"::"m"(src):"a0");
++      asm("move.l     %0, %%a1"::"m"(des_key_tmp):"a1");
++
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a0");
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA3));
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
++      asm("cp0ld.l    (%%a1),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA1));
++
++      mcfcau_des_encipher();
++
++      asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA2):"d0");
++      asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA3):"d1");
++      asm("move.l     %0, %%a1"               ::"m"(dst):"a1");
++      asm("move.l     %d0,(%a1)+");
++      asm("move.l     %d1,(%a1)");
++
++      spin_unlock_irqrestore(&mcfcau_lock, iflags);
++}
++
++
++void mcfcau_des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
++{
++      struct mcfcau_des_ctx *ctx = crypto_tfm_ctx(tfm);
++      u32 * des_key_tmp = ctx->expkey;
++      unsigned long iflags;
++
++      DBG("\n");
++
++      spin_lock_irqsave(&mcfcau_lock, iflags);
++
++      asm("move.l     %0, %%a0"::"m"(src):"a0");
++      asm("move.l     %0, %%a1"::"m"(des_key_tmp):"a1");
++
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a0");
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA3));
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
++      asm("cp0ld.l    (%%a1),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA1));
++
++      mcfcau_des_decipher();
++
++      asm("move.l     %0, %%a1"               ::"m"(dst):"a1");
++      asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA2):"d0");
++      asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA3):"d1");
++      asm("move.l     %d0,(%a1)+");
++      asm("move.l     %d1,(%a1)");
++
++      spin_unlock_irqrestore(&mcfcau_lock, iflags);
++}
++
++
++/*
++ * RFC2451:
++ *
++ *   For DES-EDE3, there is no known need to reject weak or
++ *   complementation keys.  Any weakness is obviated by the use of
++ *   multiple keys.
++ *
++ *   However, if the first two or last two independent 64-bit keys are
++ *   equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
++ *   same as DES.  Implementers MUST reject keys that exhibit this
++ *   property.
++ *
++ */
++
++static int mcfcau_des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key_p, unsigned int keylen)
++{
++      const u32 *key = (const u32 *)key_p;
++      struct mcfcau_des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
++      u32 *flags = &tfm->crt_flags;
++
++DBG("\n");
++
++      if (unlikely(!((key[0] ^ key[2]) | (key[1] ^ key[3])) ||
++                   !((key[2] ^ key[4]) | (key[3] ^ key[5]))))
++      {
++              *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
++              return -EINVAL;
++      }
++
++      memcpy(dctx->expkey,key_p,keylen);
++
++      return 0;
++}
++
++static void mcfcau_des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
++{
++      struct mcfcau_des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
++      const u32 * des_key_tmp = dctx->expkey;
++      unsigned long iflags;
++
++      DBG("\n");
++
++      spin_lock_irqsave(&mcfcau_lock, iflags);
++
++      /*EK1*/
++      asm("move.l     %0, %%a0"::"m"(src):"a0");
++      asm("move.l     %0, %%a1"::"m"(des_key_tmp):"a1");
++
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a0");
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA3));
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA1):"a1");
++
++      mcfcau_des_encipher();
++
++      /*DK2*/
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA1):"a1");
++
++      mcfcau_des_decipher();
++
++      /*EK3*/
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
++      asm("cp0ld.l    (%%a1),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA1));
++
++      mcfcau_des_encipher();
++
++      asm("move.l     %0, %%a1"               ::"m"(dst):"a1");
++      asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA2):"d0");
++      asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA3):"d1");
++      asm("move.l     %d0,(%a1)+");
++      asm("move.l     %d1,(%a1)");
++
++      spin_unlock_irqrestore(&mcfcau_lock, iflags);
++}
++
++static void mcfcau_des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
++{
++      struct mcfcau_des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
++      const u32 * des_key_tmp = dctx->expkey + 6 - 2;
++      unsigned long iflags;
++
++      DBG("\n");
++
++      spin_lock_irqsave(&mcfcau_lock, iflags);
++
++      /*DK3*/
++      asm("move.l     %0, %%a0"::"m"(src):"a0");
++      asm("move.l     %0, %%a1"::"m"(des_key_tmp):"a1");
++
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a0");
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA3));
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
++      asm("cp0ld.l    (%%a1),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA1));
++
++      mcfcau_des_decipher();
++
++      /*EK2*/
++      asm("suba.l     #12,%a1");      /*dec key pointer*/
++
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
++      asm("cp0ld.l    (%%a1),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA1));
++
++      mcfcau_des_encipher();
++
++      /*DK1*/
++      asm("suba.l     #12,%a1");      /*dec key pointer*/
++
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
++      asm("cp0ld.l    (%%a1),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA1));
++
++      mcfcau_des_decipher();
++
++      asm("move.l     %0, %%a1"               ::"m"(dst):"a1");
++      asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA2):"d0");
++      asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA3):"d1");
++      asm("move.l     %d0,(%a1)+");
++      asm("move.l     %d1,(%a1)");
++
++      spin_unlock_irqrestore(&mcfcau_lock, iflags);
++}
++
++
++static struct crypto_alg mcfcau_des_alg = {
++      .cra_name               =       "des",
++      .cra_driver_name        =       "des-mcfcau",
++      .cra_priority           =       MCFCAU_CRA_PRIORITY,
++      .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
++      .cra_blocksize          =       MCFCAU_DES_BLOCK_SIZE,
++      .cra_ctxsize            =       sizeof(struct mcfcau_des_ctx),
++      .cra_module             =       THIS_MODULE,
++      .cra_alignmask          =       3,
++      .cra_list               =       LIST_HEAD_INIT(mcfcau_des_alg.cra_list),
++      .cra_u                  =       { .cipher = {
++      .cia_min_keysize        =       MCFCAU_DES_KEY_SIZE,
++      .cia_max_keysize        =       MCFCAU_DES_KEY_SIZE,
++      .cia_setkey             =       mcfcau_des_setkey,
++      .cia_encrypt            =       mcfcau_des_encrypt,
++      .cia_decrypt            =       mcfcau_des_decrypt } }
++};
++
++static struct crypto_alg mcfcau_des3_ede_alg = {
++      .cra_name               =       "des3_ede",
++      .cra_driver_name        =       "des3_ede-mcfcau",
++      .cra_priority           =       MCFCAU_CRA_PRIORITY,
++      .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
++      .cra_blocksize          =       MCFCAU_DES3_EDE_BLOCK_SIZE,
++      .cra_ctxsize            =       sizeof(struct mcfcau_des3_ede_ctx),
++      .cra_module             =       THIS_MODULE,
++      .cra_alignmask          =       3,
++      .cra_list               =       LIST_HEAD_INIT(mcfcau_des3_ede_alg.cra_list),
++      .cra_u                  =       { .cipher = {
++      .cia_min_keysize        =       MCFCAU_DES3_EDE_KEY_SIZE,
++      .cia_max_keysize        =       MCFCAU_DES3_EDE_KEY_SIZE,
++      .cia_setkey             =       mcfcau_des3_ede_setkey,
++      .cia_encrypt            =       mcfcau_des3_ede_encrypt,
++      .cia_decrypt            =       mcfcau_des3_ede_decrypt } }
++};
++
++MODULE_ALIAS("mcfcau_des3_ede");
++
++static int __init mcfcau_des_init(void)
++{
++      int ret;
++
++      ret = crypto_register_alg(&mcfcau_des_alg);
++      if (ret < 0)
++              goto out;
++
++      ret = crypto_register_alg(&mcfcau_des3_ede_alg);
++      if (ret < 0)
++              crypto_unregister_alg(&mcfcau_des_alg);
++out:
++      printk(KERN_INFO MCFCAU_DES_DRIVER_DESC " "
++              MCFCAU_DES_DRIVER_VERSION " %s.\n",ret?"failed":"registered");
++      return ret;
++}
++
++static void __exit mcfcau_des_exit(void)
++{
++      crypto_unregister_alg(&mcfcau_des3_ede_alg);
++      crypto_unregister_alg(&mcfcau_des_alg);
++
++      printk(KERN_INFO MCFCAU_DES_DRIVER_DESC " "
++              MCFCAU_DES_DRIVER_VERSION " unregistered.\n");
++}
++
++module_init(mcfcau_des_init);
++module_exit(mcfcau_des_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms for ColdFire CAU");
++MODULE_AUTHOR("Andrey Butok");
+--- /dev/null
++++ b/drivers/crypto/mcfcau-md5.c
+@@ -0,0 +1,654 @@
++ /***************************************************************************
++ * mcfcau-md5.c - Implementation of MD5 Message Digest Algorithm (RFC1321)
++ *                for Freescale ColdFire Cryptographic Acceleration Unit (CAU).
++ *
++ * Author: Andrey Butok
++ * Copyright Freescale Semiconductor Inc.  2007
++ *
++ * NOTE: You can find the ColdFire CAU module on MCF54455 and MCF52235.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ ***************************************************************************
++ * Changes:
++ * v0.01      30 September 2007       Andrey Butok
++ *            Initial Release - developed on 2.6.20 Linux kernel.
++ */
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/crypto.h>
++#include <linux/types.h>
++#include <asm/byteorder.h>
++
++/*
++#undef DEBUG
++#define DEBUG 1
++*/
++
++#include "mcfcau.h"
++
++
++#define MCFCAU_MD5_DIGEST_SIZE                (16)
++#define MCFCAU_MD5_HMAC_BLOCK_SIZE    (64)
++#define MCFCAU_MD5_BLOCK_WORDS                (16)
++#define MCFCAU_MD5_HASH_WORDS         (4)
++
++#define       MCFCAU_MD5_DRIVER_DESC          "MD5 ColdFire CAU driver"
++#define       MCFCAU_MD5_DRIVER_VERSION       "v0.01"
++
++
++struct mcfcau_md5_ctx {
++      u32 hash[MCFCAU_MD5_HASH_WORDS];
++      u32 block[MCFCAU_MD5_BLOCK_WORDS];
++      u64 byte_count;
++};
++
++u32 mcfcau_md5_t[64]={0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
++                      0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
++                      0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
++                      0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
++                      0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
++                      0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
++                      0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
++                      0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
++                      0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
++                      0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
++                      0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
++                      0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
++                      0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
++                      0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
++                      0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
++                      0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};
++
++
++
++static void mcfcau_md5_transform(u32 *hash, u32 const *in)
++{
++      int i;
++      u32 * md5_t_p=&mcfcau_md5_t[0];
++      unsigned long iflags;
++
++      spin_lock_irqsave(&mcfcau_lock, iflags);
++      asm("move.l     %0, %%a1"::"m"(hash):"a1");
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CAA):"a1");/*a*/
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA1):"a1");/*b*/
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a1");/*c*/
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA3):"a1");/*d*/
++      asm("move.l     %0, %%a0"::"m"(in):"a0");       /* X[] */
++      asm("move.l     %0, %%a3"::"m"(md5_t_p):"a3");  /* T[] */
++
++      
++      /*  Round 1 */
++      asm("moveq.l    #7, %%d4":::"d4");      /* for rotating by 7 */
++      asm("moveq.l    #12, %%d5":::"d5");     /* for rotating by 12 */
++      asm("moveq.l    #17, %%d6":::"d6");     /* for rotating by 17 */
++      asm("moveq.l    #22, %%d7":::"d7");     /* for rotating by 22 */
++
++      for(i=0; i<4;i++){
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFF));         /* a+F(b,c,d) */
++              asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");    /* add byterev x[i] */
++              asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");     /* add t[i] */
++              asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));         /* rotate by 7 */
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));         /* add b */
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));                     /* register to register shift */
++
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFF));
++              asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++              asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++              asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFF));
++              asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++              asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++              asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFF));
++              asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++              asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++              asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++      };
++
++
++      /* Round 2 */
++      asm("moveq.l    #5, %%d4":::"d4");      /* for rotating by 5 */
++      asm("moveq.l    #9, %%d5":::"d5");      /* for rotating by 9 */
++      asm("moveq.l    #14, %%d6":::"d6");     /* for rotating by 14 */
++      asm("moveq.l    #20, %%d7":::"d7");     /* for rotating by 20 */
++
++      asm("lea -60(%%a0),%%a0":::"a0");
++
++      for(i=0; i<2;i++){
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
++              asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++              asm("lea        20(%%a0),%%a0"          :::"a0");
++              asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++              asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
++              asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++              asm("lea        20(%%a0),%%a0"          :::"a0");
++              asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++              asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
++              asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++              asm("lea        -44(%%a0),%%a0"         :::"a0");
++              asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++              asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
++              asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++              asm("lea        20(%%a0),%%a0"          :::"a0");
++              asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++              asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++      };
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        20(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -44(%%a0),%%a0"         :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        20(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        20(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -44(%%a0),%%a0"         :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        20(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        20(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -28(%%a0),%%a0"         :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++
++      /* Round 3 */
++      asm("moveq.l    #4, %%d4":::"d4");      /* for rotating by 5 */
++      asm("moveq.l    #11, %%d5":::"d5");     /* for rotating by 9 */
++      asm("moveq.l    #16, %%d6":::"d6");     /* for rotating by 14 */
++      asm("moveq.l    #23, %%d7":::"d7");     /* for rotating by 20 */
++
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        12(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        12(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        12(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -52(%%a0),%%a0"         :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        12(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        12(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        12(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        12(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -52(%%a0),%%a0"         :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        12(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        12(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        12(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        12(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        12(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -52(%%a0),%%a0"         :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -8(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      
++      /* Round 4 */
++      asm("moveq.l    #6, %%d4":::"d4");      /* for rotating by 6 */
++      asm("moveq.l    #10, %%d5":::"d5");     /* for rotating by 10 */
++      asm("moveq.l    #15, %%d6":::"d6");     /* for rotating by 15 */
++      asm("moveq.l    #21, %%d7":::"d7");     /* for rotating by 21 */
++
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        28(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        28(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -36(%%a0),%%a0"         :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        28(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -36(%%a0),%%a0"         :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        28(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -36(%%a0),%%a0"         :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        28(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        28(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -36(%%a0),%%a0"         :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        28(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -36(%%a0),%%a0"         :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        28(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        -36(%%a0),%%a0"         :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        28(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
++      asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
++      asm("lea        28(%%a0),%%a0"          :::"a0");
++      asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
++      asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
++
++      
++      asm("move.l     %0, %%a1"::"m"(hash):"a1");
++
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a1");/*a*/
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA1):"a1");/*b*/
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA2):"a1");/*c*/
++      asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA3):"a1");/*d*/
++
++      asm("cp0st.l    %%d0,-(%%a1),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA3):"a1");/*d*/
++      asm("cp0st.l    %%d0,-(%%a1),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA2):"a1");/*c*/
++      asm("cp0st.l    %%d0,-(%%a1),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA1):"a1");/*b*/
++      asm("cp0st.l    %%d0,-(%%a1),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CAA):"a1");/*a*/
++      spin_unlock_irqrestore(&mcfcau_lock, iflags);
++}
++
++static inline void le32_to_cpu_array(u32 *buf, unsigned int words)
++{
++      while (words--) {
++              __le32_to_cpus(buf);
++              buf++;
++      }
++}
++
++static inline void cpu_to_le32_array(u32 *buf, unsigned int words)
++{
++      while (words--) {
++              __cpu_to_le32s(buf);
++              buf++;
++      }
++}
++
++static void mcfcau_md5_initialization(struct crypto_tfm *tfm)
++{
++      struct mcfcau_md5_ctx *mctx = crypto_tfm_ctx(tfm);
++
++      DBG("\n");
++      mctx->hash[0] = 0x67452301;
++      mctx->hash[1] = 0xefcdab89;
++      mctx->hash[2] = 0x98badcfe;
++      mctx->hash[3] = 0x10325476;
++      mctx->byte_count = 0;
++}
++
++static void mcfcau_md5_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
++{
++      struct mcfcau_md5_ctx *mctx = crypto_tfm_ctx(tfm);
++      const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
++
++      DBG("\n");
++      mctx->byte_count += len;
++
++      if (avail > len) {
++              memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
++                     data, len);
++      }
++      else {
++              memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), data, avail);
++
++              mcfcau_md5_transform(mctx->hash, mctx->block);
++              data += avail;
++              len -= avail;
++
++              while (len >= sizeof(mctx->block)) {
++                      memcpy(mctx->block, data, sizeof(mctx->block));
++                      mcfcau_md5_transform(mctx->hash, mctx->block);
++                      data += sizeof(mctx->block);
++                      len -= sizeof(mctx->block);
++              }
++
++              memcpy(mctx->block, data, len);
++      }
++}
++
++static void mcfcau_md5_final(struct crypto_tfm *tfm, u8 *out)
++{
++      struct mcfcau_md5_ctx *mctx = crypto_tfm_ctx(tfm);
++      const unsigned int offset = mctx->byte_count & 0x3f;
++      char *p = (char *)mctx->block + offset;
++      int padding = 56 - (offset + 1);
++
++      DBG("\n");
++
++      *p++ = 0x80;
++      if (padding < 0) {
++              memset(p, 0x00, padding + sizeof (u64));
++              mcfcau_md5_transform(mctx->hash, mctx->block);
++              p = (char *)mctx->block;
++              padding = 56;
++      }
++
++      memset(p, 0, padding);
++      mctx->block[14] = mctx->byte_count << 3;
++      mctx->block[15] = mctx->byte_count >> 29;
++      le32_to_cpu_array(&mctx->block[14], 2);
++
++      mcfcau_md5_transform(mctx->hash, mctx->block);
++
++      cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32));
++      memcpy(out, mctx->hash, sizeof(mctx->hash));
++      memset(mctx, 0, sizeof(*mctx));
++}
++
++static struct crypto_alg mcfcau_md5_alg = {
++      .cra_name               =       "md5",
++      .cra_driver_name        =       "md5-mcfcau",
++      .cra_priority           =       MCFCAU_CRA_PRIORITY,
++      .cra_flags              =       CRYPTO_ALG_TYPE_DIGEST,
++      .cra_blocksize          =       MCFCAU_MD5_HMAC_BLOCK_SIZE,
++      .cra_ctxsize            =       sizeof(struct mcfcau_md5_ctx),
++      .cra_module             =       THIS_MODULE,
++      .cra_list               =       LIST_HEAD_INIT(mcfcau_md5_alg.cra_list),
++      .cra_u                  =       { .digest = {
++      .dia_digestsize         =       MCFCAU_MD5_DIGEST_SIZE,
++      .dia_init               =       mcfcau_md5_initialization,
++      .dia_update             =       mcfcau_md5_update,
++      .dia_final              =       mcfcau_md5_final } }
++};
++
++static int __init mcfcau_md5_init(void)
++{
++      int ret = crypto_register_alg(&mcfcau_md5_alg);
++      printk(KERN_INFO MCFCAU_MD5_DRIVER_DESC " "
++              MCFCAU_MD5_DRIVER_VERSION " %s.\n",ret?"failed":"registered");
++      return ret;
++}
++
++static void __exit mcfcau_md5_exit(void)
++{
++      crypto_unregister_alg(&mcfcau_md5_alg);
++      printk(KERN_INFO MCFCAU_MD5_DRIVER_DESC " "
++              MCFCAU_MD5_DRIVER_VERSION " unregistered.\n");
++}
++
++module_init(mcfcau_md5_init);
++module_exit(mcfcau_md5_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION(MCFCAU_MD5_DRIVER_DESC);
++MODULE_AUTHOR("Andrey Butok");
+--- /dev/null
++++ b/drivers/crypto/mcfcau-sha1.c
+@@ -0,0 +1,280 @@
++ /***************************************************************************
++ * mcfcau-sha1.c - Implementation of SHA1 Secure Hash Algorithm
++ *                for Freescale ColdFire Cryptographic Acceleration Unit (CAU).
++ *
++ * Author: Andrey Butok
++ * Copyright Freescale Semiconductor Inc.  2007
++ *
++ * NOTE: You can find the ColdFire CAU module on MCF54455 and MCF52235.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ ***************************************************************************
++ * Changes:
++ * v0.01      15 October 2007 Andrey Butok
++ *            Initial Release - developed on 2.6.20 Linux kernel.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/crypto.h>
++#include <linux/types.h>
++
++
++/*
++#undef DEBUG
++#define DEBUG 1
++*/
++
++#include "mcfcau.h"
++
++#define MCFCAU_SHA1_DIGEST_WORDS      (5)
++#define MCFCAU_SHA1_WORKSPACE_WORDS   (80)
++
++#define MCFCAU_SHA1_DIGEST_SIZE               (20)
++#define MCFCAU_SHA1_HMAC_BLOCK_SIZE   (64)
++
++#define       MCFCAU_SHA1_DRIVER_DESC         "SHA1 ColdFire CAU driver"
++#define       MCFCAU_SHA1_DRIVER_VERSION      "v0.01"
++
++struct mcfcau_sha1_ctx {
++        u64 count;
++        u32 state[5];
++        u8 buffer[64];
++};
++
++const static u32 K[4]={0x5A827999L,   /* Rounds  0-19: sqrt(2) * 2^30 */
++                      0x6ED9EBA1L,    /* Rounds 20-39: sqrt(3) * 2^30 */
++                      0x8F1BBCDCL,    /* Rounds 40-59: sqrt(5) * 2^30 */
++                      0xCA62C1D6L};   /* Rounds 60-79: sqrt(10) * 2^30 */
++
++static void noinline mcfcau_sha1_transform(__u32 *digest, const char *in, __u32 *W)
++{
++      int i;
++      u32 * tmp_p;
++      unsigned long iflags;
++
++      /* (a) Devide M(i) into 16 words W */
++      for (i = 0; i < 16; i++)
++              W[i] = ((const u32 *)in)[i];
++
++      /* (b) W[i+16] = S^1(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i]) */
++      tmp_p=&W[16];
++
++      spin_lock_irqsave(&mcfcau_lock, iflags);
++      asm("move.l     %0, %%a0"::"m"(tmp_p):"a0");
++      asm("moveq.l    #1, %%d3":::"d3");
++
++      for (i = 0; i < 64; i++){
++              asm("cp0ld.l    -64(%%a0),%%d0,#1,%0"   ::"n"(MCFCAU_LDR+MCFCAU_CA0));
++              asm("cp0ld.l    -56(%%a0),%%d0,#1,%0"   ::"n"(MCFCAU_XOR+MCFCAU_CA0));
++              asm("cp0ld.l    -32(%%a0),%%d0,#1,%0"   ::"n"(MCFCAU_XOR+MCFCAU_CA0));
++              asm("cp0ld.l    -12(%%a0),%%d0,#1,%0"   ::"n"(MCFCAU_XOR+MCFCAU_CA0));
++              asm("cp0ld.l    %%d3,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CA0):"d3");
++              asm("cp0st.l    %%d0,(%%a0)+,#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA0));
++      }
++
++      /* (c) */
++      asm("move.l     %0, %%a0"::"m"(digest):"a0");
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a0"); /* a */
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA1):"a0"); /* b */
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a0"); /* c */
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA3):"a0"); /* d */
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA4):"a0"); /* e */
++
++      /* (d) */
++      asm("moveq.l    #5, %%d0":::"d0");
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MVRA+MCFCAU_CA0));
++      asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA)); /*S^5(A)*/
++
++      tmp_p=(u32*)K;
++      asm("move.l     %0, %%a0"::"m"(tmp_p):"a0");
++      asm("move.l     %0, %%a1"::"m"(W):"a1");
++
++      for (i = 0; i < 20; i++) {
++              /* t = f1(b, c, d) + K1 + rol32(a, 5) + e + W[i]; */
++              /* e = d; d = c; c = rol32(b, 30); b = a; a = t; */
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFC)); /*f(b,c,d)*/
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA4)); /*+e*/
++              asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_ADR+MCFCAU_CAA)); /*+K*/
++              asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a1"); /*+W*/
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_SHS));
++      }
++
++      asm("add.l #4,%%a0"     :::"a0"); /* update K */
++
++      for (; i < 40; i ++) {
++              /* t = f2(b, c, d) + K2 + rol32(a, 5) + e + W[i]; */
++              /* e = d; d = c; c = rol32(b, 30); b = a; a = t; */
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH)); /*f(b,c,d)*/
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA4)); /*+e*/
++              asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_ADR+MCFCAU_CAA)); /*+K*/
++              asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a1"); /*+W*/
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_SHS));
++      }
++
++      asm("add.l #4,%%a0"     :::"a0"); /* update K */
++
++      for (; i < 60; i ++) {
++              /* t = f3(b, c, d) + K3 + rol32(a, 5) + e + W[i]; */
++              /* e = d; d = c; c = rol32(b, 30); b = a; a = t; */
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFM)); /*f(b,c,d)*/
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA4)); /*+e*/
++              asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_ADR+MCFCAU_CAA)); /*+K*/
++              asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a1"); /*+W*/
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_SHS));
++      }
++
++      asm("add.l #4,%%a0"     :::"a0"); /* update K */
++
++      for (; i < 80; i ++) {
++              /* t = f2(b, c, d) + K4 + rol32(a, 5) + e + W[i]; */
++              /* e = d; d = c; c = rol32(b, 30); b = a; a = t; */
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH)); /*f(b,c,d)*/
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA4)); /*+e*/
++              asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_ADR+MCFCAU_CAA)); /*+K*/
++              asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a1"); /*+W*/
++              asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_SHS));
++      }
++
++      /* (e) */
++      asm("move.l     %0, %%a0"::"m"(digest):"a0");
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA0):"a0"); /* +a */
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA1):"a0"); /* +b */
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA2):"a0"); /* +c */
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA3):"a0"); /* +d */
++      asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA4):"a0"); /* +e */
++
++      asm("cp0st.l    %%d0,-(%%a0),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA4):"a0");
++      asm("cp0st.l    %%d0,-(%%a0),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA3):"a0");
++      asm("cp0st.l    %%d0,-(%%a0),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA2):"a0");
++      asm("cp0st.l    %%d0,-(%%a0),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA1):"a0");
++      asm("cp0st.l    %%d0,-(%%a0),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA0):"a0");
++      spin_unlock_irqrestore(&mcfcau_lock, iflags);
++}
++
++static void mcfcau_sha1_init(struct crypto_tfm *tfm)
++{
++      struct mcfcau_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
++      static const struct mcfcau_sha1_ctx initstate = {
++        0,
++        { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 },
++        { 0, }
++      };
++
++      *sctx = initstate;
++}
++
++static void mcfcau_sha1_update(struct crypto_tfm *tfm, const u8 *data,
++                      unsigned int len)
++{
++      struct mcfcau_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
++      unsigned int partial, done;
++      const u8 *src;
++
++      partial = sctx->count & 0x3f;
++      sctx->count += len;
++      done = 0;
++      src = data;
++
++      if ((partial + len) > 63) {
++              u32 temp[MCFCAU_SHA1_WORKSPACE_WORDS];
++
++              if (partial) {
++                      done = -partial;
++                      memcpy(sctx->buffer + partial, data, done + 64);
++                      src = sctx->buffer;
++              }
++
++              do {
++                      mcfcau_sha1_transform(sctx->state, src, temp);
++                      done += 64;
++                      src = data + done;
++              } while (done + 63 < len);
++
++              memset(temp, 0, sizeof(temp));
++              partial = 0;
++      }
++      memcpy(sctx->buffer + partial, src, len - done);
++}
++
++
++/* Add padding and return the message digest. */
++static void mcfcau_sha1_final(struct crypto_tfm *tfm, u8 *out)
++{
++      struct mcfcau_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
++      u32 *dst = (u32 *)out;
++      u32 i, index, padlen;
++      u64 bits;
++      static const u8 padding[64] = { 0x80, };
++
++      bits = sctx->count << 3;
++
++      /* Pad out to 56 mod 64 */
++      index = sctx->count & 0x3f;
++      padlen = (index < 56) ? (56 - index) : ((64+56) - index);
++      mcfcau_sha1_update(tfm, padding, padlen);
++
++      /* Append length */
++      mcfcau_sha1_update(tfm, (const u8 *)&bits, sizeof(bits));
++
++      /* Store state in digest */
++      for (i = 0; i < 5; i++)
++              dst[i] = sctx->state[i];
++
++
++      /* Wipe context */
++      memset(sctx, 0, sizeof *sctx);
++}
++
++static struct crypto_alg mcfcau_sha1_alg = {
++      .cra_name       =       "sha1",
++      .cra_driver_name=       "sha1-mcfcau",
++      .cra_priority   =       MCFCAU_CRA_PRIORITY,
++      .cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
++      .cra_blocksize  =       MCFCAU_SHA1_HMAC_BLOCK_SIZE,
++      .cra_ctxsize    =       sizeof(struct mcfcau_sha1_ctx),
++      .cra_module     =       THIS_MODULE,
++      .cra_alignmask  =       3,
++      .cra_list       =       LIST_HEAD_INIT(mcfcau_sha1_alg.cra_list),
++      .cra_u          =       { .digest = {
++      .dia_digestsize =       MCFCAU_SHA1_DIGEST_SIZE,
++      .dia_init       =       mcfcau_sha1_init,
++      .dia_update     =       mcfcau_sha1_update,
++      .dia_final      =       mcfcau_sha1_final } }
++};
++
++static int __init init(void)
++{
++      int ret = crypto_register_alg(&mcfcau_sha1_alg);
++      printk(KERN_INFO MCFCAU_SHA1_DRIVER_DESC " "
++              MCFCAU_SHA1_DRIVER_VERSION " %s.\n",ret?"failed":"registered");
++      return ret;
++}
++
++static void __exit fini(void)
++{
++      crypto_unregister_alg(&mcfcau_sha1_alg);
++      printk(KERN_INFO MCFCAU_SHA1_DRIVER_DESC " "
++              MCFCAU_SHA1_DRIVER_VERSION " unregistered.\n");
++}
++
++module_init(init);
++module_exit(fini);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION(MCFCAU_SHA1_DRIVER_DESC);
++MODULE_AUTHOR("Andrey Butok");
+--- /dev/null
++++ b/drivers/crypto/mcfcau.c
+@@ -0,0 +1,32 @@
++/***************************************************************************
++ * mcfcau.c - Implementation of DES & Triple DES EDE Cipher Algorithms
++ *                for Freescale ColdFire Cryptographic Acceleration Unit (CAU).
++ *
++ * Author: Andrey Butok
++ * Copyright Freescale Semiconductor Inc.  2007
++ *
++ * NOTE: You can find the ColdFire CAU module on MCF54455 and MCF52235.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ ***************************************************************************
++ * Changes:
++ * v0.01      28 September 2006       Andrey Butok
++ *            Initial Release - developed on 2.6.20 Linux kernel.
++ */
++#include <linux/module.h>
++
++DEFINE_SPINLOCK(mcfcau_lock);
++EXPORT_SYMBOL(mcfcau_lock);
+--- /dev/null
++++ b/drivers/crypto/mcfcau.h
+@@ -0,0 +1,98 @@
++/***************************************************************************
++ * mcfcau.h - Common header file for Freescale ColdFire
++ *            Cryptographic Acceleration Unit (CAU) drivers.
++ *
++ * Author: Andrey Butok
++ * Copyright Freescale Semiconductor Inc.  2007
++ *
++ * NOTE: You can find the ColdFire CAU module on MCF54455 and MCF52235.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ ***************************************************************************
++ * Changes:
++ * v0.01      14 August 2007  Andrey Butok
++ */
++
++#ifndef MCFCAU_H
++#define MCFCAU_H
++
++#include <linux/spinlock.h>
++
++/* CAU Registers (CAx) */
++#define MCFCAU_CASR           (0x0)
++#define MCFCAU_CAA            (0x1)
++#define MCFCAU_CA0            (0x2)
++#define MCFCAU_CA1            (0x3)
++#define MCFCAU_CA2            (0x4)
++#define MCFCAU_CA3            (0x5)
++#define MCFCAU_CA4            (0x6)
++#define MCFCAU_CA5            (0x7)
++
++ /* CAU Commands */
++#define MCFCAU_CNOP           (0x000)
++#define MCFCAU_LDR            (0x010)
++#define MCFCAU_STR            (0x020)
++#define MCFCAU_ADR            (0x030)
++#define MCFCAU_RADR           (0x040)
++#define MCFCAU_ADRA           (0x050)
++#define MCFCAU_XOR            (0x060)
++#define MCFCAU_ROTL           (0x070)
++#define MCFCAU_MVRA           (0x080)
++#define MCFCAU_MVAR           (0x090)
++#define MCFCAU_AESS           (0x0A0)
++#define MCFCAU_AESIS          (0x0B0)
++#define MCFCAU_AESC           (0x0C0)
++#define MCFCAU_AESIC          (0x0D0)
++#define MCFCAU_AESR           (0x0E0)
++#define MCFCAU_AESIR          (0x0F0)
++#define MCFCAU_DESR           (0x100)
++#define MCFCAU_DESK           (0x110)
++#define MCFCAU_HASH           (0x120)
++#define MCFCAU_SHS            (0x130)
++#define MCFCAU_MDS            (0x140)
++#define MCFCAU_ILL            (0x1F0)
++
++/* DESR Fields */
++#define MCFCAU_IP             (0x08)  /* initial permutation */
++#define MCFCAU_FP             (0x04)  /* final permutation */
++#define MCFCAU_KSL1           (0x00)  /* key schedule left 1 bit */
++#define MCFCAU_KSL2           (0x01)  /* key schedule left 2 bits */
++#define MCFCAU_KSR1           (0x02)  /* key schedule right 1 bit */
++#define MCFCAU_KSR2           (0x03)  /* key schedule right 2 bits */
++
++/* DESK Field */
++#define MCFCAU_DC             (0x01)  /* decrypt key schedule */
++#define MCFCAU_CP             (0x02)  /* check parity */
++
++/* HASH Functions Codes */
++#define MCFCAU_HFF            (0x0)   /* MD5 F() CA1&CA2 | ~CA1&CA3 */
++#define MCFCAU_HFG            (0x1)   /* MD5 G() CA1&CA3 | CA2&~CA3 */
++#define MCFCAU_HFH            (0x2)   /* MD5 H(), SHA Parity() CA1^CA2^CA3 */
++#define MCFCAU_HFI            (0x3)   /* MD5 I() CA2^(CA1|~CA3) */
++#define MCFCAU_HFC            (0x4)   /* SHA Ch() CA1&CA2 ^ ~CA1&CA3 */
++#define MCFCAU_HFM            (0x5)   /* SHA Maj() CA1&CA2 ^ CA1&CA3 ^ CA2&CA3 */
++
++#define MCFCAU_CRA_PRIORITY   (300)
++
++extern spinlock_t mcfcau_lock;
++
++#ifdef DEBUG
++#define DBG(fmt, args...)     printk( "[%s]  " fmt , __FUNCTION__, ## args)
++#else
++#define DBG(fmt, args...)     do{}while(0)
++#endif
++
++#endif