diff options
author | John Crispin <john@openwrt.org> | 2011-05-29 21:19:26 +0000 |
---|---|---|
committer | John Crispin <john@openwrt.org> | 2011-05-29 21:19:26 +0000 |
commit | 6608f419d1a23762f34482b4628f9159bcb81fc2 (patch) | |
tree | 3f0b966c3d64ee995d89ee1a904c4306eedf846d /target/linux/lantiq/patches/270-crypto.patch | |
parent | c7cdee0230c999197b017fb4aadd49f5eb7dc0b8 (diff) | |
download | upstream-6608f419d1a23762f34482b4628f9159bcb81fc2.tar.gz upstream-6608f419d1a23762f34482b4628f9159bcb81fc2.tar.bz2 upstream-6608f419d1a23762f34482b4628f9159bcb81fc2.zip |
* backport 2.6.8 patches to .39 / .32.33
* remove lqtapi
* bump tapi/dsl to .39
* migrate to new ltq_ style api
* add amazon_se support
SVN-Revision: 27026
Diffstat (limited to 'target/linux/lantiq/patches/270-crypto.patch')
-rw-r--r-- | target/linux/lantiq/patches/270-crypto.patch | 6197 |
1 files changed, 0 insertions, 6197 deletions
diff --git a/target/linux/lantiq/patches/270-crypto.patch b/target/linux/lantiq/patches/270-crypto.patch deleted file mode 100644 index e99cfd381c..0000000000 --- a/target/linux/lantiq/patches/270-crypto.patch +++ /dev/null @@ -1,6197 +0,0 @@ ---- a/drivers/crypto/Kconfig -+++ b/drivers/crypto/Kconfig -@@ -252,4 +252,75 @@ - OMAP processors have AES module accelerator. Select this if you - want to use the OMAP module for AES algorithms. - -+config CRYPTO_DEV_LANTIQ -+ tristate "Support for Lantiq crypto engine" -+ select CRYPTO_ALGAPI -+ default y -+ help -+ Will support Lantiq crypto hardware -+ If you are unsure, say M. -+ -+menuconfig CRYPTO_DEV_LANTIQ_DES -+ bool "Lantiq crypto hardware for DES algorithm" -+ depends on CRYPTO_DEV_LANTIQ -+ select CRYPTO_BLKCIPHER -+ default y -+ help -+ Use crypto hardware for DES/3DES algorithm. -+ If unsure say N. -+ -+menuconfig CRYPTO_DEV_LANTIQ_AES -+ bool "Lantiq crypto hardware for AES algorithm" -+ depends on CRYPTO_DEV_LANTIQ -+ select CRYPTO_BLKCIPHER -+ default y -+ help -+ Use crypto hardware for AES algorithm. -+ If unsure say N. -+ -+menuconfig CRYPTO_DEV_LANTIQ_ARC4 -+ bool "Lantiq crypto hardware for ARC4 algorithm" -+ depends on (CRYPTO_DEV_LANTIQ && IFXMIPS_AR9) -+ select CRYPTO_BLKCIPHER -+ default y -+ help -+ Use crypto hardware for ARC4 algorithm. -+ If unsure say N. -+ -+menuconfig CRYPTO_DEV_LANTIQ_MD5 -+ bool "Lantiq crypto hardware for MD5 algorithm" -+ depends on CRYPTO_DEV_LANTIQ -+ select CRYPTO_BLKCIPHER -+ default y -+ help -+ Use crypto hardware for MD5 algorithm. -+ If unsure say N. -+ -+menuconfig CRYPTO_DEV_LANTIQ_SHA1 -+ bool "Lantiq crypto hardware for SHA1 algorithm" -+ depends on CRYPTO_DEV_LANTIQ -+ select CRYPTO_BLKCIPHER -+ default y -+ help -+ Use crypto hardware for SHA1 algorithm. -+ If unsure say N. -+ -+menuconfig CRYPTO_DEV_LANTIQ_SHA1_HMAC -+ bool "Lantiq crypto hardware for SHA1_HMAC algorithm" -+ depends on (CRYPTO_DEV_LANTIQ && IFXMIPS_AR9) -+ select CRYPTO_BLKCIPHER -+ default y -+ help -+ Use crypto hardware for SHA1_HMAC algorithm. -+ If unsure say N. -+ -+menuconfig CRYPTO_DEV_LANTIQ_MD5_HMAC -+ bool "Lantiq crypto hardware for MD5_HMAC algorithms" -+ depends on (CRYPTO_DEV_LANTIQ && IFXMIPS_AR9) -+ select CRYPTO_BLKCIPHER -+ default y -+ help -+ Use crypto hardware for MD5_HMAC algorithm. -+ If unsure say N. -+ - endif # CRYPTO_HW ---- /dev/null -+++ b/drivers/crypto/lantiq/Makefile -@@ -0,0 +1,11 @@ -+obj-$(CONFIG_CRYPTO_DEV_LANTIQ) += deu.o -+obj-$(CONFIG_CRYPTO_DEV_LANTIQ) += deu_falcon.o -+obj-$(CONFIG_CRYPTO_DEV_LANTIQ) += deu_danube.o -+obj-$(CONFIG_CRYPTO_DEV_LANTIQ) += deu_ar9.o -+obj-$(CONFIG_CRYPTO_DEV_LANTIQ_DES) += des.o -+obj-$(CONFIG_CRYPTO_DEV_LANTIQ_AES) += aes.o -+obj-$(CONFIG_CRYPTO_DEV_LANTIQ_ARC4) += arc4.o -+obj-$(CONFIG_CRYPTO_DEV_LANTIQ_SHA1) += sha1.o -+obj-$(CONFIG_CRYPTO_DEV_LANTIQ_SHA1_HMAC) += sha1_hmac.o -+obj-$(CONFIG_CRYPTO_DEV_LANTIQ_MD5) += md5.o -+obj-$(CONFIG_CRYPTO_DEV_LANTIQ_MD5_HMAC) += md5_hmac.o ---- /dev/null -+++ b/drivers/crypto/lantiq/aes.c -@@ -0,0 +1,1029 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief Lantiq DEU driver module -+*/ -+ -+/** -+ \file aes.c -+ \ingroup LQ_DEU -+ \brief AES Encryption Driver main file -+*/ -+ -+/** -+ \defgroup LQ_AES_FUNCTIONS LQ_AES_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief Lantiq AES driver Functions -+*/ -+ -+#include <linux/version.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <linux/crypto.h> -+#include <linux/interrupt.h> -+#include <linux/delay.h> -+#include <asm/byteorder.h> -+#include <crypto/algapi.h> -+#include "deu.h" -+ -+#ifdef CONFIG_CRYPTO_DEV_DMA -+# include "deu_dma.h" -+#endif -+ -+static spinlock_t cipher_lock; -+ -+/* Definition of constants */ -+ -+#define AES_MIN_KEY_SIZE 16 -+#define AES_MAX_KEY_SIZE 32 -+#define AES_BLOCK_SIZE 16 -+#define CTR_RFC3686_NONCE_SIZE 4 -+#define CTR_RFC3686_IV_SIZE 8 -+#define CTR_RFC3686_MAX_KEY_SIZE (AES_MAX_KEY_SIZE \ -+ + CTR_RFC3686_NONCE_SIZE) -+ -+struct aes_ctx { -+ int key_length; -+ u32 buf[AES_MAX_KEY_SIZE]; -+ u8 nonce[CTR_RFC3686_NONCE_SIZE]; -+}; -+ -+/** \fn int aes_set_key(struct crypto_tfm *tfm, const uint8_t *in_key, unsigned int key_len) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief sets the AES keys -+ * \param tfm linux crypto algo transform -+ * \param in_key input key -+ * \param key_len key lengths of 16, 24 and 32 bytes supported -+ * \return -EINVAL - bad key length, 0 - SUCCESS -+*/ -+static int aes_set_key(struct crypto_tfm *tfm, -+ const u8 *in_key, -+ unsigned int key_len) -+{ -+ struct aes_ctx *ctx = crypto_tfm_ctx(tfm); -+ u32 *flags = &tfm->crt_flags; -+ -+ DPRINTF(0, "ctx @%p, key_len %d\n", ctx, key_len); -+ -+ if (key_len != 16 && key_len != 24 && key_len != 32) { -+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; -+ return -EINVAL; -+ } -+ -+ ctx->key_length = key_len; -+ memcpy((u8 *)(ctx->buf), in_key, key_len); -+ -+ return 0; -+} -+ -+#ifndef CONFIG_CRYPTO_DEV_DMA -+/** \fn void deu_aes(void *ctx_arg, u8 *out_arg, const u8 *in_arg, u8 *iv_arg, size_t nbytes, int encdec, int mode) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief main interface to AES hardware -+ * \param ctx_arg crypto algo context -+ * \param out_arg output bytestream -+ * \param in_arg input bytestream -+ * \param iv_arg initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param mode operation mode such as ebc, cbc, ctr -+ * -+*/ -+static void deu_aes(void *ctx_arg, -+ u8 *out_arg, -+ const u8 *in_arg, -+ u8 *iv_arg, -+ size_t nbytes, -+ int encdec, -+ int mode) -+#else -+ -+/** \fn void deu_aes_core(void *ctx_arg, u8 *out_arg, const u8 *in_arg, u8 *iv_arg, size_t nbytes, int encdec, int mode) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief main interface to AES hardware -+ * \param ctx_arg crypto algo context -+ * \param out_arg output bytestream -+ * \param in_arg input bytestream -+ * \param iv_arg initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param mode operation mode such as ebc, cbc, ctr -+ * -+*/ -+static void deu_aes_core(void *ctx_arg, -+ u8 *out_arg, -+ const u8 *in_arg, -+ u8 *iv_arg, -+ size_t nbytes, -+ int encdec, -+ int mode) -+#endif -+ -+{ -+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -+ volatile struct deu_aes *aes = (volatile struct deu_aes *)AES_START; -+ struct aes_ctx *ctx = (struct aes_ctx *)ctx_arg; -+ u32 *in_key = ctx->buf; -+ ulong flag; -+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -+ int key_len = ctx->key_length; -+ -+#ifndef CONFIG_CRYPTO_DEV_DMA -+ int i = 0; -+ int byte_cnt = nbytes; -+#else -+ volatile struct deu_dma *dma = (struct deu_dma *)LQ_DEU_DMA_CON; -+ struct dma_device_info *dma_device = lq_deu[0].dma_device; -+ /* struct deu_drv_priv *deu_priv = -+ * (struct deu_drv_priv *)dma_device->priv; */ -+ int wlen = 0; -+ u32 *outcopy = NULL; -+ u32 *dword_mem_aligned_in = NULL; -+ -+# ifdef CONFIG_CRYPTO_DEV_POLL_DMA -+ u32 timeout = 0; -+ u32 *out_dma = NULL; -+# endif -+#endif -+ -+ DPRINTF(0, "ctx @%p, mode %d, encdec %d\n", ctx, mode, encdec); -+ -+ CRTCL_SECT_START; -+ -+ /* 128, 192 or 256 bit key length */ -+ aes->ctrl.K = key_len / 8 - 2; -+ if (key_len == 128 / 8) { -+ aes->K3R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 0)); -+ aes->K2R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 1)); -+ aes->K1R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 2)); -+ aes->K0R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 3)); -+ } -+ else if (key_len == 192 / 8) { -+ aes->K5R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 0)); -+ aes->K4R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 1)); -+ aes->K3R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 2)); -+ aes->K2R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 3)); -+ aes->K1R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 4)); -+ aes->K0R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 5)); -+ } -+ else if (key_len == 256 / 8) { -+ aes->K7R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 0)); -+ aes->K6R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 1)); -+ aes->K5R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 2)); -+ aes->K4R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 3)); -+ aes->K3R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 4)); -+ aes->K2R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 5)); -+ aes->K1R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 6)); -+ aes->K0R = DEU_ENDIAN_SWAP(*((u32 *)in_key + 7)); -+ } -+ else { -+ CRTCL_SECT_END; -+ return; /* -EINVAL; */ -+ } -+ -+ /* let HW pre-process DEcryption key in any case (even if -+ ENcryption is used). Key Valid (KV) bit is then only -+ checked in decryption routine! */ -+ aes->ctrl.PNK = 1; -+ -+#ifdef CONFIG_CRYPTO_DEV_DMA -+ while (aes->ctrl.BUS) { -+ /* this will not take long */ -+ } -+ AES_DMA_MISC_CONFIG(); -+#endif -+ -+ aes->ctrl.E_D = !encdec; /* encryption */ -+ aes->ctrl.O = mode; /* 0 ECB 1 CBC 2 OFB 3 CFB 4 CTR */ -+ aes->ctrl.SM = 1; /* start after writing input register */ -+ aes->ctrl.DAU = 0; /* Disable Automatic Update of init -+ vector */ -+ aes->ctrl.ARS = 1; /* Autostart Select - write to IHR */ -+ -+ /* aes->ctrl.F = 128; */ /* default; only for CFB and OFB modes; -+ change only for -+ customer-specific apps */ -+ if (mode > 0) { -+ aes->IV3R = DEU_ENDIAN_SWAP(*(u32 *)iv_arg); -+ aes->IV2R = DEU_ENDIAN_SWAP(*((u32 *)iv_arg + 1)); -+ aes->IV1R = DEU_ENDIAN_SWAP(*((u32 *)iv_arg + 2)); -+ aes->IV0R = DEU_ENDIAN_SWAP(*((u32 *)iv_arg + 3)); -+ }; -+ -+#ifndef CONFIG_CRYPTO_DEV_DMA -+ i = 0; -+ while (byte_cnt >= 16) { -+ aes->ID3R = INPUT_ENDIAN_SWAP(*((u32 *)in_arg + (i * 4) + 0)); -+ aes->ID2R = INPUT_ENDIAN_SWAP(*((u32 *)in_arg + (i * 4) + 1)); -+ aes->ID1R = INPUT_ENDIAN_SWAP(*((u32 *)in_arg + (i * 4) + 2)); -+ /* start crypto */ -+ aes->ID0R = INPUT_ENDIAN_SWAP(*((u32 *)in_arg + (i * 4) + 3)); -+ -+ while (aes->ctrl.BUS) { -+ /* this will not take long */ -+ } -+ -+ *((volatile u32 *)out_arg + (i * 4) + 0) = aes->OD3R; -+ *((volatile u32 *)out_arg + (i * 4) + 1) = aes->OD2R; -+ *((volatile u32 *)out_arg + (i * 4) + 2) = aes->OD1R; -+ *((volatile u32 *)out_arg + (i * 4) + 3) = aes->OD0R; -+ -+ i++; -+ byte_cnt -= 16; -+ } -+#else /* dma */ -+ /* Prepare Rx buf length used in dma psuedo interrupt */ -+ /* deu_priv->deu_rx_buf = out_arg; */ -+ /* deu_priv->deu_rx_len = nbytes; */ -+ -+ /* memory alignment issue */ -+ dword_mem_aligned_in = (u32 *)DEU_DWORD_REORDERING(in_arg, -+ aes_buff_in, -+ BUFFER_IN, nbytes); -+ -+ dma->ctrl.ALGO = 1; /* AES */ -+ dma->ctrl.BS = 0; -+ aes->ctrl.DAU = 0; -+ dma->ctrl.EN = 1; -+ -+ while (aes->ctrl.BUS) { -+ /* wait for AES to be ready */ -+ }; -+ -+ wlen = dma_device_write(dma_device, (u8 *)dword_mem_aligned_in, -+ nbytes, NULL); -+ if (wlen != nbytes) { -+ dma->ctrl.EN = 0; -+ CRTCL_SECT_END; -+ printk(KERN_ERR "[%s %s %d]: dma_device_write fail!\n", -+ __FILE__, __func__, __LINE__); -+ return; /* -EINVAL; */ -+ } -+ -+ WAIT_AES_DMA_READY(); -+ -+# ifdef CONFIG_CRYPTO_DEV_POLL_DMA -+ outcopy = (u32 *)DEU_DWORD_REORDERING(out_arg, aes_buff_out, -+ BUFFER_OUT, nbytes); -+ -+ /* polling DMA rx channel */ -+ while ((dma_device_read(dma_device, (u8 **)&out_dma, NULL)) == 0) { -+ timeout++; -+ -+ if (timeout >= 333000) { -+ dma->ctrl.EN = 0; -+ CRTCL_SECT_END; -+ printk (KERN_ERR "[%s %s %d]: timeout!!\n", -+ __FILE__, __func__, __LINE__); -+ return; /* -EINVAL; */ -+ } -+ } -+ -+ WAIT_AES_DMA_READY(); -+ -+ AES_MEMORY_COPY(outcopy, out_dma, out_arg, nbytes); -+ -+# else /* not working at the moment.. */ -+ CRTCL_SECT_END; -+ -+ /* sleep and wait for Rx finished */ -+ DEU_WAIT_EVENT(deu_priv->deu_thread_wait, DEU_EVENT, -+ deu_priv->deu_event_flags); -+ -+ CRTCL_SECT_START; -+# endif -+ -+#endif /* dma */ -+ -+ /* tc.chen : copy iv_arg back */ -+ if (mode > 0) { -+ *((u32 *)iv_arg) = DEU_ENDIAN_SWAP(*((u32 *)iv_arg)); -+ *((u32 *)iv_arg + 1) = DEU_ENDIAN_SWAP(*((u32 *)iv_arg + 1)); -+ *((u32 *)iv_arg + 2) = DEU_ENDIAN_SWAP(*((u32 *)iv_arg + 2)); -+ *((u32 *)iv_arg + 3) = DEU_ENDIAN_SWAP(*((u32 *)iv_arg + 3)); -+ } -+ -+ CRTCL_SECT_END; -+} -+ -+/** \fn int ctr_rfc3686_aes_set_key(struct crypto_tfm *tfm, const uint8_t *in_key, unsigned int key_len) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief sets RFC3686 key -+ * \param tfm linux crypto algo transform -+ * \param in_key input key -+ * \param key_len key lengths of 20, 28 and 36 bytes supported; last 4 bytes is nonce -+ * \return 0 - SUCCESS -+ * -EINVAL - bad key length -+*/ -+static int ctr_rfc3686_aes_set_key(struct crypto_tfm *tfm, -+ const uint8_t *in_key, -+ unsigned int key_len) -+{ -+ struct aes_ctx *ctx = crypto_tfm_ctx(tfm); -+ u32 *flags = &tfm->crt_flags; -+ -+ memcpy(ctx->nonce, in_key + (key_len - CTR_RFC3686_NONCE_SIZE), -+ CTR_RFC3686_NONCE_SIZE); -+ -+ key_len -= CTR_RFC3686_NONCE_SIZE; /* remove 4 bytes of nonce */ -+ -+ if (key_len != 16 && key_len != 24 && key_len != 32) { -+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; -+ return -EINVAL; -+ } -+ -+ ctx->key_length = key_len; -+ -+ memcpy((u8 *)(ctx->buf), in_key, key_len); -+ -+ return 0; -+} -+ -+/** \fn void deu_aes(void *ctx_arg, u8 *out_arg, const u8 *in_arg, u8 *iv_arg, u32 nbytes, int encdec, int mode) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief main interface with DEU hardware in DMA mode -+ * \param ctx_arg crypto algo context -+ * \param out_arg output bytestream -+ * \param in_arg input bytestream -+ * \param iv_arg initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param mode operation mode such as ebc, cbc, ctr -+*/ -+ -+#ifdef CONFIG_CRYPTO_DEV_DMA -+static void deu_aes(void *ctx_arg, -+ u8 *out_arg, -+ const u8 *in_arg, -+ u8 *iv_arg, -+ u32 nbytes, -+ int encdec, -+ int mode) -+{ -+ u32 remain = nbytes; -+ u32 inc; -+ -+ while (remain > 0) { -+ if (remain >= DEU_MAX_PACKET_SIZE) -+ inc = DEU_MAX_PACKET_SIZE; -+ else -+ inc = remain; -+ -+ remain -= inc; -+ -+ deu_aes_core(ctx_arg, out_arg, in_arg, iv_arg, inc, encdec, -+ mode); -+ -+ out_arg += inc; -+ in_arg += inc; -+ } -+} -+#endif -+ -+/* definitions from linux/include/crypto.h: -+#define CRYPTO_TFM_MODE_ECB 0x00000001 -+#define CRYPTO_TFM_MODE_CBC 0x00000002 -+#define CRYPTO_TFM_MODE_CFB 0x00000004 -+#define CRYPTO_TFM_MODE_CTR 0x00000008 -+#define CRYPTO_TFM_MODE_OFB 0x00000010 -+but hardware definition: 0 ECB 1 CBC 2 OFB 3 CFB 4 CTR */ -+ -+/** \fn void deu_aes_ecb(void *ctx, uint8_t *dst, const uint8_t *src, uint8_t *iv, size_t nbytes, int encdec, int inplace) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief sets AES hardware to ECB mode -+ * \param ctx crypto algo context -+ * \param dst output bytestream -+ * \param src input bytestream -+ * \param iv initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param inplace not used -+*/ -+static void deu_aes_ecb(void *ctx, -+ uint8_t *dst, -+ const uint8_t *src, -+ uint8_t *iv, -+ size_t nbytes, -+ int encdec, -+ int inplace) -+{ -+ deu_aes(ctx, dst, src, NULL, nbytes, encdec, 0); -+} -+ -+/** \fn void deu_aes_cbc(void *ctx, uint8_t *dst, const uint8_t *src, uint8_t *iv, size_t nbytes, int encdec, int inplace) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief sets AES hardware to CBC mode -+ * \param ctx crypto algo context -+ * \param dst output bytestream -+ * \param src input bytestream -+ * \param iv initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param inplace not used -+*/ -+static void deu_aes_cbc(void *ctx, -+ uint8_t *dst, -+ const uint8_t *src, -+ uint8_t *iv, -+ size_t nbytes, -+ int encdec, -+ int inplace) -+{ -+ deu_aes(ctx, dst, src, iv, nbytes, encdec, 1); -+} -+ -+#if 0 -+/** \fn void deu_aes_ofb(void *ctx, uint8_t *dst, const uint8_t *src, uint8_t *iv, size_t nbytes, int encdec, int inplace) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief sets AES hardware to OFB mode -+ * \param ctx crypto algo context -+ * \param dst output bytestream -+ * \param src input bytestream -+ * \param iv initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param inplace not used -+*/ -+static void deu_aes_ofb(void *ctx, -+ uint8_t *dst, -+ const uint8_t *src, -+ uint8_t *iv, -+ size_t nbytes, -+ int encdec, -+ int inplace) -+{ -+ deu_aes(ctx, dst, src, iv, nbytes, encdec, 2); -+} -+ -+/** \fn void deu_aes_cfb(void *ctx, uint8_t *dst, const uint8_t *src, uint8_t *iv, size_t nbytes, int encdec, int inplace) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief sets AES hardware to CFB mode -+ * \param ctx crypto algo context -+ * \param dst output bytestream -+ * \param src input bytestream -+ * \param iv initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param inplace not used -+*/ -+static void deu_aes_cfb(void *ctx, -+ uint8_t *dst, -+ const uint8_t *src, -+ uint8_t *iv, -+ size_t nbytes, -+ int encdec, -+ int inplace) -+{ -+ deu_aes(ctx, dst, src, iv, nbytes, encdec, 3); -+} -+#endif -+ -+/** \fn void deu_aes_ctr(void *ctx, uint8_t *dst, const uint8_t *src, uint8_t *iv, size_t nbytes, int encdec, int inplace) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief sets AES hardware to CTR mode -+ * \param ctx crypto algo context -+ * \param dst output bytestream -+ * \param src input bytestream -+ * \param iv initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param inplace not used -+*/ -+static void deu_aes_ctr(void *ctx, -+ uint8_t *dst, -+ const uint8_t *src, -+ uint8_t *iv, -+ size_t nbytes, -+ int encdec, -+ int inplace) -+{ -+ deu_aes(ctx, dst, src, iv, nbytes, encdec, 4); -+} -+ -+/** \fn void aes_encrypt(struct crypto_tfm *tfm, uint8_t *out, const uint8_t *in) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief encrypt AES_BLOCK_SIZE of data -+ * \param tfm linux crypto algo transform -+ * \param out output bytestream -+ * \param in input bytestream -+*/ -+static void aes_encrypt(struct crypto_tfm *tfm, uint8_t *out, const uint8_t *in) -+{ -+ struct aes_ctx *ctx = crypto_tfm_ctx(tfm); -+ deu_aes(ctx, out, in, NULL, AES_BLOCK_SIZE, CRYPTO_DIR_ENCRYPT, 0); -+} -+ -+/** \fn void aes_decrypt(struct crypto_tfm *tfm, uint8_t *out, const uint8_t *in) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief decrypt AES_BLOCK_SIZE of data -+ * \param tfm linux crypto algo transform -+ * \param out output bytestream -+ * \param in input bytestream -+*/ -+static void aes_decrypt(struct crypto_tfm *tfm, uint8_t *out, const uint8_t *in) -+{ -+ struct aes_ctx *ctx = crypto_tfm_ctx(tfm); -+ deu_aes(ctx, out, in, NULL, AES_BLOCK_SIZE, CRYPTO_DIR_DECRYPT, 0); -+} -+ -+/* -+ * \brief AES function mappings -+*/ -+static struct crypto_alg aes_alg = { -+ .cra_name = "aes", -+ .cra_driver_name = "lq_deu-aes", -+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct aes_ctx), -+ .cra_module = THIS_MODULE, -+ .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), -+ .cra_u = { -+ .cipher = { -+ .cia_min_keysize = AES_MIN_KEY_SIZE, -+ .cia_max_keysize = AES_MAX_KEY_SIZE, -+ .cia_setkey = aes_set_key, -+ .cia_encrypt = aes_encrypt, -+ .cia_decrypt = aes_decrypt, -+ } -+ } -+}; -+ -+/** \fn int ecb_aes_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief ECB AES encrypt using linux crypto blkcipher -+ * \param desc blkcipher descriptor -+ * \param dst output scatterlist -+ * \param src input scatterlist -+ * \param nbytes data size in bytes -+ * \return err -+*/ -+static int ecb_aes_encrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ while ((nbytes = walk.nbytes)) { -+ nbytes -= (nbytes % AES_BLOCK_SIZE); -+ deu_aes_ecb(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ NULL, nbytes, CRYPTO_DIR_ENCRYPT, 0); -+ nbytes &= AES_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/** \fn int ecb_aes_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief ECB AES decrypt using linux crypto blkcipher -+ * \param desc blkcipher descriptor -+ * \param dst output scatterlist -+ * \param src input scatterlist -+ * \param nbytes data size in bytes -+ * \return err -+*/ -+static int ecb_aes_decrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ while ((nbytes = walk.nbytes)) { -+ nbytes -= (nbytes % AES_BLOCK_SIZE); -+ deu_aes_ecb(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ NULL, nbytes, CRYPTO_DIR_DECRYPT, 0); -+ nbytes &= AES_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/* -+ * \brief AES function mappings -+*/ -+static struct crypto_alg ecb_aes_alg = { -+ .cra_name = "ecb(aes)", -+ .cra_driver_name = "lq_deu-ecb(aes)", -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct aes_ctx), -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_list = LIST_HEAD_INIT(ecb_aes_alg.cra_list), -+ .cra_u = { -+ .blkcipher = { -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .setkey = aes_set_key, -+ .encrypt = ecb_aes_encrypt, -+ .decrypt = ecb_aes_decrypt, -+ } -+ } -+}; -+ -+/** \fn int cbc_aes_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief CBC AES encrypt using linux crypto blkcipher -+ * \param desc blkcipher descriptor -+ * \param dst output scatterlist -+ * \param src input scatterlist -+ * \param nbytes data size in bytes -+ * \return err -+*/ -+static int cbc_aes_encrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ while ((nbytes = walk.nbytes)) { -+ u8 *iv = walk.iv; -+ nbytes -= (nbytes % AES_BLOCK_SIZE); -+ deu_aes_cbc(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ iv, nbytes, CRYPTO_DIR_ENCRYPT, 0); -+ nbytes &= AES_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/** \fn int cbc_aes_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief CBC AES decrypt using linux crypto blkcipher -+ * \param desc blkcipher descriptor -+ * \param dst output scatterlist -+ * \param src input scatterlist -+ * \param nbytes data size in bytes -+ * \return err -+*/ -+static int cbc_aes_decrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ while ((nbytes = walk.nbytes)) { -+ u8 *iv = walk.iv; -+ nbytes -= (nbytes % AES_BLOCK_SIZE); -+ deu_aes_cbc(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ iv, nbytes, CRYPTO_DIR_DECRYPT, 0); -+ nbytes &= AES_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/* -+ * \brief AES function mappings -+*/ -+static struct crypto_alg cbc_aes_alg = { -+ .cra_name = "cbc(aes)", -+ .cra_driver_name = "lq_deu-cbc(aes)", -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct aes_ctx), -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_list = LIST_HEAD_INIT(cbc_aes_alg.cra_list), -+ .cra_u = { -+ .blkcipher = { -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .setkey = aes_set_key, -+ .encrypt = cbc_aes_encrypt, -+ .decrypt = cbc_aes_decrypt, -+ } -+ } -+}; -+ -+/** \fn int ctr_basic_aes_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief Counter mode AES encrypt using linux crypto blkcipher -+ * \param desc blkcipher descriptor -+ * \param dst output scatterlist -+ * \param src input scatterlist -+ * \param nbytes data size in bytes -+ * \return err -+*/ -+static int ctr_basic_aes_encrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ while ((nbytes = walk.nbytes)) { -+ u8 *iv = walk.iv; -+ nbytes -= (nbytes % AES_BLOCK_SIZE); -+ deu_aes_ctr(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ iv, nbytes, CRYPTO_DIR_ENCRYPT, 0); -+ nbytes &= AES_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/** \fn int ctr_basic_aes_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief Counter mode AES decrypt using linux crypto blkcipher -+ * \param desc blkcipher descriptor -+ * \param dst output scatterlist -+ * \param src input scatterlist -+ * \param nbytes data size in bytes -+ * \return err -+*/ -+static int ctr_basic_aes_decrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ while ((nbytes = walk.nbytes)) { -+ u8 *iv = walk.iv; -+ nbytes -= (nbytes % AES_BLOCK_SIZE); -+ deu_aes_ctr(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ iv, nbytes, CRYPTO_DIR_DECRYPT, 0); -+ nbytes &= AES_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/* -+ * \brief AES function mappings -+*/ -+static struct crypto_alg ctr_basic_aes_alg = { -+ .cra_name = "ctr(aes)", -+ .cra_driver_name = "lq_deu-ctr(aes)", -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct aes_ctx), -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_list = LIST_HEAD_INIT(ctr_basic_aes_alg.cra_list), -+ .cra_u = { -+ .blkcipher = { -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .setkey = aes_set_key, -+ .encrypt = ctr_basic_aes_encrypt, -+ .decrypt = ctr_basic_aes_decrypt, -+ } -+ } -+}; -+ -+/** \fn int ctr_rfc3686_aes_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief Counter mode AES (rfc3686) encrypt using linux crypto blkcipher -+ * \param desc blkcipher descriptor -+ * \param dst output scatterlist -+ * \param src input scatterlist -+ * \param nbytes data size in bytes -+ * \return err -+*/ -+static int ctr_rfc3686_aes_encrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ u8 rfc3686_iv[16]; -+ -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ /* set up counter block */ -+ memcpy(rfc3686_iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE); -+ memcpy(rfc3686_iv + CTR_RFC3686_NONCE_SIZE, walk.iv, -+ CTR_RFC3686_IV_SIZE); -+ -+ /* initialize counter portion of counter block */ -+ *(__be32 *)(rfc3686_iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) = -+ cpu_to_be32(1); -+ -+ while ((nbytes = walk.nbytes)) { -+ nbytes -= (nbytes % AES_BLOCK_SIZE); -+ deu_aes_ctr(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ rfc3686_iv, nbytes, CRYPTO_DIR_ENCRYPT, 0); -+ nbytes &= AES_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/** \fn int ctr_rfc3686_aes_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief Counter mode AES (rfc3686) decrypt using linux crypto blkcipher -+ * \param desc blkcipher descriptor -+ * \param dst output scatterlist -+ * \param src input scatterlist -+ * \param nbytes data size in bytes -+ * \return err -+*/ -+static int ctr_rfc3686_aes_decrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ u8 rfc3686_iv[16]; -+ -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ /* set up counter block */ -+ memcpy(rfc3686_iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE); -+ memcpy(rfc3686_iv + CTR_RFC3686_NONCE_SIZE, walk.iv, -+ CTR_RFC3686_IV_SIZE); -+ -+ /* initialize counter portion of counter block */ -+ *(__be32 *)(rfc3686_iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) = -+ cpu_to_be32(1); -+ -+ while ((nbytes = walk.nbytes)) { -+ nbytes -= (nbytes % AES_BLOCK_SIZE); -+ deu_aes_ctr(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ rfc3686_iv, nbytes, CRYPTO_DIR_DECRYPT, 0); -+ nbytes &= AES_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/* -+ * \brief AES function mappings -+*/ -+static struct crypto_alg ctr_rfc3686_aes_alg = { -+ .cra_name = "rfc3686(ctr(aes))", -+ .cra_driver_name = "lq_deu-ctr-rfc3686(aes)", -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct aes_ctx), -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_list = LIST_HEAD_INIT(ctr_rfc3686_aes_alg.cra_list), -+ .cra_u = { -+ .blkcipher = { -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = CTR_RFC3686_MAX_KEY_SIZE, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .setkey = ctr_rfc3686_aes_set_key, -+ .encrypt = ctr_rfc3686_aes_encrypt, -+ .decrypt = ctr_rfc3686_aes_decrypt, -+ } -+ } -+}; -+ -+/** \fn int lq_deu_init_aes (void) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief function to initialize AES driver -+ * \return ret -+*/ -+int lq_deu_init_aes(void) -+{ -+ int ret; -+ -+ if ((ret = crypto_register_alg(&aes_alg))) -+ goto aes_err; -+ -+ if ((ret = crypto_register_alg(&ecb_aes_alg))) -+ goto ecb_aes_err; -+ -+ if ((ret = crypto_register_alg(&cbc_aes_alg))) -+ goto cbc_aes_err; -+ -+ if ((ret = crypto_register_alg(&ctr_basic_aes_alg))) -+ goto ctr_basic_aes_err; -+ -+ if ((ret = crypto_register_alg(&ctr_rfc3686_aes_alg))) -+ goto ctr_rfc3686_aes_err; -+ -+ deu_aes_chip_init(); -+ -+ CRTCL_SECT_INIT; -+ -+#ifdef CONFIG_CRYPTO_DEV_DMA -+ if (ALLOCATE_MEMORY(BUFFER_IN, AES_ALGO) < 0) { -+ printk(KERN_ERR "[%s %s %d]: malloc memory fail!\n", -+ __FILE__, __func__, __LINE__); -+ goto ctr_rfc3686_aes_err; -+ } -+ if (ALLOCATE_MEMORY(BUFFER_OUT, AES_ALGO) < 0) { -+ printk(KERN_ERR "[%s %s %d]: malloc memory fail!\n", -+ __FILE__, __func__, __LINE__); -+ goto ctr_rfc3686_aes_err; -+ } -+#endif -+ -+ printk(KERN_NOTICE "Lantiq DEU AES initialized%s.\n", -+ disable_deudma ? "" : " (DMA)"); -+ return ret; -+ -+ctr_rfc3686_aes_err: -+ crypto_unregister_alg(&ctr_rfc3686_aes_alg); -+ printk(KERN_ERR "Lantiq ctr_rfc3686_aes initialization failed!\n"); -+ return ret; -+ctr_basic_aes_err: -+ crypto_unregister_alg(&ctr_basic_aes_alg); -+ printk(KERN_ERR "Lantiq ctr_basic_aes initialization failed!\n"); -+ return ret; -+cbc_aes_err: -+ crypto_unregister_alg(&cbc_aes_alg); -+ printk(KERN_ERR "Lantiq cbc_aes initialization failed!\n"); -+ return ret; -+ecb_aes_err: -+ crypto_unregister_alg(&ecb_aes_alg); -+ printk(KERN_ERR "Lantiq aes initialization failed!\n"); -+ return ret; -+aes_err: -+ printk(KERN_ERR "Lantiq DEU AES initialization failed!\n"); -+ return ret; -+} -+ -+/** \fn void lq_deu_fini_aes(void) -+ * \ingroup LQ_AES_FUNCTIONS -+ * \brief unregister aes driver -+*/ -+void lq_deu_fini_aes(void) -+{ -+ crypto_unregister_alg(&aes_alg); -+ crypto_unregister_alg(&ecb_aes_alg); -+ crypto_unregister_alg(&cbc_aes_alg); -+ crypto_unregister_alg(&ctr_basic_aes_alg); -+ crypto_unregister_alg(&ctr_rfc3686_aes_alg); -+ -+#ifdef CONFIG_CRYPTO_DEV_DMA -+ FREE_MEMORY(aes_buff_in); -+ FREE_MEMORY(aes_buff_out); -+#endif -+} ---- /dev/null -+++ b/drivers/crypto/lantiq/arc4.c -@@ -0,0 +1,397 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief Lantiq DEU driver module -+*/ -+ -+/** -+ \file arc4.c -+ \ingroup LQ_DEU -+ \brief ARC4 encryption DEU driver file -+*/ -+ -+/** -+ \defgroup LQ_ARC4_FUNCTIONS LQ_ARC4_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief Lantiq DEU driver functions -+*/ -+ -+#include <linux/version.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <linux/crypto.h> -+#include <crypto/algapi.h> -+#include <linux/interrupt.h> -+#include <asm/byteorder.h> -+#include <linux/delay.h> -+ -+#ifdef CONFIG_SOL_LANTIQ_XWAY -+ -+#include "deu.h" -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ -+static spinlock_t cipher_lock; -+ -+/* Preprocessor declerations */ -+#define ARC4_MIN_KEY_SIZE 1 -+/* #define ARC4_MAX_KEY_SIZE 256 */ -+#define ARC4_MAX_KEY_SIZE 16 -+#define ARC4_BLOCK_SIZE 1 -+ -+/* -+ * \brief arc4 private structure -+*/ -+struct arc4_ctx { -+ int key_length; -+ u8 buf[120]; -+}; -+ -+/** \fn static void deu_arc4(void *ctx_arg, u8 *out_arg, const u8 *in_arg, u8 *iv_arg, u32 nbytes, int encdec, int mode) -+ \ingroup LQ_ARC4_FUNCTIONS -+ \brief main interface to AES hardware -+ \param ctx_arg crypto algo context -+ \param out_arg output bytestream -+ \param in_arg input bytestream -+ \param iv_arg initialization vector -+ \param nbytes length of bytestream -+ \param encdec 1 for encrypt; 0 for decrypt -+ \param mode operation mode such as ebc, cbc, ctr -+*/ -+static void deu_arc4(void *ctx_arg, -+ u8 *out_arg, -+ const u8 *in_arg, -+ u8 *iv_arg, -+ u32 nbytes, -+ int encdec, -+ int mode) -+{ -+ volatile struct deu_arc4 *arc4 = (struct deu_arc4 *) ARC4_START; -+ int i = 0; -+ ulong flag; -+ -+#if 1 /* need to handle nbytes not multiple of 16 */ -+ volatile u32 tmp_array32[4]; -+ volatile u8 *tmp_ptr8; -+ int remaining_bytes, j; -+#endif -+ -+ CRTCL_SECT_START; -+ -+ arc4->IDLEN = nbytes; -+ -+#if 1 -+ while (i < nbytes) { -+ arc4->ID3R = *((u32 *) in_arg + (i>>2) + 0); -+ arc4->ID2R = *((u32 *) in_arg + (i>>2) + 1); -+ arc4->ID1R = *((u32 *) in_arg + (i>>2) + 2); -+ arc4->ID0R = *((u32 *) in_arg + (i>>2) + 3); -+ -+ arc4->ctrl.GO = 1; -+ -+ while (arc4->ctrl.BUS) { -+ /* this will not take long */ } -+ -+#if 1 -+ /* need to handle nbytes not multiple of 16 */ -+ tmp_array32[0] = arc4->OD3R; -+ tmp_array32[1] = arc4->OD2R; -+ tmp_array32[2] = arc4->OD1R; -+ tmp_array32[3] = arc4->OD0R; -+ -+ remaining_bytes = nbytes - i; -+ if (remaining_bytes > 16) -+ remaining_bytes = 16; -+ -+ tmp_ptr8 = (u8 *)&tmp_array32[0]; -+ for (j = 0; j < remaining_bytes; j++) -+ *out_arg++ = *tmp_ptr8++; -+#else -+ *((u32 *) out_arg + (i>>2) + 0) = arc4->OD3R; -+ *((u32 *) out_arg + (i>>2) + 1) = arc4->OD2R; -+ *((u32 *) out_arg + (i>>2) + 2) = arc4->OD1R; -+ *((u32 *) out_arg + (i>>2) + 3) = arc4->OD0R; -+#endif -+ -+ i += 16; -+ } -+#else /* dma */ -+ -+#endif /* dma */ -+ -+ CRTCL_SECT_END; -+} -+ -+/** \fn arc4_chip_init(void) -+ \ingroup LQ_ARC4_FUNCTIONS -+ \brief initialize arc4 hardware -+*/ -+static void arc4_chip_init(void) -+{ -+ /* do nothing */ -+} -+ -+/** \fn static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len) -+ \ingroup LQ_ARC4_FUNCTIONS -+ \brief sets ARC4 key -+ \param tfm linux crypto algo transform -+ \param in_key input key -+ \param key_len key lengths less than or equal to 16 bytes supported -+*/ -+static int arc4_set_key(struct crypto_tfm *tfm, -+ const u8 *inkey, -+ unsigned int key_len) -+{ -+ /* struct arc4_ctx *ctx = crypto_tfm_ctx(tfm); */ -+ volatile struct deu_arc4 *arc4 = (struct deu_arc4 *) ARC4_START; -+ -+ u32 *in_key = (u32 *)inkey; -+ -+ /* must program all bits at one go?!!! */ -+#if 1 -+ /* #ifndef CONFIG_CRYPTO_DEV_VR9_DMA */ -+ *LQ_ARC4_CON = ( (1<<31) | ((key_len - 1)<<27) | (1<<26) | (3<<16) ); -+ /* NDC=1,ENDI=1,GO=0,KSAE=1,SM=0 */ -+ -+ arc4->K3R = *((u32 *) in_key + 0); -+ arc4->K2R = *((u32 *) in_key + 1); -+ arc4->K1R = *((u32 *) in_key + 2); -+ arc4->K0R = *((u32 *) in_key + 3); -+#else /* dma */ -+ *AMAZONS_ARC4_CON = ( (1<<31) | ((key_len - 1)<<27) | (1<<26) | (3<<16) | (1<<4) ); -+ /* NDC=1,ENDI=1,GO=0,KSAE=1,SM=1 */ -+ -+ arc4->K3R = *((u32 *) in_key + 0); -+ arc4->K2R = *((u32 *) in_key + 1); -+ arc4->K1R = *((u32 *) in_key + 2); -+ arc4->K0R = *((u32 *) in_key + 3); -+ -+#if 0 -+ arc4->K3R = deu_endian_swap(*((u32 *) in_key + 0)); -+ arc4->K2R = deu_endian_swap(*((u32 *) in_key + 1)); -+ arc4->K1R = deu_endian_swap(*((u32 *) in_key + 2)); -+ arc4->K0R = deu_endian_swap(*((u32 *) in_key + 3)); -+#endif -+ -+#endif -+ -+#if 0 /* arc4 is a ugly state machine, KSAE can only be set once per session */ -+ ctx->key_length = key_len; -+ -+ memcpy((u8 *)(ctx->buf), in_key, key_len); -+#endif -+ -+ return 0; -+} -+ -+/** \fn static void deu_arc4_ecb(void *ctx, uint8_t *dst, const uint8_t *src, uint8_t *iv, size_t nbytes, int encdec, int inplace) -+ \ingroup LQ_ARC4_FUNCTIONS -+ \brief sets ARC4 hardware to ECB mode -+ \param ctx crypto algo context -+ \param dst output bytestream -+ \param src input bytestream -+ \param iv initialization vector -+ \param nbytes length of bytestream -+ \param encdec 1 for encrypt; 0 for decrypt -+ \param inplace not used -+*/ -+static void deu_arc4_ecb(void *ctx, -+ uint8_t *dst, -+ const uint8_t *src, -+ uint8_t *iv, -+ size_t nbytes, -+ int encdec, -+ int inplace) -+{ -+ deu_arc4(ctx, dst, src, NULL, nbytes, encdec, 0); -+} -+ -+/** \fn static void arc4_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -+ \ingroup LQ_ARC4_FUNCTIONS -+ \brief encrypt/decrypt ARC4_BLOCK_SIZE of data -+ \param tfm linux crypto algo transform -+ \param out output bytestream -+ \param in input bytestream -+*/ -+static void arc4_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -+{ -+ struct arc4_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ deu_arc4(ctx, out, in, NULL, ARC4_BLOCK_SIZE, -+ CRYPTO_DIR_DECRYPT, CRYPTO_TFM_MODE_ECB); -+} -+ -+/* -+ * \brief ARC4 function mappings -+*/ -+static struct crypto_alg arc4_alg = { -+ .cra_name = "arc4", -+ .cra_driver_name = "lq_deu-arc4", -+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER, -+ .cra_blocksize = ARC4_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct arc4_ctx), -+ .cra_module = THIS_MODULE, -+ .cra_list = LIST_HEAD_INIT(arc4_alg.cra_list), -+ .cra_u = { -+ .cipher = { -+ .cia_min_keysize = ARC4_MIN_KEY_SIZE, -+ .cia_max_keysize = ARC4_MAX_KEY_SIZE, -+ .cia_setkey = arc4_set_key, -+ .cia_encrypt = arc4_crypt, -+ .cia_decrypt = arc4_crypt, -+ } -+ } -+}; -+ -+/** \fn static int ecb_arc4_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ \ingroup LQ_ARC4_FUNCTIONS -+ \brief ECB ARC4 encrypt using linux crypto blkcipher -+ \param desc blkcipher descriptor -+ \param dst output scatterlist -+ \param src input scatterlist -+ \param nbytes data size in bytes -+*/ -+static int ecb_arc4_encrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct arc4_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ -+ DPRINTF(1, "\n"); -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ while ((nbytes = walk.nbytes)) { -+ deu_arc4_ecb(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ NULL, nbytes, CRYPTO_DIR_ENCRYPT, 0); -+ nbytes &= ARC4_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/** \fn static int ecb_arc4_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ \ingroup LQ_ARC4_FUNCTIONS -+ \brief ECB ARC4 decrypt using linux crypto blkcipher -+ \param desc blkcipher descriptor -+ \param dst output scatterlist -+ \param src input scatterlist -+ \param nbytes data size in bytes -+*/ -+static int ecb_arc4_decrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct arc4_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ -+ DPRINTF(1, "\n"); -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ while ((nbytes = walk.nbytes)) { -+ deu_arc4_ecb(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ NULL, nbytes, CRYPTO_DIR_DECRYPT, 0); -+ nbytes &= ARC4_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/* -+ * \brief ARC4 function mappings -+*/ -+static struct crypto_alg ecb_arc4_alg = { -+ .cra_name = "ecb(arc4)", -+ .cra_driver_name = "lq_deu-ecb(arc4)", -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = ARC4_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct arc4_ctx), -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_list = LIST_HEAD_INIT(ecb_arc4_alg.cra_list), -+ .cra_u = { -+ .blkcipher = { -+ .min_keysize = ARC4_MIN_KEY_SIZE, -+ .max_keysize = ARC4_MAX_KEY_SIZE, -+ .setkey = arc4_set_key, -+ .encrypt = ecb_arc4_encrypt, -+ .decrypt = ecb_arc4_decrypt, -+ } -+ } -+}; -+ -+/** \fn int lq_deu_init_arc4(void) -+ \ingroup LQ_ARC4_FUNCTIONS -+ \brief initialize arc4 driver -+*/ -+int lq_deu_init_arc4(void) -+{ -+ int ret; -+ -+ if ((ret = crypto_register_alg(&arc4_alg))) -+ goto arc4_err; -+ -+ if ((ret = crypto_register_alg(&ecb_arc4_alg))) -+ goto ecb_arc4_err; -+ -+ arc4_chip_init(); -+ -+ CRTCL_SECT_INIT; -+ -+ printk(KERN_NOTICE "Lantiq DEU ARC4 initialized %s.\n", -+ disable_deudma ? "" : " (DMA)"); -+ return ret; -+ -+arc4_err: -+ crypto_unregister_alg(&arc4_alg); -+ printk(KERN_ERR "Lantiq arc4 initialization failed!\n"); -+ return ret; -+ecb_arc4_err: -+ crypto_unregister_alg(&ecb_arc4_alg); -+ printk(KERN_ERR "Lantiq ecb_arc4 initialization failed!\n"); -+ -+ return ret; -+} -+ -+/** \fn void lq_deu_fini_arc4(void) -+ \ingroup LQ_ARC4_FUNCTIONS -+ \brief unregister arc4 driver -+*/ -+void lq_deu_fini_arc4(void) -+{ -+ crypto_unregister_alg(&arc4_alg); -+ crypto_unregister_alg(&ecb_arc4_alg); -+} -+ -+#endif -+ -+#endif ---- /dev/null -+++ b/drivers/crypto/lantiq/des.c -@@ -0,0 +1,929 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief Lantiq DEU driver -+*/ -+ -+/** -+ \file des.c -+ \ingroup LQ_DEU -+ \brief DES encryption DEU driver file -+*/ -+ -+/** -+ \defgroup LQ_DES_FUNCTIONS LQ_DES_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief Lantiq DES Encryption functions -+*/ -+ -+#include <linux/version.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <linux/crypto.h> -+#include <linux/interrupt.h> -+#include <linux/delay.h> -+#include <asm/byteorder.h> -+#include <crypto/algapi.h> -+ -+#ifdef CONFIG_SOL_LANTIQ_XWAY -+ -+#include "deu.h" -+ -+#ifdef CONFIG_CRYPTO_DEV_DMA -+# include "deu_dma.h" -+#endif -+ -+static spinlock_t cipher_lock; -+ -+/* Preprocessor declarations */ -+#define DES_KEY_SIZE 8 -+#define DES_EXPKEY_WORDS 32 -+#define DES_BLOCK_SIZE 8 -+#define DES3_EDE_KEY_SIZE (3 * DES_KEY_SIZE) -+#define DES3_EDE_EXPKEY_WORDS (3 * DES_EXPKEY_WORDS) -+#define DES3_EDE_BLOCK_SIZE DES_BLOCK_SIZE -+ -+struct des_ctx { -+ int controlr_M; -+ int key_length; -+ u8 iv[DES_BLOCK_SIZE]; -+ u32 expkey[DES3_EDE_EXPKEY_WORDS]; -+}; -+ -+/** \fn int des_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief sets DES key -+ * \param tfm linux crypto algo transform -+ * \param key input key -+ * \param key_len key length -+*/ -+static int des_setkey(struct crypto_tfm *tfm, -+ const u8 *key, -+ unsigned int key_len) -+{ -+ struct des_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ DPRINTF(0, "ctx @%p, key_len %d %d\n", ctx, key_len); -+ -+ ctx->controlr_M = 0; /* des */ -+ ctx->key_length = key_len; -+ -+ memcpy((u8 *)(ctx->expkey), key, key_len); -+ -+ return 0; -+} -+ -+#ifndef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+/** \fn void deu_des(void *ctx_arg, u8 *out_arg, const u8 *in_arg, u8 *iv_arg, u32 nbytes, int encdec, int mode) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief main interface to DES hardware -+ * \param ctx_arg crypto algo context -+ * \param out_arg output bytestream -+ * \param in_arg input bytestream -+ * \param iv_arg initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param mode operation mode such as ebc, cbc -+*/ -+ -+static void deu_des(void *ctx_arg, -+ u8 *out_arg, -+ const u8 *in_arg, -+ u8 *iv_arg, -+ u32 nbytes, -+ int encdec, -+ int mode) -+#else -+/** \fn void deu_des_core(void *ctx_arg, u8 *out_arg, const u8 *in_arg, u8 *iv_arg, u32 nbytes, int encdec, int mode) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief main interface to DES hardware -+ * \param ctx_arg crypto algo context -+ * \param out_arg output bytestream -+ * \param in_arg input bytestream -+ * \param iv_arg initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param mode operation mode such as ebc, cbc -+*/ -+static void deu_des_core(void *ctx_arg, -+ u8 *out_arg, -+ const u8 *in_arg, -+ u8 *iv_arg, -+ u32 nbytes, -+ int encdec, -+ int mode) -+#endif -+{ -+ volatile struct deu_des *des = (struct deu_des *) DES_3DES_START; -+ struct des_ctx *dctx = ctx_arg; -+ u32 *key = dctx->expkey; -+ ulong flag; -+ -+#ifndef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ int i = 0; -+ int nblocks = 0; -+#else -+ volatile struct deu_dma *dma = (struct deu_dma *) LQ_DEU_DMA_CON; -+ struct dma_device_info *dma_device = lq_deu[0].dma_device; -+ /* struct deu_drv_priv *deu_priv = -+ * (struct deu_drv_priv *)dma_device->priv; */ -+ int wlen = 0; -+ u32 *outcopy = NULL; -+ u32 *dword_mem_aligned_in = NULL; -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_POLL_DMA -+ u32 timeout = 0; -+ u32 *out_dma = NULL; -+#endif -+ -+#endif -+ -+ DPRINTF(0, "ctx @%p, mode %d, encdec %d\n", dctx, mode, encdec); -+ -+ CRTCL_SECT_START; -+ -+ des->ctrl.E_D = !encdec; /* encryption */ -+ des->ctrl.O = mode; /* 0 ECB, 1 CBC, 2 OFB, 3 CFB, 4 CTR */ -+ des->ctrl.SM = 1; /* start after writing input register */ -+ des->ctrl.DAU = 0; /* Disable Automatic Update of init vect */ -+ des->ctrl.ARS = 1; /* Autostart Select - write to IHR */ -+ -+ des->ctrl.M = dctx->controlr_M; -+ /* write keys */ -+ if (dctx->controlr_M == 0) { -+ /* DES mode */ -+ des->K1HR = DEU_ENDIAN_SWAP(*((u32 *) key + 0)); -+ des->K1LR = DEU_ENDIAN_SWAP(*((u32 *) key + 1)); -+#ifdef CRYPTO_DEBUG -+ printk("key1: %x\n", (*((u32 *) key + 0))); -+ printk("key2: %x\n", (*((u32 *) key + 1))); -+#endif -+ } else { -+ /* 3DES mode (EDE-x) */ -+ switch (dctx->key_length) { -+ case 24: -+ des->K3HR = DEU_ENDIAN_SWAP(*((u32 *) key + 4)); -+ des->K3LR = DEU_ENDIAN_SWAP(*((u32 *) key + 5)); -+ /* no break; */ -+ case 16: -+ des->K2HR = DEU_ENDIAN_SWAP(*((u32 *) key + 2)); -+ des->K2LR = DEU_ENDIAN_SWAP(*((u32 *) key + 3)); -+ /* no break; */ -+ case 8: -+ des->K1HR = DEU_ENDIAN_SWAP(*((u32 *) key + 0)); -+ des->K1LR = DEU_ENDIAN_SWAP(*((u32 *) key + 1)); -+ break; -+ default: -+ CRTCL_SECT_END; -+ return; -+ } -+ } -+ -+ /* write init vector (not required for ECB mode) */ -+ if (mode > 0) { -+ des->IVHR = DEU_ENDIAN_SWAP(*(u32 *) iv_arg); -+ des->IVLR = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 1)); -+ } -+ -+#ifndef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ nblocks = nbytes / 4; -+ -+ for (i = 0; i < nblocks; i += 2) { -+ /* wait for busy bit to clear */ -+ -+ /*--- Workaround --------------------------------------------- -+ do a dummy read to the busy flag because it is not raised -+ early enough in CFB/OFB 3DES modes */ -+#ifdef CRYPTO_DEBUG -+ printk("ihr: %x\n", (*((u32 *) in_arg + i))); -+ printk("ilr: %x\n", (*((u32 *) in_arg + 1 + i))); -+#endif -+ des->IHR = INPUT_ENDIAN_SWAP(*((u32 *) in_arg + i)); -+ /* start crypto */ -+ des->ILR = INPUT_ENDIAN_SWAP(*((u32 *) in_arg + 1 + i)); -+ -+ while (des->ctrl.BUS) { -+ /* this will not take long */ -+ } -+ -+ *((u32 *) out_arg + 0 + i) = des->OHR; -+ *((u32 *) out_arg + 1 + i) = des->OLR; -+ -+#ifdef CRYPTO_DEBUG -+ printk("ohr: %x\n", (*((u32 *) out_arg + i))); -+ printk("olr: %x\n", (*((u32 *) out_arg + 1 + i))); -+#endif -+ } -+ -+#else /* dma mode */ -+ -+ /* Prepare Rx buf length used in dma psuedo interrupt */ -+ /* deu_priv->deu_rx_buf = out_arg; */ -+ /* deu_priv->deu_rx_len = nbytes; */ -+ -+ /* memory alignment issue */ -+ dword_mem_aligned_in = (u32 *) DEU_DWORD_REORDERING(in_arg, des_buff_in, -+ BUFFER_IN, nbytes); -+ -+ dma->ctrl.ALGO = 0; /* DES */ -+ des->ctrl.DAU = 0; -+ dma->ctrl.BS = 0; -+ dma->ctrl.EN = 1; -+ -+ while (des->ctrl.BUS) { -+ /* wait for AES to be ready */ -+ }; -+ -+ wlen = dma_device_write(dma_device, (u8 *) dword_mem_aligned_in, nbytes, -+ NULL); -+ if (wlen != nbytes) { -+ dma->ctrl.EN = 0; -+ CRTCL_SECT_END; -+ printk(KERN_ERR "[%s %s %d]: dma_device_write fail!\n", -+ __FILE__, __func__, __LINE__); -+ return; /* -EINVAL; */ -+ } -+ -+ WAIT_DES_DMA_READY(); -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_POLL_DMA -+ outcopy = (u32 *) DEU_DWORD_REORDERING(out_arg, des_buff_out, -+ BUFFER_OUT, nbytes); -+ -+ /* polling DMA rx channel */ -+ while ((dma_device_read(dma_device, (u8 **) &out_dma, NULL)) == 0) { -+ timeout++; -+ -+ if (timeout >= 333000) { -+ dma->ctrl.EN = 0; -+ CRTCL_SECT_END; -+ printk(KERN_ERR "[%s %s %d]: timeout!!\n", -+ __FILE__, __func__, __LINE__); -+ return; /* -EINVAL; */ -+ } -+ } -+ -+ WAIT_DES_DMA_READY(); -+ -+ DES_MEMORY_COPY(outcopy, out_dma, out_arg, nbytes); -+#else -+ CRTCL_SECT_END; /* Sleep and wait for Rx finished */ -+ DEU_WAIT_EVENT(deu_priv->deu_thread_wait, DEU_EVENT, -+ deu_priv->deu_event_flags); -+ CRTCL_SECT_START; -+#endif -+ -+#endif /* dma mode */ -+ -+ if (mode > 0) { -+ *(u32 *) iv_arg = DEU_ENDIAN_SWAP(des->IVHR); -+ *((u32 *) iv_arg + 1) = DEU_ENDIAN_SWAP(des->IVLR); -+ }; -+ -+ CRTCL_SECT_END; -+} -+ -+/* definitions from linux/include/crypto.h: -+#define CRYPTO_TFM_MODE_ECB 0x00000001 -+#define CRYPTO_TFM_MODE_CBC 0x00000002 -+#define CRYPTO_TFM_MODE_CFB 0x00000004 -+#define CRYPTO_TFM_MODE_CTR 0x00000008 -+#define CRYPTO_TFM_MODE_OFB 0x00000010 -+but hardware definition: 0 ECB 1 CBC 2 OFB 3 CFB 4 CTR */ -+ -+/** \fn void deu_des(void *ctx_arg, u8 *out_arg, const u8 *in_arg, u8 *iv_arg, u32 nbytes, int encdec, int mode) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief main interface to DES hardware -+ * \param ctx_arg crypto algo context -+ * \param out_arg output bytestream -+ * \param in_arg input bytestream -+ * \param iv_arg initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param mode operation mode such as ebc, cbc -+*/ -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+static void deu_des(void *ctx_arg, -+ u8 *out_arg, -+ const u8 *in_arg, -+ u8 *iv_arg, -+ u32 nbytes, -+ int encdec, -+ int mode) -+{ -+ u32 remain = nbytes; -+ u32 inc; -+ -+ DPRINTF(0, "\n"); -+ -+ while (remain > 0) { -+ if (remain >= DEU_MAX_PACKET_SIZE) -+ inc = DEU_MAX_PACKET_SIZE; -+ else -+ inc = remain; -+ -+ remain -= inc; -+ -+ deu_des_core(ctx_arg, out_arg, in_arg, iv_arg, inc, encdec, -+ mode); -+ -+ out_arg += inc; -+ in_arg += inc; -+ } -+} -+#endif -+ -+/** \fn void deu_des_ecb(void *ctx, uint8_t *dst, const uint8_t *src, uint8_t *iv, size_t nbytes, int encdec, int inplace) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief sets DES hardware to ECB mode -+ * \param ctx crypto algo context -+ * \param dst output bytestream -+ * \param src input bytestream -+ * \param iv initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param inplace not used -+*/ -+ -+static void deu_des_ecb(void *ctx, -+ uint8_t *dst, -+ const uint8_t *src, -+ uint8_t *iv, -+ size_t nbytes, -+ int encdec, -+ int inplace) -+{ -+ DPRINTF(0, "ctx @%p\n", ctx); -+ deu_des(ctx, dst, src, NULL, nbytes, encdec, 0); -+} -+ -+/** \fn void deu_des_cbc(void *ctx, uint8_t *dst, const uint8_t *src, uint8_t *iv, size_t nbytes, int encdec, int inplace) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief sets DES hardware to CBC mode -+ * \param ctx crypto algo context -+ * \param dst output bytestream -+ * \param src input bytestream -+ * \param iv initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param inplace not used -+*/ -+static void deu_des_cbc(void *ctx, -+ uint8_t *dst, -+ const uint8_t *src, -+ uint8_t *iv, -+ size_t nbytes, -+ int encdec, -+ int inplace) -+{ -+ DPRINTF(0, "ctx @%p\n", ctx); -+ deu_des(ctx, dst, src, iv, nbytes, encdec, 1); -+} -+ -+#if 0 -+/** \fn void deu_des_ofb(void *ctx, uint8_t *dst, const uint8_t *src, uint8_t *iv, size_t nbytes, int encdec, int inplace) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief sets DES hardware to OFB mode -+ * \param ctx crypto algo context -+ * \param dst output bytestream -+ * \param src input bytestream -+ * \param iv initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param inplace not used -+*/ -+static void deu_des_ofb(void *ctx, -+ uint8_t *dst, -+ const uint8_t *src, -+ uint8_t *iv, -+ size_t nbytes, -+ int encdec, -+ int inplace) -+{ -+ DPRINTF(0, "ctx @%p\n", ctx); -+ deu_des(ctx, dst, src, iv, nbytes, encdec, 2); -+} -+ -+/** \fn void deu_des_cfb(void *ctx, uint8_t *dst, const uint8_t *src, uint8_t *iv, size_t nbytes, int encdec, int inplace) -+ \ingroup LQ_DES_FUNCTIONS -+ \brief sets DES hardware to CFB mode -+ \param ctx crypto algo context -+ \param dst output bytestream -+ \param src input bytestream -+ \param iv initialization vector -+ \param nbytes length of bytestream -+ \param encdec 1 for encrypt; 0 for decrypt -+ \param inplace not used -+*/ -+static void deu_des_cfb(void *ctx, -+ uint8_t *dst, -+ const uint8_t *src, -+ uint8_t *iv, -+ size_t nbytes, -+ int encdec, -+ int inplace) -+{ -+ DPRINTF(0, "ctx @%p\n", ctx); -+ deu_des(ctx, dst, src, iv, nbytes, encdec, 3); -+} -+ -+/** \fn void deu_des_ctr(void *ctx, uint8_t *dst, const uint8_t *src, uint8_t *iv, size_t nbytes, int encdec, int inplace) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief sets DES hardware to CTR mode -+ * \param ctx crypto algo context -+ * \param dst output bytestream -+ * \param src input bytestream -+ * \param iv initialization vector -+ * \param nbytes length of bytestream -+ * \param encdec 1 for encrypt; 0 for decrypt -+ * \param inplace not used -+*/ -+static void deu_des_ctr(void *ctx, -+ uint8_t *dst, -+ const uint8_t *src, -+ uint8_t *iv, -+ size_t nbytes, -+ int encdec, -+ int inplace) -+{ -+ DPRINTF(0, "ctx @%p\n", ctx); -+ deu_des(ctx, dst, src, iv, nbytes, encdec, 4); -+} -+#endif -+ -+/** \fn void des_encrypt(struct crypto_tfm *tfm, uint8_t *out, const uint8_t *in) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief encrypt DES_BLOCK_SIZE of data -+ * \param tfm linux crypto algo transform -+ * \param out output bytestream -+ * \param in input bytestream -+*/ -+static void des_encrypt(struct crypto_tfm *tfm, uint8_t *out, const uint8_t *in) -+{ -+ struct des_ctx *ctx = crypto_tfm_ctx(tfm); -+ DPRINTF(0, "ctx @%p\n", ctx); -+ deu_des(ctx, out, in, NULL, DES_BLOCK_SIZE, CRYPTO_DIR_ENCRYPT, 0); -+} -+ -+/** \fn void des_decrypt(struct crypto_tfm *tfm, uint8_t *out, const uint8_t *in) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief encrypt DES_BLOCK_SIZE of data -+ * \param tfm linux crypto algo transform -+ * \param out output bytestream -+ * \param in input bytestream -+*/ -+static void des_decrypt(struct crypto_tfm *tfm, uint8_t *out, const uint8_t *in) -+{ -+ struct des_ctx *ctx = crypto_tfm_ctx(tfm); -+ DPRINTF(0, "ctx @%p\n", ctx); -+ deu_des(ctx, out, in, NULL, DES_BLOCK_SIZE, CRYPTO_DIR_DECRYPT, 0); -+} -+ -+/* -+ * \brief 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. -+ * -+ */ -+ -+/** \fn int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief sets 3DES key -+ * \param tfm linux crypto algo transform -+ * \param key input key -+ * \param keylen key length -+*/ -+static int des3_ede_setkey(struct crypto_tfm *tfm, -+ const u8 *key, -+ unsigned int key_len) -+{ -+ struct des_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ DPRINTF(0, "ctx @%p, key_len %d\n", ctx, key_len); -+ -+ ctx->controlr_M = key_len / 8 + 1; /* 3DES EDE1 / EDE2 / EDE3 Mode */ -+ ctx->key_length = key_len; -+ -+ memcpy((u8 *)(ctx->expkey), key, key_len); -+ -+ return 0; -+} -+ -+/* -+ * \brief DES function mappings -+*/ -+static struct crypto_alg des_alg = { -+ .cra_name = "des", -+ .cra_driver_name = "lq_deu-des", -+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct des_ctx), -+ .cra_module = THIS_MODULE, -+ .cra_alignmask = 3, -+ .cra_list = LIST_HEAD_INIT(des_alg.cra_list), -+ .cra_u = { -+ .cipher = { -+ .cia_min_keysize = DES_KEY_SIZE, -+ .cia_max_keysize = DES_KEY_SIZE, -+ .cia_setkey = des_setkey, -+ .cia_encrypt = des_encrypt, -+ .cia_decrypt = des_decrypt -+ } -+ } -+}; -+ -+/* -+ * \brief DES function mappings -+*/ -+static struct crypto_alg des3_ede_alg = { -+ .cra_name = "des3_ede", -+ .cra_driver_name = "lq_deu-des3_ede", -+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct des_ctx), -+ .cra_module = THIS_MODULE, -+ .cra_alignmask = 3, -+ .cra_list = LIST_HEAD_INIT(des3_ede_alg.cra_list), -+ .cra_u = { -+ .cipher = { -+ .cia_min_keysize = DES_KEY_SIZE, -+ .cia_max_keysize = DES_KEY_SIZE, -+ .cia_setkey = des3_ede_setkey, -+ .cia_encrypt = des_encrypt, -+ .cia_decrypt = des_decrypt -+ } -+ } -+}; -+ -+/** \fn int ecb_des_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief ECB DES encrypt using linux crypto blkcipher -+ * \param desc blkcipher descriptor -+ * \param dst output scatterlist -+ * \param src input scatterlist -+ * \param nbytes data size in bytes -+*/ -+static int ecb_des_encrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ -+ DPRINTF(0, "ctx @%p\n", ctx); -+ -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ while ((nbytes = walk.nbytes)) { -+ nbytes -= (nbytes % DES_BLOCK_SIZE); -+ deu_des_ecb(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ NULL, nbytes, CRYPTO_DIR_ENCRYPT, 0); -+ nbytes &= DES_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/** \fn int ecb_des_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief ECB DES decrypt using linux crypto blkcipher -+ * \param desc blkcipher descriptor -+ * \param dst output scatterlist -+ * \param src input scatterlist -+ * \param nbytes data size in bytes -+ * \return err -+*/ -+static int ecb_des_decrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ -+ DPRINTF(0, "ctx @%p\n", ctx); -+ -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ while ((nbytes = walk.nbytes)) { -+ nbytes -= (nbytes % DES_BLOCK_SIZE); -+ deu_des_ecb(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ NULL, nbytes, CRYPTO_DIR_DECRYPT, 0); -+ nbytes &= DES_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/* -+ * \brief DES function mappings -+*/ -+static struct crypto_alg ecb_des_alg = { -+ .cra_name = "ecb(des)", -+ .cra_driver_name = "lq_deu-ecb(des)", -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct des_ctx), -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_list = LIST_HEAD_INIT(ecb_des_alg.cra_list), -+ .cra_u = { -+ .blkcipher = { -+ .min_keysize = DES_KEY_SIZE, -+ .max_keysize = DES_KEY_SIZE, -+ .setkey = des_setkey, -+ .encrypt = ecb_des_encrypt, -+ .decrypt = ecb_des_decrypt, -+ } -+ } -+}; -+ -+/* -+ * \brief DES function mappings -+*/ -+static struct crypto_alg ecb_des3_ede_alg = { -+ .cra_name = "ecb(des3_ede)", -+ .cra_driver_name = "lq_deu-ecb(des3_ede)", -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct des_ctx), -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_list = LIST_HEAD_INIT(ecb_des3_ede_alg.cra_list), -+ .cra_u = { -+ .blkcipher = { -+ .min_keysize = DES3_EDE_KEY_SIZE, -+ .max_keysize = DES3_EDE_KEY_SIZE, -+ .setkey = des3_ede_setkey, -+ .encrypt = ecb_des_encrypt, -+ .decrypt = ecb_des_decrypt, -+ } -+ } -+}; -+ -+/** \fn int cbc_des_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief CBC DES encrypt using linux crypto blkcipher -+ * \param desc blkcipher descriptor -+ * \param dst output scatterlist -+ * \param src input scatterlist -+ * \param nbytes data size in bytes -+ * \return err -+*/ -+static int cbc_des_encrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ -+ DPRINTF(0, "ctx @%p\n", ctx); -+ -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ while ((nbytes = walk.nbytes)) { -+ u8 *iv = walk.iv; -+ /* printk("iv = %08x\n", *(u32 *)iv); */ -+ nbytes -= (nbytes % DES_BLOCK_SIZE); -+ deu_des_cbc(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ iv, nbytes, CRYPTO_DIR_ENCRYPT, 0); -+ nbytes &= DES_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/** \fn int cbc_des_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief CBC DES decrypt using linux crypto blkcipher -+ * \param desc blkcipher descriptor -+ * \param dst output scatterlist -+ * \param src input scatterlist -+ * \param nbytes data size in bytes -+ * \return err -+*/ -+static int cbc_des_decrypt(struct blkcipher_desc *desc, -+ struct scatterlist *dst, -+ struct scatterlist *src, -+ unsigned int nbytes) -+{ -+ struct des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ struct blkcipher_walk walk; -+ int err; -+ -+ DPRINTF(0, "ctx @%p\n", ctx); -+ -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ while ((nbytes = walk.nbytes)) { -+ u8 *iv = walk.iv; -+ /* printk("iv = %08x\n", *(u32 *)iv); */ -+ nbytes -= (nbytes % DES_BLOCK_SIZE); -+ deu_des_cbc(ctx, walk.dst.virt.addr, walk.src.virt.addr, -+ iv, nbytes, CRYPTO_DIR_DECRYPT, 0); -+ nbytes &= DES_BLOCK_SIZE - 1; -+ err = blkcipher_walk_done(desc, &walk, nbytes); -+ } -+ -+ return err; -+} -+ -+/* -+ * \brief DES function mappings -+*/ -+static struct crypto_alg cbc_des_alg = { -+ .cra_name = "cbc(des)", -+ .cra_driver_name = "lq_deu-cbc(des)", -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct des_ctx), -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_list = LIST_HEAD_INIT(cbc_des_alg.cra_list), -+ .cra_u = { -+ .blkcipher = { -+ .min_keysize = DES_KEY_SIZE, -+ .max_keysize = DES_KEY_SIZE, -+ .ivsize = DES_BLOCK_SIZE, -+ .setkey = des_setkey, -+ .encrypt = cbc_des_encrypt, -+ .decrypt = cbc_des_decrypt, -+ } -+ } -+}; -+ -+/* -+ * \brief DES function mappings -+*/ -+static struct crypto_alg cbc_des3_ede_alg = { -+ .cra_name = "cbc(des3_ede)", -+ .cra_driver_name = "lq_deu-cbc(des3_ede)", -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct des_ctx), -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_list = LIST_HEAD_INIT(cbc_des3_ede_alg.cra_list), -+ .cra_u = { -+ .blkcipher = { -+ .min_keysize = DES3_EDE_KEY_SIZE, -+ .max_keysize = DES3_EDE_KEY_SIZE, -+ .ivsize = DES_BLOCK_SIZE, -+ .setkey = des3_ede_setkey, -+ .encrypt = cbc_des_encrypt, -+ .decrypt = cbc_des_decrypt, -+ } -+ } -+}; -+ -+/** \fn int lq_deu_init_des(void) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief initialize des driver -+*/ -+int lq_deu_init_des(void) -+{ -+ int ret = 0; -+ -+ ret = crypto_register_alg(&des_alg); -+ if (ret < 0) -+ goto des_err; -+ -+ ret = crypto_register_alg(&ecb_des_alg); -+ if (ret < 0) -+ goto ecb_des_err; -+ -+ ret = crypto_register_alg(&cbc_des_alg); -+ if (ret < 0) -+ goto cbc_des_err; -+ -+ ret = crypto_register_alg(&des3_ede_alg); -+ if (ret < 0) -+ goto des3_ede_err; -+ -+ ret = crypto_register_alg(&ecb_des3_ede_alg); -+ if (ret < 0) -+ goto ecb_des3_ede_err; -+ -+ ret = crypto_register_alg(&cbc_des3_ede_alg); -+ if (ret < 0) -+ goto cbc_des3_ede_err; -+ -+ deu_des_chip_init(); -+ -+ CRTCL_SECT_INIT; -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ if (ALLOCATE_MEMORY(BUFFER_IN, DES_ALGO) < 0) { -+ printk(KERN_ERR "[%s %s %d]: malloc memory fail!\n", -+ __FILE__, __func__, __LINE__); -+ goto cbc_des3_ede_err; -+ } -+ if (ALLOCATE_MEMORY(BUFFER_OUT, DES_ALGO) < 0) { -+ printk(KERN_ERR "[%s %s %d]: malloc memory fail!\n", -+ __FILE__, __func__, __LINE__); -+ goto cbc_des3_ede_err; -+ } -+#endif -+ -+ printk(KERN_NOTICE "Lantiq DEU DES initialized%s.\n", -+ disable_deudma ? "" : " (DMA)"); -+ return ret; -+ -+des_err: -+ crypto_unregister_alg(&des_alg); -+ printk(KERN_ERR "Lantiq des initialization failed!\n"); -+ -+ return ret; -+ -+ecb_des_err: -+ crypto_unregister_alg(&ecb_des_alg); -+ printk(KERN_ERR "Lantiq ecb_des initialization failed!\n"); -+ -+ return ret; -+ -+cbc_des_err: -+ crypto_unregister_alg(&cbc_des_alg); -+ printk(KERN_ERR "Lantiq cbc_des initialization failed!\n"); -+ -+ return ret; -+ -+des3_ede_err: -+ crypto_unregister_alg(&des3_ede_alg); -+ printk(KERN_ERR "Lantiq des3_ede initialization failed!\n"); -+ -+ return ret; -+ -+ecb_des3_ede_err: -+ crypto_unregister_alg(&ecb_des3_ede_alg); -+ printk(KERN_ERR "Lantiq ecb_des3_ede initialization failed!\n"); -+ -+ return ret; -+ -+cbc_des3_ede_err: -+ crypto_unregister_alg(&cbc_des3_ede_alg); -+ printk(KERN_ERR "Lantiq cbc_des3_ede initialization failed!\n"); -+ -+ return ret; -+} -+ -+/** \fn void lq_deu_fini_des(void) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief unregister des driver -+*/ -+void lq_deu_fini_des(void) -+{ -+ crypto_unregister_alg(&des_alg); -+ crypto_unregister_alg(&ecb_des_alg); -+ crypto_unregister_alg(&cbc_des_alg); -+ crypto_unregister_alg(&des3_ede_alg); -+ crypto_unregister_alg(&ecb_des3_ede_alg); -+ crypto_unregister_alg(&cbc_des3_ede_alg); -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ FREE_MEMORY(des_buff_in); -+ FREE_MEMORY(des_buff_out); -+#endif /* CONFIG_CRYPTO_DEV_LANTIQ_DMA_DANUBE */ -+} -+ -+#endif ---- /dev/null -+++ b/drivers/crypto/lantiq/deu.c -@@ -0,0 +1,195 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief Lantiq DEU driver module -+*/ -+ -+/** -+ \file deu.c -+ \ingroup LQ_DEU -+ \brief main DEU driver file -+*/ -+ -+/** -+ \defgroup LQ_DEU_FUNCTIONS LQ_DEU_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief Lantiq DEU functions -+*/ -+ -+#include <linux/version.h> -+#if defined(CONFIG_MODVERSIONS) -+#define MODVERSIONS -+#include <linux/modversions.h> -+#endif -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <linux/crypto.h> -+#include <linux/proc_fs.h> -+#include <linux/fs.h> /* Stuff about file systems that we need */ -+#include <asm/byteorder.h> -+ -+#if 0 -+#ifdef CONFIG_SOC_LANTIQ_XWAY -+# include <lq_pmu.h> -+#endif -+#endif -+ -+#include "deu.h" -+ -+struct lq_crypto_priv lq_crypto_ops; -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+int disable_deudma = 0; -+#else -+int disable_deudma = 1; -+#endif /* CONFIG_CRYPTO_DEV_LANTIQ_DMA */ -+ -+#ifdef CRYPTO_DEBUG -+char deu_debug_level = 3; -+#endif -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_MODULE -+# define STATIC static -+#else -+# define STATIC -+#endif -+ -+/** \fn static int lq_deu_init(void) -+ * \ingroup LQ_DEU_FUNCTIONS -+ * \brief link all modules that have been selected in kernel config for Lantiq HW crypto support -+ * \return ret -+*/ -+int lq_deu_init(void) -+{ -+ int ret = -ENOSYS; -+ u32 config; -+ -+ printk(KERN_INFO "Lantiq crypto hardware driver version %s\n", -+ LQ_DEU_DRV_VERSION); -+ -+ config = deu_chip_init(); -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ deu_dma_init(); -+#endif -+ -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_AES) -+ if(config & LQ_DEU_ID_AES) { -+ if ((ret = lq_deu_init_aes())) { -+ printk(KERN_ERR "Lantiq AES initialization failed!\n"); -+ } -+ } else { -+ printk(KERN_ERR "Lantiq AES not supported!\n"); -+ } -+#endif -+ -+#ifdef CONFIG_SOL_LANTIQ_XWAY -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_DES) -+ if(config & LQ_DEU_ID_DES) { -+ if ((ret = lq_deu_init_des())) { -+ printk(KERN_ERR "Lantiq DES initialization failed!\n"); -+ } -+ } else { -+ printk(KERN_ERR "Lantiq DES not supported!\n"); -+ } -+#endif -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_ARC4) && defined(CONFIG_CRYPTO_DEV_LANTIQ_DMA) -+ if ((ret = lq_deu_init_arc4())) { -+ printk(KERN_ERR "Lantiq ARC4 initialization failed!\n"); -+ } -+#endif -+#endif -+ -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_SHA1) -+ if(config & LQ_DEU_ID_HASH) { -+ if ((ret = lq_deu_init_sha1())) { -+ printk(KERN_ERR "Lantiq SHA1 initialization failed!\n"); -+ } -+ } else { -+ printk(KERN_ERR "Lantiq SHA1 not supported!\n"); -+ } -+#endif -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_MD5) -+ if(config & LQ_DEU_ID_HASH) { -+ if ((ret = lq_deu_init_md5())) { -+ printk(KERN_ERR "Lantiq MD5 initialization failed!\n"); -+ } -+ } else { -+ printk(KERN_ERR "Lantiq MD5 not supported!\n"); -+ } -+#endif -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_SHA1_HMAC) -+ if ((ret = lq_deu_init_sha1_hmac())) { -+ printk(KERN_ERR "Lantiq SHA1_HMAC initialization failed!\n"); -+ } -+#endif -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_MD5_HMAC) -+ if ((ret = lq_deu_init_md5_hmac())) { -+ printk(KERN_ERR "Lantiq MD5_HMAC initialization failed!\n"); -+ } -+#endif -+ return ret; -+} -+ -+/** \fn static void lq_deu_fini(void) -+ * \ingroup LQ_DEU_FUNCTIONS -+ * \brief remove the loaded crypto algorithms -+*/ -+void lq_deu_exit(void) -+{ -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_AES) -+ lq_deu_fini_aes(); -+#endif -+#ifdef CONFIG_SOL_LANTIQ_XWAY -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_DES) -+ lq_deu_fini_des(); -+#endif -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_ARC4) \ -+ && defined(CONFIG_CRYPTO_DEV_LANTIQ_DMA) -+ lq_deu_fini_arc4(); -+#endif -+#endif -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_SHA1) -+ lq_deu_fini_sha1(); -+#endif -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_MD5) -+ lq_deu_fini_md5(); -+#endif -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_SHA1_HMAC) -+ lq_deu_fini_sha1_hmac(); -+#endif -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_MD5_HMAC) -+ lq_deu_fini_md5_hmac(); -+#endif -+ -+ printk("DEU has exited successfully\n"); -+ -+#if defined(CONFIG_CRYPTO_DEV_LANTIQ_DMA) -+ deu_dma_exit(); -+ printk("DMA has deregistered successfully\n"); -+#endif -+} -+ -+EXPORT_SYMBOL(lq_deu_init); -+EXPORT_SYMBOL(lq_deu_exit); ---- /dev/null -+++ b/drivers/crypto/lantiq/deu.h -@@ -0,0 +1,248 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief Lantiq DEU driver module -+*/ -+ -+/** -+ \file deu.h -+ \brief Main DEU driver header file -+*/ -+ -+/** -+ \defgroup LQ_DEU_DEFINITIONS LQ_DEU_DEFINITIONS -+ \ingroup LQ_DEU -+ \brief Lantiq DEU definitions -+*/ -+ -+ -+#ifndef DEU_H -+#define DEU_H -+ -+#undef CRYPTO_DEBUG -+ -+#define LQ_DEU_DRV_VERSION "1.0.1" -+ -+#if defined(CONFIG_LANTIQ_DANUBE) -+# include "deu_danube.h" -+#elif defined(CONFIG_LANTIQ_AR9) -+# include "deu_ar9.h" -+#elif defined(CONFIG_SOC_LANTIQ_FALCON) -+# include "deu_falcon.h" -+#else -+//# error "Unknown platform" -+# include "deu_danube.h" -+#endif -+ -+struct lq_crypto_priv { -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ u32 *des_buff_in; -+ u32 *des_buff_out; -+ u32 *aes_buff_in; -+ u32 *aes_buff_out; -+ -+ int (*dma_init)(void); -+ void (*dma_exit)(void); -+ u32 (*dma_align)(const u8 *, u32 *, int, int); -+ void (*aes_dma_memcpy)(u32 *, u32 *, u8 *, int); -+ void (*des_dma_memcpy)(u32 *, u32 *, u8 *, int); -+ int (*aes_dma_malloc)(int); -+ int (*des_dma_malloc)(int); -+ void (*dma_free)(u32 *); -+#endif -+ -+ u32 (*endian_swap)(u32); -+ u32 (*input_swap)(u32); -+ void (*aes_chip_init)(void); -+ void (*des_chip_init)(void); -+ u32 (*chip_init)(void); -+}; -+ -+extern struct lq_crypto_priv lq_crypto_ops; -+ -+#define LQ_DEU_ALIGNMENT 16 -+ -+#define PFX "lq_deu: " -+ -+#define LQ_DEU_CRA_PRIORITY 300 -+#define LQ_DEU_COMPOSITE_PRIORITY 400 -+ -+#define CRYPTO_DIR_ENCRYPT 1 -+#define CRYPTO_DIR_DECRYPT 0 -+ -+#define CRTCL_SECT_INIT spin_lock_init(&cipher_lock) -+#define CRTCL_SECT_START spin_lock_irqsave(&cipher_lock, flag) -+#define CRTCL_SECT_END spin_unlock_irqrestore(&cipher_lock, flag) -+ -+#define LQ_DEU_ID_REV 0x00001F -+#define LQ_DEU_ID_ID 0x00FF00 -+#define LQ_DEU_ID_DMA 0x010000 -+#define LQ_DEU_ID_HASH 0x020000 -+#define LQ_DEU_ID_AES 0x040000 -+#define LQ_DEU_ID_3DES 0x080000 -+#define LQ_DEU_ID_DES 0x100000 -+ -+extern int disable_deudma; -+ -+int lq_deu_init(void); -+void lq_deu_exit(void); -+ -+int lq_deu_init_des(void); -+int lq_deu_init_aes(void); -+int lq_deu_init_arc4(void); -+int lq_deu_init_sha1(void); -+int lq_deu_init_md5(void); -+int lq_deu_init_sha1_hmac(void); -+int lq_deu_init_md5_hmac(void); -+ -+void lq_deu_fini_des(void); -+void lq_deu_fini_aes(void); -+void lq_deu_fini_arc4(void); -+void lq_deu_fini_sha1(void); -+void lq_deu_fini_md5(void); -+void lq_deu_fini_sha1_hmac(void); -+void lq_deu_fini_md5_hmac(void); -+ -+/* board specific functions */ -+/* { */ -+static inline u32 deu_chip_init(void) -+{ -+ return lq_crypto_ops.chip_init(); -+} -+ -+static inline void deu_des_chip_init(void) -+{ -+ lq_crypto_ops.des_chip_init(); -+} -+ -+static inline void deu_aes_chip_init(void) -+{ -+ lq_crypto_ops.aes_chip_init(); -+} -+ -+static inline u32 deu_input_swap(u32 input) -+{ -+ return lq_crypto_ops.input_swap(input); -+} -+ -+static inline u32 deu_endian_swap(u32 input) -+{ -+ return lq_crypto_ops.endian_swap(input); -+} -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+static inline int deu_aes_dma_malloc(int value) -+{ -+ return lq_crypto_ops.aes_dma_malloc(value); -+} -+ -+static inline int deu_des_dma_malloc(int value) -+{ -+ return lq_crypto_ops.des_dma_malloc(value); -+} -+ -+static inline u32 *deu_dma_align(const u8 *arg, -+ u32 *buff_alloc, -+ int in_out, -+ int nbytes) -+{ -+ return lq_crypto_ops.dma_align(arg, buff_alloc, in_out, nbytes); -+} -+ -+static inline void deu_aes_dma_memcpy(u32 *outcopy, -+ u32 *out_dma, -+ u8 *out_arg, -+ int nbytes) -+{ -+ lq_crypto_ops.aes_dma_memcpy(outcopy, out_dma, out_arg, nbytes); -+} -+ -+static inline void deu_des_dma_memcpy(u32 *outcopy, -+ u32 *out_dma, -+ u8 *out_arg, -+ int nbytes) -+{ -+ lq_crypto_ops.des_dma_memcpy(outcopy, out_dma, out_arg, nbytes); -+} -+ -+static inline void deu_dma_free(u32 *addr) -+{ -+ lq_crypto_ops.dma_free(addr); -+} -+ -+static inline int deu_dma_init(void) -+{ -+ lq_crypto_ops.dma_init(); -+} -+ -+static inline void deu_dma_exit(void) -+{ -+ lq_crypto_ops.dma_exit(); -+} -+#endif -+ -+/* } */ -+ -+#define DEU_WAKELIST_INIT(queue) \ -+ init_waitqueue_head(&queue) -+ -+#define DEU_WAIT_EVENT_TIMEOUT(queue, event, flags, timeout) \ -+ do { \ -+ wait_event_interruptible_timeout((queue), \ -+ test_bit((event), \ -+ &(flags)), (timeout)); \ -+ clear_bit((event), &(flags)); \ -+ }while (0) -+ -+ -+#define DEU_WAKEUP_EVENT(queue, event, flags) \ -+ do { \ -+ set_bit((event), &(flags)); \ -+ wake_up_interruptible(&(queue)); \ -+ }while (0) -+ -+#define DEU_WAIT_EVENT(queue, event, flags) \ -+ do { \ -+ wait_event_interruptible(queue, \ -+ test_bit((event), &(flags))); \ -+ clear_bit((event), &(flags)); \ -+ }while (0) -+ -+struct deu_drv_priv { -+ wait_queue_head_t deu_thread_wait; -+#define DEU_EVENT 1 -+ volatile long deu_event_flags; -+ u8 *deu_rx_buf; -+ u32 deu_rx_len; -+}; -+ -+#ifdef CRYPTO_DEBUG -+extern char deu_debug_level; -+# define DPRINTF(level, format, args...) \ -+ if (level < deu_debug_level) \ -+ printk(KERN_INFO "[%s %s %d]: " format, \ -+ __FILE__, __func__, __LINE__, ##args) -+#else -+# define DPRINTF(level, format, args...) do { } while(0) -+#endif -+ -+#endif /* DEU_H */ ---- /dev/null -+++ b/drivers/crypto/lantiq/deu_ar9.c -@@ -0,0 +1,327 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <asm/io.h> /* dma_cache_inv */ -+#include <linux/platform_device.h> -+ -+#ifdef CONFIG_SOC_LANTIQ_XWAY -+ -+#include "deu.h" -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief Lantiq DEU driver module -+*/ -+ -+/** -+ \file deu_ar9.c -+ \brief Lantiq DEU board specific driver file for ar9 -+*/ -+ -+/** -+ \defgroup BOARD_SPECIFIC_FUNCTIONS LQ_BOARD_SPECIFIC_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief board specific functions -+*/ -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+struct lq_deu_device lq_deu[1]; -+ -+static u8 *g_dma_page_ptr = NULL; -+static u8 *g_dma_block = NULL; -+static u8 *g_dma_block2 = NULL; -+ -+/** \fn int dma_init(void) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief Initialize DMA for DEU usage. DMA specific registers are -+ * intialized here, including a pointer to the device, memory -+ * space for the device and DEU-DMA descriptors -+ * \return -1: fail, 0: SUCCESS -+*/ -+static int dma_init(void) -+{ -+ volatile struct deu_dma *dma = (struct deu_dma *) LQ_DEU_DMA_CON; -+ struct dma_device_info *dma_device = NULL; -+ int i = 0; -+ -+ struct dma_device_info *deu_dma_device_ptr; -+ -+ /* get one free page and share between g_dma_block and g_dma_block2 */ -+ printk("PAGE_SIZE = %ld\n", PAGE_SIZE); -+ /* need 16-byte alignment memory block */ -+ g_dma_page_ptr = (u8 *)__get_free_page(GFP_KERNEL); -+ /* need 16-byte alignment memory block */ -+ g_dma_block = g_dma_page_ptr; -+ /* need 16-byte alignment memory block */ -+ g_dma_block2 = (u8 *)(g_dma_page_ptr + (PAGE_SIZE >> 1)); -+ -+ /* deu_dma_priv_init(); */ -+ -+ deu_dma_device_ptr = dma_device_reserve("DEU"); -+ if (!deu_dma_device_ptr) { -+ printk("DEU: reserve DMA fail!\n"); -+ return -1; -+ } -+ lq_deu[0].dma_device = deu_dma_device_ptr; -+ -+ dma_device = deu_dma_device_ptr; -+ /* dma_device->priv = &deu_dma_priv; */ -+ dma_device->buffer_alloc = &deu_dma_buffer_alloc; -+ dma_device->buffer_free = &deu_dma_buffer_free; -+ dma_device->intr_handler = &deu_dma_intr_handler; -+ -+ dma_device->tx_endianness_mode = LQ_DMA_ENDIAN_TYPE3; -+ dma_device->rx_endianness_mode = LQ_DMA_ENDIAN_TYPE3; -+ dma_device->port_num = 1; -+ dma_device->tx_burst_len = 2; -+ dma_device->rx_burst_len = 2; -+ dma_device->max_rx_chan_num = 1; -+ dma_device->max_tx_chan_num = 1; -+ dma_device->port_packet_drop_enable = 0; -+ -+ for (i = 0; i < dma_device->max_rx_chan_num; i++) { -+ dma_device->rx_chan[i]->packet_size = DEU_MAX_PACKET_SIZE; -+ dma_device->rx_chan[i]->desc_len = 1; -+ dma_device->rx_chan[i]->control = LQ_DMA_CH_ON; -+ dma_device->rx_chan[i]->byte_offset = 0; -+ dma_device->rx_chan[i]->chan_poll_enable = 1; -+ } -+ -+ for (i = 0; i < dma_device->max_tx_chan_num; i++) { -+ dma_device->tx_chan[i]->control = LQ_DMA_CH_ON; -+ dma_device->tx_chan[i]->desc_len = 1; -+ dma_device->tx_chan[i]->chan_poll_enable = 1; -+ } -+ -+ dma_device->current_tx_chan = 0; -+ dma_device->current_rx_chan = 0; -+ -+ i = dma_device_register(dma_device); -+ for (i = 0; i < dma_device->max_rx_chan_num; i++) { -+ (dma_device->rx_chan[i])->open(dma_device->rx_chan[i]); -+ } -+ -+ dma->ctrl.BS = 0; -+ dma->ctrl.RXCLS = 0; -+ dma->ctrl.EN = 1; -+ -+ return 0; -+} -+ -+/** \fn u32 *dma_align(const u8 *arg, u32 *buffer_alloc, int in_buff, int nbytes) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief Not used for AR9 -+ * \param arg Pointer to the input / output memory address -+ * \param buffer_alloc A pointer to the buffer -+ * \param in_buff Input (if == 1) or Output (if == 0) buffer -+ * \param nbytes Number of bytes of data -+*/ -+static u32 *dma_align(const u8 *arg, u32 *buffer_alloc, int in_buff, int nbytes) -+{ -+ return (u32 *) arg; -+} -+ -+/** \fn void aes_dma_memcpy(u32 *outcopy, u32 *out_dma, u8 *out_arg, int nbytes) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief copy the DMA data to the memory address space for AES -+ * \param outcopy Not used -+ * \param out_dma A pointer to the memory address that stores the DMA data -+ * \param out_arg The pointer to the memory address that needs to be copied to] -+ * \param nbytes Number of bytes of data -+*/ -+static void aes_dma_memcpy(u32 *outcopy, u32 *out_dma, u8 *out_arg, int nbytes) -+{ -+ memcpy(out_arg, out_dma, nbytes); -+} -+ -+/** \fn void des_dma_memcpy(u32 *outcopy, u32 *out_dma, u8 *out_arg, int nbytes) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief copy the DMA data to the memory address space for DES -+ * \param outcopy Not used -+ * \param out_dma A pointer to the memory address that stores the DMA data -+ * \param out_arg The pointer to the memory address that needs to be copied to] -+ * \param nbytes Number of bytes of data -+*/ -+static void des_dma_memcpy(u32 *outcopy, u32 *out_dma, u8 *out_arg, int nbytes) -+{ -+ memcpy(out_arg, out_dma, nbytes); -+} -+ -+/** \fn dma_exit(void) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief unregister dma devices after exit -+*/ -+static void dma_exit(void) -+{ -+ if (g_dma_page_ptr) -+ free_page((u32) g_dma_page_ptr); -+ dma_device_release(lq_deu[0].dma_device); -+ dma_device_unregister(lq_deu[0].dma_device); -+} -+#endif /* CONFIG_CRYPTO_DEV_LANTIQ_DMA */ -+ -+/** \fn u32 endian_swap(u32 input) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief Swap data given to the function -+ * \param input Data input to be swapped -+ * \return either the swapped data or the input data depending on whether it is in DMA mode or FPI mode -+*/ -+static u32 endian_swap(u32 input) -+{ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ u8 *ptr = (u8 *)&input; -+ return ((ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | ptr[0]); -+#else -+ return input; -+#endif -+} -+ -+/** \fn u32 input_swap(u32 input) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief Not used -+ * \return input -+*/ -+static u32 input_swap(u32 input) -+{ -+ return input; -+} -+ -+/** \fn void aes_chip_init(void) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief initialize AES hardware -+*/ -+static void aes_chip_init(void) -+{ -+ volatile struct deu_aes *aes = (struct deu_aes *) AES_START; -+ -+ aes->ctrl.SM = 1; -+#ifndef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ aes->ctrl.ARS = 1; -+#else -+ aes->ctrl.NDC = 1; /* to write to ENDI */ -+ asm("sync"); -+ aes->ctrl.ENDI = 0; -+ asm("sync"); -+ aes->ctrl.ARS = 0; /* 0 for dma */ -+ asm("sync"); -+#endif -+} -+ -+/** \fn void des_chip_init(void) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief initialize DES hardware -+*/ -+static void des_chip_init(void) -+{ -+ volatile struct deu_des *des = (struct deu_des *) DES_3DES_START; -+ -+#ifndef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ /* start crypto engine with write to ILR */ -+ des->ctrl.SM = 1; -+ asm("sync"); -+ des->ctrl.ARS = 1; -+#else -+ des->ctrl.SM = 1; -+ des->ctrl.NDC = 1; -+ asm("sync"); -+ des->ctrl.ENDI = 0; -+ asm("sync"); -+ des->ctrl.ARS = 0; /* 0 for dma */ -+ -+#endif -+} -+ -+static u32 chip_init(void) -+{ -+ volatile struct deu_clk_ctrl *clc = (struct deu_clk_ctrl *) LQ_DEU_CLK; -+ -+#if 0 -+ lq_pmu_enable(1<<20); -+#endif -+ -+ clc->FSOE = 0; -+ clc->SBWE = 0; -+ clc->SPEN = 0; -+ clc->SBWE = 0; -+ clc->DISS = 0; -+ clc->DISR = 0; -+ -+ return *LQ_DEU_ID; -+} -+ -+static int lq_crypto_probe(struct platform_device *pdev) -+{ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ lq_crypto_ops.dma_init = dma_init; -+ lq_crypto_ops.dma_exit = dma_exit; -+ lq_crypto_ops.aes_dma_memcpy = aes_dma_memcpy; -+ lq_crypto_ops.des_dma_memcpy = des_dma_memcpy; -+ lq_crypto_ops.aes_dma_malloc = aes_dma_malloc; -+ lq_crypto_ops.des_dma_malloc = des_dma_malloc; -+ lq_crypto_ops.dma_align = dma_align; -+ lq_crypto_ops.dma_free = dma_free; -+#endif -+ -+ lq_crypto_ops.endian_swap = endian_swap; -+ lq_crypto_ops.input_swap = input_swap; -+ lq_crypto_ops.aes_chip_init = aes_chip_init; -+ lq_crypto_ops.des_chip_init = des_chip_init; -+ lq_crypto_ops.chip_init = chip_init; -+ -+ printk("lq_ar9_deu: driver loaded!\n"); -+ -+ lq_deu_init(); -+ -+ return 0; -+} -+ -+static int lq_crypto_remove(struct platform_device *pdev) -+{ -+ lq_deu_exit(); -+ -+ return 0; -+} -+ -+static struct platform_driver lq_crypto = { -+ .probe = lq_crypto_probe, -+ .remove = lq_crypto_remove, -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "lq_ar9_deu" -+ } -+}; -+ -+static int __init lq_crypto_init(void) -+{ -+ return platform_driver_register(&lq_crypto); -+} -+module_init(lq_crypto_init); -+ -+static void __exit lq_crypto_exit(void) -+{ -+ platform_driver_unregister(&lq_crypto); -+} -+module_exit(lq_crypto_exit); -+ -+#endif ---- /dev/null -+++ b/drivers/crypto/lantiq/deu_ar9.h -@@ -0,0 +1,291 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus / Infineon Technologies -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief DEU driver module -+*/ -+ -+/** -+ \defgroup LQ_DEU_DEFINITIONS LQ_DEU_DEFINITIONS -+ \ingroup LQ_DEU -+ \brief Lantiq DEU definitions -+*/ -+ -+/** -+ \file deu_ar9.h -+ \brief DEU driver header file -+*/ -+ -+ -+#ifndef DEU_AR9_H -+#define DEU_AR9_H -+ -+#define LQ_DEU_BASE_ADDR (KSEG1 | 0x1E103100) -+#define LQ_DEU_CLK ((volatile u32 *)(LQ_DEU_BASE_ADDR + 0x0000)) -+#define LQ_DEU_ID ((volatile u32 *)(LQ_DEU_BASE_ADDR + 0x0008)) -+#define LQ_DES_CON ((volatile u32 *)(LQ_DEU_BASE_ADDR + 0x0010)) -+#define LQ_AES_CON ((volatile u32 *)(LQ_DEU_BASE_ADDR + 0x0050)) -+#define LQ_HASH_CON ((volatile u32 *)(LQ_DEU_BASE_ADDR + 0x00B0)) -+#define LQ_ARC4_CON ((volatile u32 *)(LQ_DEU_BASE_ADDR + 0x0100)) -+ -+#define ARC4_START LQ_ARC4_CON -+#define DES_3DES_START LQ_DES_CON -+#define HASH_START LQ_HASH_CON -+#define AES_START LQ_AES_CON -+ -+#ifdef CONFIG_CRYPTO_DEV_DMA -+# include "deu_dma.h" -+# define DEU_DWORD_REORDERING(ptr, buffer, in_out, bytes) \ -+ deu_dma_align(ptr, buffer, in_out, bytes) -+# define AES_MEMORY_COPY(outcopy, out_dma, out_arg, nbytes) \ -+ deu_aes_dma_memcpy(outcopy, out_dma, out_arg, nbytes) -+# define DES_MEMORY_COPY(outcopy, out_dma, out_arg, nbytes) \ -+ deu_des_dma_memcpy(outcopy, out_dma, out_arg, nbytes) -+# define BUFFER_IN 1 -+# define BUFFER_OUT 0 -+# define AES_ALGO 1 -+# define DES_ALGO 0 -+# define ALLOCATE_MEMORY(val, type) 1 -+# define FREE_MEMORY(buff) -+extern struct lq_deu_device lq_deu[1]; -+#endif /* CONFIG_CRYPTO_DEV_DMA */ -+ -+/* SHA CONSTANTS */ -+#define HASH_CON_VALUE 0x0700002C -+ -+#define INPUT_ENDIAN_SWAP(input) deu_input_swap(input) -+#define DEU_ENDIAN_SWAP(input) deu_endian_swap(input) -+#define DELAY_PERIOD 10 -+#define FIND_DEU_CHIP_VERSION chip_version() -+ -+#define WAIT_AES_DMA_READY() \ -+ do { \ -+ int i; \ -+ volatile struct deu_dma *dma = \ -+ (struct deu_dma *) LQ_DEU_DMA_CON; \ -+ volatile struct deu_aes *aes = \ -+ (volatile struct deu_aes *) AES_START; \ -+ for (i = 0; i < 10; i++) \ -+ udelay(DELAY_PERIOD); \ -+ while (dma->ctrl.BSY) {}; \ -+ while (aes->ctrl.BUS) {}; \ -+ } while (0) -+ -+#define WAIT_DES_DMA_READY() \ -+ do { \ -+ int i; \ -+ volatile struct deu_dma *dma = \ -+ (struct deu_dma *) LQ_DEU_DMA_CON; \ -+ volatile struct deu_des *des = \ -+ (struct deu_des *) DES_3DES_START; \ -+ for (i = 0; i < 10; i++) \ -+ udelay(DELAY_PERIOD); \ -+ while (dma->ctrl.BSY) {}; \ -+ while (des->ctrl.BUS) {}; \ -+ } while (0) -+ -+#define AES_DMA_MISC_CONFIG() \ -+ do { \ -+ volatile struct deu_aes *aes = \ -+ (volatile struct deu_aes *) AES_START; \ -+ aes->ctrl.KRE = 1; \ -+ aes->ctrl.GO = 1; \ -+ } while(0) -+ -+#define SHA_HASH_INIT \ -+ do { \ -+ volatile struct deu_hash *hash = \ -+ (struct deu_hash *) HASH_START; \ -+ hash->ctrl.SM = 1; \ -+ hash->ctrl.ALGO = 0; \ -+ hash->ctrl.INIT = 1; \ -+ } while(0) -+ -+/* DEU Common Structures for AR9*/ -+ -+struct deu_clk_ctrl { -+ u32 Res:26; -+ u32 FSOE:1; -+ u32 SBWE:1; -+ u32 EDIS:1; -+ u32 SPEN:1; -+ u32 DISS:1; -+ u32 DISR:1; -+}; -+ -+struct deu_des { -+ struct deu_des_ctrl { /* 10h */ -+ u32 KRE:1; -+ u32 reserved1:5; -+ u32 GO:1; -+ u32 STP:1; -+ u32 Res2:6; -+ u32 NDC:1; -+ u32 ENDI:1; -+ u32 Res3:2; -+ u32 F:3; -+ u32 O:3; -+ u32 BUS:1; -+ u32 DAU:1; -+ u32 ARS:1; -+ u32 SM:1; -+ u32 E_D:1; -+ u32 M:3; -+ } ctrl; -+ -+ u32 IHR; /* 14h */ -+ u32 ILR; /* 18h */ -+ u32 K1HR; /* 1c */ -+ u32 K1LR; -+ u32 K2HR; -+ u32 K2LR; -+ u32 K3HR; -+ u32 K3LR; /* 30h */ -+ u32 IVHR; /* 34h */ -+ u32 IVLR; /* 38 */ -+ u32 OHR; /* 3c */ -+ u32 OLR; /* 40 */ -+}; -+ -+struct deu_aes { -+ struct deu_aes_ctrl { -+ u32 KRE:1; -+ u32 reserved1:4; -+ u32 PNK:1; -+ u32 GO:1; -+ u32 STP:1; -+ u32 reserved2:6; -+ u32 NDC:1; -+ u32 ENDI:1; -+ u32 reserved3:2; -+ u32 F:3; /* fbs */ -+ u32 O:3; /* om */ -+ u32 BUS:1; /* bsy */ -+ u32 DAU:1; -+ u32 ARS:1; -+ u32 SM:1; -+ u32 E_D:1; -+ u32 KV:1; -+ u32 K:2; /* KL */ -+ } ctrl; -+ -+ u32 ID3R; /* 80h */ -+ u32 ID2R; /* 84h */ -+ u32 ID1R; /* 88h */ -+ u32 ID0R; /* 8Ch */ -+ u32 K7R; /* 90h */ -+ u32 K6R; /* 94h */ -+ u32 K5R; /* 98h */ -+ u32 K4R; /* 9Ch */ -+ u32 K3R; /* A0h */ -+ u32 K2R; /* A4h */ -+ u32 K1R; /* A8h */ -+ u32 K0R; /* ACh */ -+ u32 IV3R; /* B0h */ -+ u32 IV2R; /* B4h */ -+ u32 IV1R; /* B8h */ -+ u32 IV0R; /* BCh */ -+ u32 OD3R; /* D4h */ -+ u32 OD2R; /* D8h */ -+ u32 OD1R; /* DCh */ -+ u32 OD0R; /* E0h */ -+}; -+ -+struct deu_arc4 { -+ struct arc4_controlr { -+ u32 KRE:1; -+ u32 KLEN:4; -+ u32 KSAE:1; -+ u32 GO:1; -+ u32 STP:1; -+ u32 reserved1:6; -+ u32 NDC:1; -+ u32 ENDI:1; -+ u32 reserved2:8; -+ u32 BUS:1; /* bsy */ -+ u32 reserved3:1; -+ u32 ARS:1; -+ u32 SM:1; -+ u32 reserved4:4; -+ } ctrl; -+ -+ u32 K3R; /* 104h */ -+ u32 K2R; /* 108h */ -+ u32 K1R; /* 10Ch */ -+ u32 K0R; /* 110h */ -+ u32 IDLEN; /* 114h */ -+ u32 ID3R; /* 118h */ -+ u32 ID2R; /* 11Ch */ -+ u32 ID1R; /* 120h */ -+ u32 ID0R; /* 124h */ -+ u32 OD3R; /* 128h */ -+ u32 OD2R; /* 12Ch */ -+ u32 OD1R; /* 130h */ -+ u32 OD0R; /* 134h */ -+}; -+ -+struct deu_hash { -+ struct deu_hash_ctrl { -+ u32 reserved1:5; -+ u32 KHS:1; -+ u32 GO:1; -+ u32 INIT:1; -+ u32 reserved2:6; -+ u32 NDC:1; -+ u32 ENDI:1; -+ u32 reserved3:7; -+ u32 DGRY:1; -+ u32 BSY:1; -+ u32 reserved4:1; -+ u32 IRCL:1; -+ u32 SM:1; -+ u32 KYUE:1; -+ u32 HMEN:1; -+ u32 SSEN:1; -+ u32 ALGO:1; -+ } ctrl; -+ -+ u32 MR; /* B4h */ -+ u32 D1R; /* B8h */ -+ u32 D2R; /* BCh */ -+ u32 D3R; /* C0h */ -+ u32 D4R; /* C4h */ -+ u32 D5R; /* C8h */ -+ u32 dummy; /* CCh */ -+ u32 KIDX; /* D0h */ -+ u32 KEY; /* D4h */ -+ u32 DBN; /* D8h */ -+}; -+ -+struct deu_dma { -+ struct deu_dma_ctrl { -+ u32 reserved1:22; -+ u32 BS:2; -+ u32 BSY:1; -+ u32 reserved2:1; -+ u32 ALGO:2; -+ u32 RXCLS:2; -+ u32 reserved3:1; -+ u32 EN:1; -+ } ctrl; -+}; -+ -+#endif /* DEU_AR9_H */ ---- /dev/null -+++ b/drivers/crypto/lantiq/deu_danube.c -@@ -0,0 +1,484 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <asm/io.h> /* dma_cache_inv */ -+#include <linux/platform_device.h> -+ -+#ifdef CONFIG_SOC_LANTIQ_XWAY -+ -+#include "deu.h" -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief DEU driver module -+*/ -+ -+/** -+ \file deu_danube.c -+ \ingroup LQ_DEU -+ \brief board specific DEU driver file for danube -+*/ -+ -+/** -+ \defgroup BOARD_SPECIFIC_FUNCTIONS LQ_BOARD_SPECIFIC_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief board specific DEU functions -+*/ -+ -+static int danube_pre_1_4; -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+u32 *des_buff_in = NULL; -+u32 *des_buff_out = NULL; -+u32 *aes_buff_in = NULL; -+u32 *aes_buff_out = NULL; -+ -+struct lq_deu_device lq_deu[1]; -+ -+static u8 *g_dma_page_ptr = NULL; -+static u8 *g_dma_block = NULL; -+static u8 *g_dma_block2 = NULL; -+ -+/** \fn int dma_init(void) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief Initialize DMA for DEU usage. DMA specific registers are -+ * intialized here, including a pointer to the device, memory -+ * space for the device and DEU-DMA descriptors -+ * \return -1 if fail, otherwise return 0 -+*/ -+static int dma_init(void) -+{ -+ struct dma_device_info *dma_device = NULL; -+ int i = 0; -+ volatile struct deu_dma *dma = (struct deu_dma *) LQ_DEU_DMA_CON; -+ struct dma_device_info *deu_dma_device_ptr; -+ -+ /* get one free page and share between g_dma_block and g_dma_block2 */ -+ printk("PAGE_SIZE = %ld\n", PAGE_SIZE); -+ /* need 16-byte alignment memory block */ -+ g_dma_page_ptr = (u8 *)__get_free_page(GFP_KERNEL); -+ /* need 16-byte alignment memory block */ -+ g_dma_block = g_dma_page_ptr; -+ /* need 16-byte alignment memory block */ -+ g_dma_block2 = (u8 *)(g_dma_page_ptr + (PAGE_SIZE >> 1)); -+ -+ deu_dma_device_ptr = dma_device_reserve("DEU"); -+ if (!deu_dma_device_ptr) { -+ printk("DEU: reserve DMA fail!\n"); -+ return -1; -+ } -+ lq_deu[0].dma_device = deu_dma_device_ptr; -+ dma_device = deu_dma_device_ptr; -+ /* dma_device->priv = &deu_dma_priv; */ -+ dma_device->buffer_alloc = &deu_dma_buffer_alloc; -+ dma_device->buffer_free = &deu_dma_buffer_free; -+ dma_device->intr_handler = &deu_dma_intr_handler; -+ dma_device->tx_endianness_mode = LQ_DMA_ENDIAN_TYPE3; -+ dma_device->rx_endianness_mode = LQ_DMA_ENDIAN_TYPE3; -+ dma_device->port_num = 1; -+ dma_device->tx_burst_len = 4; -+ dma_device->max_rx_chan_num = 1; -+ dma_device->max_tx_chan_num = 1; -+ dma_device->port_packet_drop_enable = 0; -+ -+ for (i = 0; i < dma_device->max_rx_chan_num; i++) { -+ dma_device->rx_chan[i]->packet_size = DEU_MAX_PACKET_SIZE; -+ dma_device->rx_chan[i]->desc_len = 1; -+ dma_device->rx_chan[i]->control = LQ_DMA_CH_ON; -+ dma_device->rx_chan[i]->byte_offset = 0; -+ dma_device->rx_chan[i]->chan_poll_enable = 1; -+ -+ } -+ -+ for (i = 0; i < dma_device->max_tx_chan_num; i++) { -+ dma_device->tx_chan[i]->control = LQ_DMA_CH_ON; -+ dma_device->tx_chan[i]->desc_len = 1; -+ dma_device->tx_chan[i]->chan_poll_enable = 1; -+ } -+ -+ dma_device->current_tx_chan = 0; -+ dma_device->current_rx_chan = 0; -+ -+ dma_device_register(dma_device); -+ for (i = 0; i < dma_device->max_rx_chan_num; i++) { -+ (dma_device->rx_chan[i])->open(dma_device->rx_chan[i]); -+ } -+ -+ dma->ctrl.BS = 0; -+ dma->ctrl.RXCLS = 0; -+ dma->ctrl.EN = 1; -+ -+ -+ *LQ_DMA_PS = 1; -+ -+ /* DANUBE PRE 1.4 SOFTWARE FIX */ -+ if (danube_pre_1_4) -+ *LQ_DMA_PCTRL = 0x14; -+ else -+ *LQ_DMA_PCTRL = 0xF14; -+ -+ return 0; -+} -+ -+/** \fn u32 *dma_align(const u8 *arg, u32 *buffer_alloc, int in_buff, int nbytes) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief A fix to align mis-aligned address for Danube version 1.3 chips -+ * which has memory alignment issues. -+ * \param arg Pointer to the input / output memory address -+ * \param buffer_alloc A pointer to the buffer -+ * \param in_buff Input (if == 1) or Output (if == 0) buffer -+ * \param nbytes Number of bytes of data -+ * \return returns arg: if address is aligned, buffer_alloc: if memory address is not aligned -+*/ -+static u32 *dma_align(const u8 *arg, u32 *buffer_alloc, int in_buff, int nbytes) -+{ -+ if (danube_pre_1_4) { -+ /* for input buffer */ -+ if (in_buff) { -+ if (((u32) arg) & 0xF) { -+ memcpy(buffer_alloc, arg, nbytes); -+ return (u32 *) buffer_alloc; -+ } else { -+ return (u32 *) arg; -+ } -+ } -+ else { -+ /* for output buffer */ -+ if (((u32) arg) & 0x3) -+ return buffer_alloc; -+ else -+ return (u32 *) arg; -+ } -+ } -+ -+ return (u32 *) arg; -+} -+ -+/** \fn void aes_dma_memcpy(u32 *outcopy, u32 *out_dma, u8 *out_arg, int nbytes) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief copy the DMA data to the memory address space for AES. The swaping -+ * of the 4 bytes is done only for Danube version 1.3 (FIX). Otherwise, -+ * it is a direct memory copy to out_arg pointer -+ * \param outcopy Pointer to the address to store swapped copy -+ * \param out_dma A pointer to the memory address that stores the DMA data -+ * \param out_arg The pointer to the memory address that needs to be copied to -+ * \param nbytes Number of bytes of data -+*/ -+static void aes_dma_memcpy(u32 *outcopy, u32 *out_dma, u8 *out_arg, int nbytes) -+{ -+ int i = 0; -+ int x = 0; -+ -+ /* DANUBE PRE 1.4 SOFTWARE FIX */ -+ if (danube_pre_1_4) { -+ for (i = 0; i < (nbytes / 4); i++) { -+ x = i ^ 0x3; -+ outcopy[i] = out_dma[x]; -+ -+ } -+ if (((u32) out_arg) & 0x3) { -+ memcpy((u8 *)out_arg, outcopy, nbytes); -+ } -+ } else { -+ memcpy(out_arg, out_dma, nbytes); -+ } -+} -+ -+/** \fn void des_dma_memcpy(u32 *outcopy, u32 *out_dma, u8 *out_arg, int nbytes) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief copy the DMA data to the memory address space for DES. The swaping -+ * of the 4 bytes is done only for Danube version 1.3 (FIX). Otherwise, -+ * it is a direct memory copy to out_arg pointer -+ * \param outcopy Pointer to the address to store swapped copy -+ * \param out_dma A pointer to the memory address that stores the DMA data -+ * \param out_arg The pointer to the memory address that needs to be copied to -+ * \param nbytes Number of bytes of data -+*/ -+static void des_dma_memcpy(u32 *outcopy, u32 *out_dma, u8 *out_arg, int nbytes) -+{ -+ int i = 0; -+ int x = 0; -+ -+ /* DANUBE PRE 1.4 SOFTWARE FIX */ -+ if (danube_pre_1_4) { -+ for (i = 0; i < (nbytes / 4); i++) { -+ x = i ^ 1; -+ outcopy[i] = out_dma[x]; -+ -+ } -+ if (((u32) out_arg) & 0x3) { -+ memcpy((u8 *)out_arg, outcopy, nbytes); -+ } -+ } else { -+ memcpy(out_arg, out_dma, nbytes); -+ } -+} -+ -+/** \fn int des_dma_malloc(int value) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief allocates memory to the necessary memory input/output buffer -+ * location, used during the DES algorithm DMA transfer (memory -+ * alignment issues) -+ * \param value value determinds whether the calling of the function is for a -+ * input buffer or for an output buffer memory allocation -+*/ -+static int des_dma_malloc(int value) -+{ -+ if (danube_pre_1_4) { -+ if (value == BUFFER_IN) { -+ des_buff_in = kmalloc(DEU_MAX_PACKET_SIZE, GFP_ATOMIC); -+ if (!des_buff_in) -+ return -1; -+ else -+ return 0; -+ } -+ else { -+ des_buff_out = kmalloc(DEU_MAX_PACKET_SIZE, GFP_ATOMIC); -+ if (!des_buff_out) -+ return -1; -+ else -+ return 0; -+ } -+ } else { -+ return 0; -+ } -+} -+ -+/** \fn int aes_dma_malloc(int value) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief allocates memory to the necessary memory input/output buffer -+ * location, used during the AES algorithm DMA transfer (memory -+ * alignment issues) -+ * \param value value determinds whether the calling of the function is for a -+ * input buffer or for an output buffer memory allocation -+*/ -+static int aes_dma_malloc(int value) -+{ -+ if (danube_pre_1_4) { -+ if (value == BUFFER_IN) { -+ aes_buff_in = kmalloc(DEU_MAX_PACKET_SIZE, GFP_ATOMIC); -+ if (!aes_buff_in) -+ return -1; -+ else -+ return 0; -+ } -+ else { -+ aes_buff_out = kmalloc(DEU_MAX_PACKET_SIZE, GFP_ATOMIC); -+ if (!aes_buff_out) -+ return -1; -+ else -+ return 0; -+ } -+ } else { -+ return 0; -+ } -+} -+ -+/** \fn void dma_free(u32 *addr) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief frees previously allocated memory -+ * \param addr memory address of the buffer that needs to be freed -+*/ -+static void dma_free(u32 *addr) -+{ -+ if (addr) -+ kfree(addr); -+ return; -+} -+ -+/** \fn dma_exit(void) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief unregister dma devices after exit -+*/ -+static void dma_exit(void) -+{ -+ if (g_dma_page_ptr) -+ free_page((u32) g_dma_page_ptr); -+ dma_device_release(lq_deu[0].dma_device); -+ dma_device_unregister(lq_deu[0].dma_device); -+} -+#endif /* CONFIG_CRYPTO_DEV_LANTIQ_DMA */ -+ -+/** \fn u32 endian_swap(u32 input) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief function is not used -+ * \param input Data input to be swapped -+ * \return input -+*/ -+static u32 endian_swap(u32 input) -+{ -+ return input; -+} -+ -+/** \fn u32 input_swap(u32 input) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief Swap the input data if the current chip is Danube version -+ * 1.4 and do nothing to the data if the current chip is -+ * Danube version 1.3 -+ * \param input data that needs to be swapped -+ * \return input or swapped input -+*/ -+static u32 input_swap(u32 input) -+{ -+ if (!danube_pre_1_4) { -+ u8 *ptr = (u8 *)&input; -+ return ((ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | ptr[0]); -+ } else { -+ return input; -+ } -+} -+ -+/** \fn void aes_chip_init(void) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief initialize AES hardware -+*/ -+static void aes_chip_init(void) -+{ -+ volatile struct deu_aes *aes = (struct deu_aes *) AES_START; -+ -+#ifndef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ /* start crypto engine with write to ILR */ -+ aes->ctrl.SM = 1; -+ aes->ctrl.ARS = 1; -+#else -+ aes->ctrl.SM = 1; -+ aes->ctrl.ARS = 1; /* 0 for dma */ -+#endif -+} -+ -+/** \fn void des_chip_init(void) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief initialize DES hardware -+*/ -+static void des_chip_init(void) -+{ -+ volatile struct deu_des *des = (struct deu_des *) DES_3DES_START; -+ -+#ifndef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ /* start crypto engine with write to ILR */ -+ des->ctrl.SM = 1; -+ des->ctrl.ARS = 1; -+#else -+ des->ctrl.SM = 1; -+ des->ctrl.ARS = 1; /* 0 for dma */ -+#endif -+} -+ -+/** \fn void deu_chip_version(void) -+ * \ingroup LQ_DES_FUNCTIONS -+ * \brief To find the version of the chip by looking at the chip ID -+ * \param danube_pre_1_4 (sets to 1 if Chip is Danube less than v1.4) -+*/ -+static void deu_chip_version(void) -+{ -+ /* DANUBE PRE 1.4 SOFTWARE FIX */ -+ int chip_id = 0; -+ chip_id = *LQ_MPS_CHIPID; -+ chip_id >>= 28; -+ -+ if (chip_id >= 4) { -+ danube_pre_1_4 = 0; -+ printk("Danube Chip ver. 1.4 detected. \n"); -+ } -+ else { -+ danube_pre_1_4 = 1; -+ printk("Danube Chip ver. 1.3 or below detected. \n"); -+ } -+} -+ -+static u32 chip_init(void) -+{ -+ volatile struct deu_clk_ctrl *clc = (struct deu_clk_ctrl *) LQ_DEU_CLK; -+ -+#if 0 -+ lq_pmu_enable(1<<20); -+#endif -+ -+ deu_chip_version(); -+ -+ clc->FSOE = 0; -+ clc->SBWE = 0; -+ clc->SPEN = 0; -+ clc->SBWE = 0; -+ clc->DISS = 0; -+ clc->DISR = 0; -+ -+ return *LQ_DEU_ID; -+} -+ -+static int lq_crypto_probe(struct platform_device *pdev) -+{ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ lq_crypto_ops.dma_init = dma_init; -+ lq_crypto_ops.dma_exit = dma_exit; -+ lq_crypto_ops.aes_dma_memcpy = aes_dma_memcpy; -+ lq_crypto_ops.des_dma_memcpy = des_dma_memcpy; -+ lq_crypto_ops.aes_dma_malloc = aes_dma_malloc; -+ lq_crypto_ops.des_dma_malloc = des_dma_malloc; -+ lq_crypto_ops.dma_align = dma_align; -+ lq_crypto_ops.dma_free = dma_free; -+#endif -+ -+ lq_crypto_ops.endian_swap = endian_swap; -+ lq_crypto_ops.input_swap = input_swap; -+ lq_crypto_ops.aes_chip_init = aes_chip_init; -+ lq_crypto_ops.des_chip_init = des_chip_init; -+ lq_crypto_ops.chip_init = chip_init; -+ -+ printk("lq_danube_deu: driver loaded!\n"); -+ -+ lq_deu_init(); -+ -+ return 0; -+} -+ -+static int lq_crypto_remove(struct platform_device *pdev) -+{ -+ lq_deu_exit(); -+ -+ return 0; -+} -+ -+static struct platform_driver lq_crypto = { -+ .probe = lq_crypto_probe, -+ .remove = lq_crypto_remove, -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "lq_danube_deu" -+ } -+}; -+ -+static int __init lq_crypto_init(void) -+{ -+ return platform_driver_register(&lq_crypto); -+} -+module_init(lq_crypto_init); -+ -+static void __exit lq_crypto_exit(void) -+{ -+ platform_driver_unregister(&lq_crypto); -+} -+module_exit(lq_crypto_exit); -+ -+#endif ---- /dev/null -+++ b/drivers/crypto/lantiq/deu_danube.h -@@ -0,0 +1,255 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus / Infineon Technologies -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief DEU driver module -+*/ -+ -+/** -+ \file deu_danube.h -+ \brief board specific driver header file for danube -+*/ -+ -+/** -+ \defgroup BOARD_SPECIFIC_FUNCTIONS LQ_BOARD_SPECIFIC_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief board specific DEU header files -+*/ -+ -+#ifndef DEU_DANUBE_H -+#define DEU_DANUBE_H -+ -+#define LQ_DEU_BASE_ADDR (KSEG1 | 0x1E103100) -+#define LQ_DEU_CLK ((volatile u32 *)(LQ_DEU_BASE_ADDR + 0x0000)) -+#define LQ_DEU_ID ((volatile u32 *)(LQ_DEU_BASE_ADDR + 0x0008)) -+#define LQ_DES_CON ((volatile u32 *)(LQ_DEU_BASE_ADDR + 0x0010)) -+#define LQ_AES_CON ((volatile u32 *)(LQ_DEU_BASE_ADDR + 0x0050)) -+#define LQ_HASH_CON ((volatile u32 *)(LQ_DEU_BASE_ADDR + 0x00B0)) -+#define LQ_ARC4_CON ((volatile u32 *)(LQ_DEU_BASE_ADDR + 0x0100)) -+ -+#define ARC4_START LQ_ARC4_CON -+#define DES_3DES_START LQ_DES_CON -+#define HASH_START LQ_HASH_CON -+#define AES_START LQ_AES_CON -+ -+#define LQ_MPS (KSEG1 | 0x1F107000) -+#define LQ_MPS_CHIPID ((volatile u32*)(LQ_MPS + 0x0344)) -+#define LQ_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & 0xF) -+#define LQ_MPS_CHIPID_VERSION_SET(value) (((value) & 0xF) << 28) -+#define LQ_MPS_CHIPID_PARTNUM_GET(value) (((value) >> 12) & 0xFFFF) -+#define LQ_MPS_CHIPID_PARTNUM_SET(value) (((value) & 0xFFFF) << 12) -+#define LQ_MPS_CHIPID_MANID_GET(value) (((value) >> 1) & 0x7FF) -+#define LQ_MPS_CHIPID_MANID_SET(value) (((value) & 0x7FF) << 1) -+ -+#ifdef CONFIG_CRYPTO_DEV_DMA -+# define DEU_DWORD_REORDERING(ptr, buffer, in_out, bytes) \ -+ deu_dma_align(ptr, buffer, in_out, bytes) -+# define AES_MEMORY_COPY(outcopy, out_dma, out_arg, nbytes) \ -+ deu_aes_dma_memcpy(outcopy, out_dma, out_arg, nbytes) -+# define DES_MEMORY_COPY(outcopy, out_dma, out_arg, nbytes) \ -+ deu_des_dma_memcpy(outcopy, out_dma, out_arg, nbytes) -+# define BUFFER_IN 1 -+# define BUFFER_OUT 0 -+# define DELAY_PERIOD 9 -+# define AES_ALGO 1 -+# define DES_ALGO 0 -+# define FREE_MEMORY(buff) deu_dma_free(buff) -+# define ALLOCATE_MEMORY(val, type) type ? \ -+ deu_aes_dma_malloc(val) : \ -+ deu_des_dma_malloc(val) -+#endif /* CONFIG_CRYPTO_DEV_DMA */ -+ -+#define INPUT_ENDIAN_SWAP(input) deu_input_swap(input) -+#define DEU_ENDIAN_SWAP(input) deu_endian_swap(input) -+#define AES_DMA_MISC_CONFIG() -+ -+#define WAIT_AES_DMA_READY() \ -+ do { \ -+ int i; \ -+ volatile struct deu_dma *dma = \ -+ (struct deu_dma *) LQ_DEU_DMA_CON; \ -+ volatile struct deu_aes *aes = \ -+ (volatile struct deu_aes *) AES_START; \ -+ for (i = 0; i < 10; i++) \ -+ udelay(DELAY_PERIOD); \ -+ while (dma->ctrl.BSY) {}; \ -+ while (aes->ctrl.BUS) {}; \ -+ } while (0) -+ -+#define WAIT_DES_DMA_READY() \ -+ do { \ -+ int i; \ -+ volatile struct deu_dma *dma = \ -+ (struct deu_dma *) LQ_DEU_DMA_CON; \ -+ volatile struct deu_des *des = \ -+ (struct deu_des *) DES_3DES_START; \ -+ for (i = 0; i < 10; i++) \ -+ udelay(DELAY_PERIOD); \ -+ while (dma->ctrl.BSY) {}; \ -+ while (des->ctrl.BUS) {}; \ -+ } while (0) -+ -+#define SHA_HASH_INIT \ -+ do { \ -+ volatile struct deu_hash *hash = \ -+ (struct deu_hash *) HASH_START; \ -+ hash->ctrl.SM = 1; \ -+ hash->ctrl.ALGO = 0; \ -+ hash->ctrl.INIT = 1; \ -+ } while(0) -+ -+/* DEU STRUCTURES */ -+ -+struct deu_clk_ctrl { -+ u32 Res:26; -+ u32 FSOE:1; -+ u32 SBWE:1; -+ u32 EDIS:1; -+ u32 SPEN:1; -+ u32 DISS:1; -+ u32 DISR:1; -+}; -+ -+struct deu_des { -+ struct deu_des_ctrl { -+ u32 KRE:1; -+ u32 reserved1:5; -+ u32 GO:1; -+ u32 STP:1; -+ u32 Res2:6; -+ u32 NDC:1; -+ u32 ENDI:1; -+ u32 Res3:2; -+ u32 F:3; -+ u32 O:3; -+ u32 BUS:1; -+ u32 DAU:1; -+ u32 ARS:1; -+ u32 SM:1; -+ u32 E_D:1; -+ u32 M:3; -+ } ctrl; -+ -+ u32 IHR; -+ u32 ILR; -+ u32 K1HR; -+ u32 K1LR; -+ u32 K2HR; -+ u32 K2LR; -+ u32 K3HR; -+ u32 K3LR; -+ u32 IVHR; -+ u32 IVLR; -+ u32 OHR; -+ u32 OLR; -+}; -+ -+struct deu_aes { -+ struct deu_aes_ctrl { -+ u32 KRE:1; -+ u32 reserved1:4; -+ u32 PNK:1; -+ u32 GO:1; -+ u32 STP:1; -+ u32 reserved2:6; -+ u32 NDC:1; -+ u32 ENDI:1; -+ u32 reserved3:2; -+ u32 F:3; /* fbs */ -+ u32 O:3; /* om */ -+ u32 BUS:1; /* bsy */ -+ u32 DAU:1; -+ u32 ARS:1; -+ u32 SM:1; -+ u32 E_D:1; -+ u32 KV:1; -+ u32 K:2; /* KL */ -+ } ctrl; -+ -+ u32 ID3R; /* 80h */ -+ u32 ID2R; /* 84h */ -+ u32 ID1R; /* 88h */ -+ u32 ID0R; /* 8Ch */ -+ u32 K7R; /* 90h */ -+ u32 K6R; /* 94h */ -+ u32 K5R; /* 98h */ -+ u32 K4R; /* 9Ch */ -+ u32 K3R; /* A0h */ -+ u32 K2R; /* A4h */ -+ u32 K1R; /* A8h */ -+ u32 K0R; /* ACh */ -+ u32 IV3R; /* B0h */ -+ u32 IV2R; /* B4h */ -+ u32 IV1R; /* B8h */ -+ u32 IV0R; /* BCh */ -+ u32 OD3R; /* D4h */ -+ u32 OD2R; /* D8h */ -+ u32 OD1R; /* DCh */ -+ u32 OD0R; /* E0h */ -+}; -+ -+struct deu_hash { -+ struct deu_hash_ctrl { -+ u32 reserved1:5; -+ u32 KHS:1; -+ u32 GO:1; -+ u32 INIT:1; -+ u32 reserved2:6; -+ u32 NDC:1; -+ u32 ENDI:1; -+ u32 reserved3:7; -+ u32 DGRY:1; -+ u32 BSY:1; -+ u32 reserved4:1; -+ u32 IRCL:1; -+ u32 SM:1; -+ u32 KYUE:1; -+ u32 HMEN:1; -+ u32 SSEN:1; -+ u32 ALGO:1; -+ } ctrl; -+ -+ u32 MR; /* B4h */ -+ u32 D1R; /* B8h */ -+ u32 D2R; /* BCh */ -+ u32 D3R; /* C0h */ -+ u32 D4R; /* C4h */ -+ u32 D5R; /* C8h */ -+ u32 dummy; /* CCh */ -+ u32 KIDX; /* D0h */ -+ u32 KEY; /* D4h */ -+ u32 DBN; /* D8h */ -+}; -+ -+struct deu_dma { -+ struct deu_dma_ctrl { -+ u32 reserved1:22; -+ u32 BS:2; -+ u32 BSY:1; -+ u32 reserved2:1; -+ u32 ALGO:2; -+ u32 RXCLS:2; -+ u32 reserved3:1; -+ u32 EN:1; -+ } ctrl; -+}; -+ -+#endif /* DEU_DANUBE_H */ ---- /dev/null -+++ b/drivers/crypto/lantiq/deu_dma.c -@@ -0,0 +1,147 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup LQ_API -+ \brief Lantiq DEU driver module -+*/ -+ -+/** -+ \file deu_dma.c -+ \ingroup LQ_DEU -+ \brief DMA DEU driver file -+*/ -+ -+/** -+ \defgroup LQ_DMA_FUNCTIONS LQ_DMA_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief DMA DEU driver functions -+*/ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <linux/delay.h> -+#include <asm/io.h> -+#include "deu.h" -+#include "deu_dma.h" -+ -+/* extern struct deu_drv_priv deu_dma_priv; */ -+ -+/** \fn int deu_dma_intr_handler(struct dma_device_info *dma_dev, int status) -+ * \ingroup LQ_DMA_FUNCTIONS -+ * \brief callback function for DEU DMA interrupt -+ * \param dma_dev dma device -+ * \param status not used -+*/ -+int deu_dma_intr_handler(struct dma_device_info *dma_dev, int status) -+{ -+#if 0 -+ int len = 0; -+ while (len <= 20000) { len++; } -+ u8 *buf; -+ int len = 0; -+ -+ struct deu_drv_priv *deu_priv = (struct deu_drv_priv *)dma_dev->priv; -+ /* printk("status:%d \n",status); */ -+ switch(status) { -+ case RCV_INT: -+ len = dma_device_read(dma_dev, (u8 **)&buf, NULL); -+ if ( len != deu_priv->deu_rx_len) { -+ printk(KERN_ERR "%s packet length %d is not " -+ "equal to expect %d\n", -+ __func__, len, deu_priv->deu_rx_len); -+ return -1; -+ } -+ memcpy(deu_priv->deu_rx_buf, buf, deu_priv->deu_rx_len); -+ /* Reset for next usage */ -+ deu_priv->deu_rx_buf = NULL; -+ deu_priv->deu_rx_len = 0; -+ DEU_WAKEUP_EVENT(deu_priv->deu_thread_wait, DEU_EVENT, -+ deu_priv->deu_event_flags); -+ break; -+ case TX_BUF_FULL_INT: -+ /* delay for buffer to be cleared */ -+ while (len <= 20000) { len++; } -+ break; -+ -+ case TRANSMIT_CPT_INT: -+ break; -+ default: -+ break; -+ } -+#endif -+ return 0; -+} -+ -+extern u8 *g_dma_block; -+extern u8 *g_dma_block2; -+ -+/** \fn u8 *deu_dma_buffer_alloc(int len, int *byte_offset, void **opt) -+ * \ingroup LQ_DMA_FUNCTIONS -+ * \brief callback function for allocating buffers for dma receive descriptors -+ * \param len not used -+ * \param byte_offset dma byte offset -+ * \param *opt not used -+ * -+*/ -+u8 *deu_dma_buffer_alloc(int len, int *byte_offset, void **opt) -+{ -+ u8 *swap = NULL; -+ -+ /* dma-core needs at least 2 blocks of memory */ -+ swap = g_dma_block; -+ g_dma_block = g_dma_block2; -+ g_dma_block2 = swap; -+ -+ /* dma_cache_wback_inv((unsigned long) g_dma_block,(PAGE_SIZE >> 1)); */ -+ *byte_offset = 0; -+ -+ return g_dma_block; -+} -+ -+/** \fn int deu_dma_buffer_free(u8 * dataptr, void *opt) -+ * \ingroup LQ_DMA_FUNCTIONS -+ * \brief callback function for freeing dma transmit descriptors -+ * \param dataptr data pointer to be freed -+ * \param opt not used -+*/ -+int deu_dma_buffer_free(u8 *dataptr, void *opt) -+{ -+#if 0 -+ printk("Trying to free memory buffer\n"); -+ if (dataptr == NULL && opt == NULL) -+ return 0; -+ else if (opt == NULL) { -+ kfree(dataptr); -+ return 1; -+ } -+ else if (dataptr == NULL) { -+ kfree(opt); -+ return 1; -+ } -+ else { -+ kfree(opt); -+ kfree(dataptr); -+ } -+#endif -+ return 0; -+} ---- /dev/null -+++ b/drivers/crypto/lantiq/deu_dma.h -@@ -0,0 +1,78 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+/** -+ \addtogroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief Lantiq DEU driver module -+*/ -+ -+/** -+ \file deu_dma.h -+ \ingroup LQ_DEU -+ \brief DMA DEU driver header file -+*/ -+ -+#ifndef DEU_DMA_H -+#define DEU_DMA_H -+ -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/mm.h> -+#include <linux/crypto.h> -+#include <asm/scatterlist.h> -+#include <asm/byteorder.h> -+#include <linux/skbuff.h> -+#include <linux/netdevice.h> -+ -+#include <asm/ifx/irq.h> -+#include <asm/ifx/ifx_dma_core.h> -+#ifndef CONFIG_CRYPTO_DEV_POLL_DMA -+# define CONFIG_CRYPTO_DEV_POLL_DMA -+#endif -+ -+/* must match the size of memory block allocated for -+ * g_dma_block and g_dma_block2 */ -+#define DEU_MAX_PACKET_SIZE (PAGE_SIZE >> 1) -+ -+struct lq_deu_device { -+ struct dma_device_info *dma_device; -+ u8 *dst; -+ u8 *src; -+ int len; -+ int dst_count; -+ int src_count; -+ int recv_count; -+ int packet_size; -+ int packet_num; -+ wait_queue_t wait; -+}; -+ -+extern struct lq_deu_device lq_deu[1]; -+ -+extern int deu_dma_intr_handler(struct dma_device_info *, int); -+extern u8 *deu_dma_buffer_alloc(int, int *, void **); -+extern int deu_dma_buffer_free(u8 *, void *); -+extern void deu_dma_inactivate_poll(struct dma_device_info* dma_dev); -+extern void deu_dma_activate_poll(struct dma_device_info* dma_dev); -+extern struct dma_device_info* deu_dma_reserve(struct dma_device_info** -+ dma_device); -+extern int deu_dma_release(struct dma_device_info** dma_device); -+ -+#endif /* IFMIPS_DEU_DMA_H */ ---- /dev/null -+++ b/drivers/crypto/lantiq/md5.c -@@ -0,0 +1,285 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief Lantiq DEU driver module -+*/ -+ -+/** -+ \file md5.c -+ \ingroup LQ_DEU -+ \brief MD5 encryption DEU driver file -+*/ -+ -+/** -+ \defgroup LQ_MD5_FUNCTIONS LQ_MD5_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief Lantiq DEU MD5 functions -+*/ -+ -+#include <crypto/internal/hash.h> -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/string.h> -+#include <linux/crypto.h> -+#include <linux/types.h> -+#include <asm/byteorder.h> -+#include "deu.h" -+ -+#define MD5_DIGEST_SIZE 16 -+#define MD5_HMAC_BLOCK_SIZE 64 -+#define MD5_BLOCK_WORDS 16 -+#define MD5_HASH_WORDS 4 -+ -+static spinlock_t cipher_lock; -+ -+struct md5_ctx { -+ u32 hash[MD5_HASH_WORDS]; -+ u32 block[MD5_BLOCK_WORDS]; -+ u64 byte_count; -+}; -+ -+/** \fn static u32 md5_endian_swap(u32 input) -+ * \ingroup LQ_MD5_FUNCTIONS -+ * \brief perform dword level endian swap -+ * \param input value of dword that requires to be swapped -+*/ -+static u32 md5_endian_swap(u32 input) -+{ -+ u8 *ptr = (u8 *)&input; -+ -+ return ((ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | ptr[0]); -+} -+ -+/** \fn static void md5_transform(u32 *hash, u32 const *in) -+ * \ingroup LQ_MD5_FUNCTIONS -+ * \brief main interface to md5 hardware -+ * \param hash current hash value -+ * \param in 64-byte block of input -+*/ -+static void md5_transform(u32 *hash, u32 const *in) -+{ -+ int i; -+ volatile struct deu_hash *hashs = (struct deu_hash *) HASH_START; -+ ulong flag; -+ -+ CRTCL_SECT_START; -+ -+ for (i = 0; i < 16; i++) { -+ hashs->MR = md5_endian_swap(in[i]); -+ }; -+ -+ /* wait for processing */ -+ while (hashs->ctrl.BSY) { -+ /* this will not take long */ -+ } -+ -+ CRTCL_SECT_END; -+} -+ -+/** \fn static inline void md5_transform_helper(struct md5_ctx *ctx) -+ * \ingroup LQ_MD5_FUNCTIONS -+ * \brief interfacing function for md5_transform() -+ * \param ctx crypto context -+*/ -+static inline void md5_transform_helper(struct md5_ctx *ctx) -+{ -+ /* le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32)); */ -+ md5_transform(ctx->hash, ctx->block); -+} -+ -+/** \fn static void md5_init(struct crypto_tfm *tfm) -+ * \ingroup LQ_MD5_FUNCTIONS -+ * \brief initialize md5 hardware -+ * \param tfm linux crypto algo transform -+*/ -+static int md5_init(struct shash_desc *desc) -+{ -+ struct md5_ctx *mctx = shash_desc_ctx(desc); -+ volatile struct deu_hash *hash = (struct deu_hash *) HASH_START; -+ -+ hash->ctrl.SM = 1; -+ hash->ctrl.ALGO = 1; /* 1 = md5 0 = sha1 */ -+ hash->ctrl.INIT = 1; /* Initialize the hash operation by writing -+ a '1' to the INIT bit. */ -+ -+ mctx->byte_count = 0; -+ -+ return 0; -+} -+ -+/** \fn static void md5_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len) -+ * \ingroup LQ_MD5_FUNCTIONS -+ * \brief on-the-fly md5 computation -+ * \param tfm linux crypto algo transform -+ * \param data input data -+ * \param len size of input data -+*/ -+static int md5_update(struct shash_desc *desc, const u8 *data, unsigned int len) -+{ -+ struct md5_ctx *mctx = shash_desc_ctx(desc); -+ const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); -+ -+ mctx->byte_count += len; -+ -+ if (avail > len) { -+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), -+ data, len); -+ return 0; -+ } -+ -+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), -+ data, avail); -+ -+ md5_transform_helper(mctx); -+ data += avail; -+ len -= avail; -+ -+ while (len >= sizeof(mctx->block)) { -+ memcpy(mctx->block, data, sizeof(mctx->block)); -+ md5_transform_helper(mctx); -+ data += sizeof(mctx->block); -+ len -= sizeof(mctx->block); -+ } -+ -+ memcpy(mctx->block, data, len); -+ -+ return 0; -+} -+ -+/** \fn static void md5_final(struct crypto_tfm *tfm, u8 *out) -+ * \ingroup LQ_MD5_FUNCTIONS -+ * \brief compute final md5 value -+ * \param tfm linux crypto algo transform -+ * \param out final md5 output value -+*/ -+static int md5_final(struct shash_desc *desc, u8 *out) -+{ -+ struct md5_ctx *mctx = shash_desc_ctx(desc); -+ const unsigned int offset = mctx->byte_count & 0x3f; -+ char *p = (char *)mctx->block + offset; -+ int padding = 56 - (offset + 1); -+ volatile struct deu_hash *hashs = (struct deu_hash *) HASH_START; -+ unsigned long flag; -+ -+ *p++ = 0x80; -+ if (padding < 0) { -+ memset(p, 0x00, padding + sizeof (u64)); -+ md5_transform_helper(mctx); -+ p = (char *)mctx->block; -+ padding = 56; -+ } -+ -+ memset(p, 0, padding); -+ mctx->block[14] = md5_endian_swap(mctx->byte_count << 3); -+ mctx->block[15] = md5_endian_swap(mctx->byte_count >> 29); -+ -+#if 0 -+ le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - -+ sizeof(u64)) / sizeof(u32)); -+#endif -+ -+ md5_transform(mctx->hash, mctx->block); -+ -+ CRTCL_SECT_START; -+ -+ *((u32 *) out + 0) = md5_endian_swap(hashs->D1R); -+ *((u32 *) out + 1) = md5_endian_swap(hashs->D2R); -+ *((u32 *) out + 2) = md5_endian_swap(hashs->D3R); -+ *((u32 *) out + 3) = md5_endian_swap(hashs->D4R); -+ -+ CRTCL_SECT_END; -+ -+ /* Wipe context */ -+ memset(mctx, 0, sizeof(*mctx)); -+ -+ return 0; -+} -+ -+static int md5_export(struct shash_desc *desc, void *out) -+{ -+ struct md5_ctx *sctx = shash_desc_ctx(desc); -+ -+ memcpy(out, sctx, sizeof(*sctx)); -+ return 0; -+} -+ -+static int md5_import(struct shash_desc *desc, const void *in) -+{ -+ struct md5_ctx *sctx = shash_desc_ctx(desc); -+ -+ memcpy(sctx, in, sizeof(*sctx)); -+ return 0; -+} -+ -+/* -+ * \brief MD5 function mappings -+*/ -+static struct shash_alg md5_alg = { -+ .digestsize = MD5_DIGEST_SIZE, -+ .init = md5_init, -+ .update = md5_update, -+ .final = md5_final, -+ .export = md5_export, -+ .import = md5_import, -+ .descsize = sizeof(struct md5_ctx), -+ .statesize = sizeof(struct md5_ctx), -+ .base = { -+ .cra_name = "md5", -+ .cra_driver_name = "lq_deu-md5", -+ .cra_flags = CRYPTO_ALG_TYPE_SHASH, -+ .cra_blocksize = MD5_HMAC_BLOCK_SIZE, -+ .cra_module = THIS_MODULE, -+ } -+}; -+ -+/** \fn int lq_deu_init_md5(void) -+ * \ingroup LQ_MD5_FUNCTIONS -+ * \brief initialize md5 driver -+*/ -+int lq_deu_init_md5(void) -+{ -+ int ret; -+ -+ if ((ret = crypto_register_shash(&md5_alg))) -+ goto md5_err; -+ -+ CRTCL_SECT_INIT; -+ -+ printk(KERN_NOTICE "Lantiq DEU MD5 initialized%s.\n", -+ disable_deudma ? "" : " (DMA)"); -+ return ret; -+ -+md5_err: -+ printk(KERN_ERR "Lantiq DEU MD5 initialization failed!\n"); -+ return ret; -+} -+ -+/** \fn void lq_deu_fini_md5(void) -+ * \ingroup LQ_MD5_FUNCTIONS -+ * \brief unregister md5 driver -+*/ -+ -+void lq_deu_fini_md5(void) -+{ -+ crypto_unregister_shash(&md5_alg); -+} -+ ---- /dev/null -+++ b/drivers/crypto/lantiq/md5_hmac.c -@@ -0,0 +1,329 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief Lantiq DEU driver module -+*/ -+ -+/** -+ \file md5_hmac.c -+ \ingroup LQ_DEU -+ \brief MD5-HMAC encryption DEU driver file -+*/ -+ -+/** -+ \defgroup LQ_MD5_HMAC_FUNCTIONS LQ_MD5_HMAC_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief Lantiq md5-hmac driver functions -+*/ -+ -+#include <crypto/internal/hash.h> -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/string.h> -+#include <linux/crypto.h> -+#include <linux/types.h> -+#include <asm/byteorder.h> -+#include "deu.h" -+ -+#define MD5_DIGEST_SIZE 16 -+#define MD5_HMAC_BLOCK_SIZE 64 -+#define MD5_BLOCK_WORDS 16 -+#define MD5_HASH_WORDS 4 -+#define MD5_HMAC_DBN_TEMP_SIZE 1024 /* size in dword, -+ needed for dbn workaround */ -+ -+static spinlock_t cipher_lock; -+ -+struct md5_hmac_ctx { -+ u32 hash[MD5_HASH_WORDS]; -+ u32 block[MD5_BLOCK_WORDS]; -+ u64 byte_count; -+ u32 dbn; -+ u32 temp[MD5_HMAC_DBN_TEMP_SIZE]; -+}; -+ -+/** \fn static u32 md5_endian_swap(u32 input) -+ * \ingroup LQ_MD5_HMAC_FUNCTIONS -+ * \brief perform dword level endian swap -+ * \param input value of dword that requires to be swapped -+*/ -+static u32 md5_endian_swap(u32 input) -+{ -+ u8 *ptr = (u8 *)&input; -+ -+ return ((ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | ptr[0]); -+} -+ -+/** \fn static void md5_hmac_transform(struct crypto_tfm *tfm, u32 const *in) -+ * \ingroup LQ_MD5_HMAC_FUNCTIONS -+ * \brief save input block to context -+ * \param tfm linux crypto algo transform -+ * \param in 64-byte block of input -+*/ -+static void md5_hmac_transform(struct shash_desc *desc, u32 const *in) -+{ -+ struct md5_hmac_ctx *mctx = shash_desc_ctx(desc); -+ -+ memcpy(&mctx->temp[mctx->dbn<<4], in, 64); /* dbn workaround */ -+ mctx->dbn += 1; -+ -+ if ( (mctx->dbn<<4) > MD5_HMAC_DBN_TEMP_SIZE ) -+ { -+ printk("MD5_HMAC_DBN_TEMP_SIZE exceeded\n"); -+ } -+} -+ -+/** \fn int md5_hmac_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) -+ * \ingroup LQ_MD5_HMAC_FUNCTIONS -+ * \brief sets md5 hmac key -+ * \param tfm linux crypto algo transform -+ * \param key input key -+ * \param keylen key length greater than 64 bytes IS NOT SUPPORTED -+*/ -+static int md5_hmac_setkey(struct crypto_shash *tfm, -+ const u8 *key, -+ unsigned int keylen) -+{ -+ volatile struct deu_hash *hash = (struct deu_hash *) HASH_START; -+ int i, j; -+ u32 *in_key = (u32 *)key; -+ -+ hash->KIDX = 0x80000000; /* reset all 16 words of the key to '0' */ -+ asm("sync"); -+ -+ j = 0; -+ for (i = 0; i < keylen; i+=4) -+ { -+ hash->KIDX = j; -+ asm("sync"); -+ hash->KEY = *((u32 *) in_key + j); -+ j++; -+ } -+ -+ return 0; -+} -+ -+/** \fn void md5_hmac_init(struct crypto_tfm *tfm) -+ * \ingroup LQ_MD5_HMAC_FUNCTIONS -+ * \brief initialize md5 hmac context -+ * \param tfm linux crypto algo transform -+*/ -+static int md5_hmac_init(struct shash_desc *desc) -+{ -+ struct md5_hmac_ctx *mctx = shash_desc_ctx(desc); -+ -+ memset(mctx, 0, sizeof(struct md5_hmac_ctx)); -+ mctx->dbn = 0; /* dbn workaround */ -+ return 0; -+} -+ -+/** \fn void md5_hmac_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len) -+ * \ingroup LQ_MD5_HMAC_FUNCTIONS -+ * \brief on-the-fly md5 hmac computation -+ * \param tfm linux crypto algo transform -+ * \param data input data -+ * \param len size of input data -+*/ -+static int md5_hmac_update(struct shash_desc *desc, -+ const u8 *data, -+ unsigned int len) -+{ -+ struct md5_hmac_ctx *mctx = shash_desc_ctx(desc); -+ const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); -+ -+ mctx->byte_count += len; -+ -+ if (avail > len) { -+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), -+ data, len); -+ return 0; -+ } -+ -+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), -+ data, avail); -+ -+ md5_hmac_transform(desc, mctx->block); -+ data += avail; -+ len -= avail; -+ -+ while (len >= sizeof(mctx->block)) { -+ memcpy(mctx->block, data, sizeof(mctx->block)); -+ md5_hmac_transform(desc, mctx->block); -+ data += sizeof(mctx->block); -+ len -= sizeof(mctx->block); -+ } -+ -+ memcpy(mctx->block, data, len); -+ -+ return 0; -+} -+ -+/** \fn void md5_hmac_final(struct crypto_tfm *tfm, u8 *out) -+ * \ingroup LQ_MD5_HMAC_FUNCTIONS -+ * \brief compute final md5 hmac value -+ * \param tfm linux crypto algo transform -+ * \param out final md5 hmac output value -+*/ -+static int md5_hmac_final(struct shash_desc *desc, u8 *out) -+{ -+ struct md5_hmac_ctx *mctx = shash_desc_ctx(desc); -+ const unsigned int offset = mctx->byte_count & 0x3f; -+ char *p = (char *)mctx->block + offset; -+ int padding = 56 - (offset + 1); -+ volatile struct deu_hash *hashs = (struct deu_hash *) HASH_START; -+ u32 flag; -+ int i = 0; -+ int dbn; -+ u32 *in = &mctx->temp[0]; -+ -+ *p++ = 0x80; -+ if (padding < 0) { -+ memset(p, 0x00, padding + sizeof (u64)); -+ md5_hmac_transform(desc, mctx->block); -+ p = (char *)mctx->block; -+ padding = 56; -+ } -+ -+ memset(p, 0, padding); -+ /* need to add 512 bit of the IPAD operation */ -+ mctx->block[14] = md5_endian_swap((mctx->byte_count + 64) << 3); -+ mctx->block[15] = 0x00000000; -+ -+ md5_hmac_transform(desc, mctx->block); -+ -+ CRTCL_SECT_START; -+ -+ printk("dbn = %d\n", mctx->dbn); -+ hashs->DBN = mctx->dbn; -+ -+ /* khs, go, init, ndc, endi, kyue, hmen, md5 */ -+ *LQ_HASH_CON = 0x0703002D; -+ -+ /* wait for processing */ -+ while (hashs->ctrl.BSY) { -+ /* this will not take long */ -+ } -+ -+ for (dbn = 0; dbn < mctx->dbn; dbn++) -+ { -+ for (i = 0; i < 16; i++) { -+ hashs->MR = in[i]; -+ }; -+ -+ hashs->ctrl.GO = 1; -+ asm("sync"); -+ -+ /* wait for processing */ -+ while (hashs->ctrl.BSY) { -+ /* this will not take long */ -+ } -+ -+ in += 16; -+ } -+ -+#if 1 -+ /* wait for digest ready */ -+ while (! hashs->ctrl.DGRY) { -+ /* this will not take long */ -+ } -+#endif -+ -+ *((u32 *) out + 0) = hashs->D1R; -+ *((u32 *) out + 1) = hashs->D2R; -+ *((u32 *) out + 2) = hashs->D3R; -+ *((u32 *) out + 3) = hashs->D4R; -+ *((u32 *) out + 4) = hashs->D5R; -+ -+ CRTCL_SECT_END; -+ -+ return 0; -+} -+ -+static int md5_hmac_export(struct shash_desc *desc, void *out) -+{ -+ struct md5_hmac_ctx *sctx = shash_desc_ctx(desc); -+ -+ memcpy(out, sctx, sizeof(*sctx)); -+ return 0; -+} -+ -+static int md5_hmac_import(struct shash_desc *desc, const void *in) -+{ -+ struct md5_hmac_ctx *sctx = shash_desc_ctx(desc); -+ -+ memcpy(sctx, in, sizeof(*sctx)); -+ return 0; -+} -+ -+/* -+ * \brief MD5_HMAC function mappings -+*/ -+static struct shash_alg md5_hmac_alg = { -+ .digestsize = MD5_DIGEST_SIZE, -+ .init = md5_hmac_init, -+ .update = md5_hmac_update, -+ .final = md5_hmac_final, -+ .setkey = md5_hmac_setkey, -+ .export = md5_hmac_export, -+ .import = md5_hmac_import, -+ .descsize = sizeof(struct md5_hmac_ctx), -+ .statesize = sizeof(struct md5_hmac_ctx), -+ .base = { -+ .cra_name = "hmac(md5)", -+ .cra_driver_name = "lq_deu-md5_hmac", -+ .cra_flags = CRYPTO_ALG_TYPE_SHASH, -+ .cra_blocksize = MD5_HMAC_BLOCK_SIZE, -+ .cra_module = THIS_MODULE, -+ } -+}; -+ -+/** \fn int lq_deu_init_md5_hmac(void) -+ * \ingroup LQ_MD5_HMAC_FUNCTIONS -+ * \brief initialize md5 hmac driver -+*/ -+int lq_deu_init_md5_hmac(void) -+{ -+ int ret; -+ -+ if ((ret = crypto_register_shash(&md5_hmac_alg))) -+ goto md5_hmac_err; -+ -+ CRTCL_SECT_INIT; -+ -+ printk(KERN_NOTICE "Lantiq DEU MD5_HMAC initialized%s.\n", -+ disable_deudma ? "" : " (DMA)"); -+ return ret; -+ -+md5_hmac_err: -+ printk(KERN_ERR "Lantiq DEU MD5_HMAC initialization failed!\n"); -+ return ret; -+} -+ -+/** \fn void lq_deu_fini_md5_hmac(void) -+ * \ingroup LQ_MD5_HMAC_FUNCTIONS -+ * \brief unregister md5 hmac driver -+*/ -+void lq_deu_fini_md5_hmac(void) -+{ -+ crypto_unregister_shash(&md5_hmac_alg); -+} -+ ---- /dev/null -+++ b/drivers/crypto/lantiq/sha1.c -@@ -0,0 +1,262 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief Lantiq DEU driver module -+*/ -+ -+/** -+ \file sha1.c -+ \ingroup LQ_DEU -+ \brief SHA1 encryption DEU driver file -+*/ -+ -+/** -+ \defgroup LQ_SHA1_FUNCTIONS LQ_SHA1_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief Lantiq DEU sha1 functions -+*/ -+ -+ -+#include <crypto/internal/hash.h> -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/mm.h> -+#include <linux/crypto.h> -+#include <linux/cryptohash.h> -+#include <crypto/sha.h> -+#include <linux/types.h> -+#include <asm/scatterlist.h> -+#include <asm/byteorder.h> -+#include "deu.h" -+ -+#define SHA1_DIGEST_SIZE 20 -+#define SHA1_HMAC_BLOCK_SIZE 64 -+ -+static spinlock_t cipher_lock; -+ -+/* -+ * \brief SHA1 private structure -+*/ -+struct sha1_ctx { -+ u64 count; -+ u32 state[5]; -+ u8 buffer[64]; -+}; -+ -+/** \fn static void sha1_transform(u32 *state, const u32 *in) -+ * \ingroup LQ_SHA1_FUNCTIONS -+ * \brief main interface to sha1 hardware -+ * \param state current state -+ * \param in 64-byte block of input -+*/ -+static void sha1_transform(u32 *state, const u32 *in) -+{ -+ int i = 0; -+ volatile struct deu_hash *hashs = (struct deu_hash *) HASH_START; -+ unsigned long flag; -+ -+ CRTCL_SECT_START; -+ -+ for (i = 0; i < 16; i++) { -+ hashs->MR = in[i]; -+ }; -+ -+ /* wait for processing */ -+ while (hashs->ctrl.BSY) { -+ /* this will not take long */ -+ } -+ -+ CRTCL_SECT_END; -+} -+ -+/** \fn static void sha1_init(struct crypto_tfm *tfm) -+ * \ingroup LQ_SHA1_FUNCTIONS -+ * \brief initialize sha1 hardware -+ * \param tfm linux crypto algo transform -+*/ -+static int sha1_init(struct shash_desc *desc) -+{ -+ struct sha1_ctx *sctx = shash_desc_ctx(desc); -+ -+ SHA_HASH_INIT; -+ -+ sctx->count = 0; -+ -+ return 0; -+} -+ -+/** \fn static void sha1_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len) -+ * \ingroup LQ_SHA1_FUNCTIONS -+ * \brief on-the-fly sha1 computation -+ * \param tfm linux crypto algo transform -+ * \param data input data -+ * \param len size of input data -+*/ -+static int sha1_update(struct shash_desc *desc, const u8 *data, unsigned int len) -+{ -+ struct sha1_ctx *sctx = shash_desc_ctx(desc); -+ unsigned int i, j; -+ -+ j = (sctx->count >> 3) & 0x3f; -+ sctx->count += len << 3; -+ -+ if ((j + len) > 63) { -+ memcpy(&sctx->buffer[j], data, (i = 64 - j)); -+ sha1_transform(sctx->state, (const u32 *)sctx->buffer); -+ for (; i + 63 < len; i += 64) { -+ sha1_transform(sctx->state, (const u32 *)&data[i]); -+ } -+ -+ j = 0; -+ } else { -+ i = 0; -+ } -+ -+ memcpy(&sctx->buffer[j], &data[i], len - i); -+ -+ return 0; -+} -+ -+/** \fn static void sha1_final(struct crypto_tfm *tfm, u8 *out) -+ * \ingroup LQ_SHA1_FUNCTIONS -+ * \brief compute final sha1 value -+ * \param tfm linux crypto algo transform -+ * \param out final md5 output value -+*/ -+static int sha1_final(struct shash_desc *desc, u8 *out) -+{ -+ struct sha1_ctx *sctx = shash_desc_ctx(desc); -+ u32 index, padlen; -+ u64 t; -+ u8 bits[8] = { 0, }; -+ static const u8 padding[64] = { 0x80, }; -+ volatile struct deu_hash *hashs = (struct deu_hash *) HASH_START; -+ ulong flag; -+ -+ t = sctx->count; -+ bits[7] = 0xff & t; -+ t >>= 8; -+ bits[6] = 0xff & t; -+ t >>= 8; -+ bits[5] = 0xff & t; -+ t >>= 8; -+ bits[4] = 0xff & t; -+ t >>= 8; -+ bits[3] = 0xff & t; -+ t >>= 8; -+ bits[2] = 0xff & t; -+ t >>= 8; -+ bits[1] = 0xff & t; -+ t >>= 8; -+ bits[0] = 0xff & t; -+ -+ /* Pad out to 56 mod 64 */ -+ index = (sctx->count >> 3) & 0x3f; -+ padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); -+ sha1_update(desc, padding, padlen); -+ -+ /* Append length */ -+ sha1_update(desc, bits, sizeof bits); -+ -+ CRTCL_SECT_START; -+ -+ *((u32 *) out + 0) = hashs->D1R; -+ *((u32 *) out + 1) = hashs->D2R; -+ *((u32 *) out + 2) = hashs->D3R; -+ *((u32 *) out + 3) = hashs->D4R; -+ *((u32 *) out + 4) = hashs->D5R; -+ -+ CRTCL_SECT_END; -+ -+ /* Wipe context*/ -+ memset(sctx, 0, sizeof *sctx); -+ -+ return 0; -+} -+ -+static int sha1_export(struct shash_desc *desc, void *out) -+{ -+ struct sha1_ctx *sctx = shash_desc_ctx(desc); -+ -+ memcpy(out, sctx, sizeof(*sctx)); -+ return 0; -+} -+ -+static int sha1_import(struct shash_desc *desc, const void *in) -+{ -+ struct sha1_ctx *sctx = shash_desc_ctx(desc); -+ -+ memcpy(sctx, in, sizeof(*sctx)); -+ return 0; -+} -+ -+/* -+ * \brief SHA1 function mappings -+*/ -+static struct shash_alg deu_sha1_alg = { -+ .digestsize = SHA1_DIGEST_SIZE, -+ .init = sha1_init, -+ .update = sha1_update, -+ .final = sha1_final, -+ .export = sha1_export, -+ .import = sha1_import, -+ .descsize = sizeof(struct sha1_ctx), -+ .statesize = sizeof(struct sha1_ctx), -+ .base = { -+ .cra_name = "sha1", -+ .cra_driver_name = "lq_deu-sha1", -+ .cra_flags = CRYPTO_ALG_TYPE_SHASH, -+ .cra_blocksize = SHA1_HMAC_BLOCK_SIZE, -+ .cra_module = THIS_MODULE, -+ } -+}; -+ -+/** \fn int lq_deu_init_sha1(void) -+ * \ingroup LQ_SHA1_FUNCTIONS -+ * \brief initialize sha1 driver -+*/ -+int lq_deu_init_sha1(void) -+{ -+ int ret; -+ -+ if ((ret = crypto_register_shash(&deu_sha1_alg))) -+ goto sha1_err; -+ -+ CRTCL_SECT_INIT; -+ -+ printk(KERN_NOTICE "Lantiq DEU SHA1 initialized%s.\n", -+ disable_deudma ? "" : " (DMA)"); -+ return ret; -+ -+sha1_err: -+ printk(KERN_ERR "Lantiq DEU SHA1 initialization failed!\n"); -+ return ret; -+} -+ -+/** \fn void lq_deu_fini_sha1(void) -+ * \ingroup LQ_SHA1_FUNCTIONS -+ * \brief unregister sha1 driver -+*/ -+void lq_deu_fini_sha1(void) -+{ -+ crypto_unregister_shash(&deu_sha1_alg); -+} ---- /dev/null -+++ b/drivers/crypto/lantiq/sha1_hmac.c -@@ -0,0 +1,325 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief Lantiq DEU driver module -+*/ -+ -+/** -+ \file sha1_hmac.c -+ \ingroup LQ_DEU -+ \brief SHA1-HMAC DEU driver file -+*/ -+ -+/** -+ \defgroup LQ_SHA1_HMAC_FUNCTIONS LQ_SHA1_HMAC_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief Lantiq sha1 hmac functions -+*/ -+ -+ -+#include <crypto/internal/hash.h> -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/mm.h> -+#include <linux/crypto.h> -+#include <linux/cryptohash.h> -+#include <linux/types.h> -+#include <asm/scatterlist.h> -+#include <asm/byteorder.h> -+#include <linux/delay.h> -+#include "deu.h" -+ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_SHA1_HMAC -+ -+#define SHA1_DIGEST_SIZE 20 -+#define SHA1_HMAC_BLOCK_SIZE 64 -+/* size in dword, needed for dbn workaround */ -+#define SHA1_HMAC_DBN_TEMP_SIZE 1024 -+ -+static spinlock_t cipher_lock; -+ -+struct sha1_hmac_ctx { -+ u64 count; -+ u32 state[5]; -+ u8 buffer[64]; -+ u32 dbn; -+ u32 temp[SHA1_HMAC_DBN_TEMP_SIZE]; -+}; -+ -+/** \fn static void sha1_hmac_transform(struct crypto_tfm *tfm, u32 const *in) -+ * \ingroup LQ_SHA1_HMAC_FUNCTIONS -+ * \brief save input block to context -+ * \param tfm linux crypto algo transform -+ * \param in 64-byte block of input -+*/ -+static void sha1_hmac_transform(struct shash_desc *desc, u32 const *in) -+{ -+ struct sha1_hmac_ctx *sctx = shash_desc_ctx(desc); -+ -+ memcpy(&sctx->temp[sctx->dbn<<4], in, 64); /* dbn workaround */ -+ sctx->dbn += 1; -+ -+ if ((sctx->dbn<<4) > SHA1_HMAC_DBN_TEMP_SIZE) { -+ printk("SHA1_HMAC_DBN_TEMP_SIZE exceeded\n"); -+ } -+} -+ -+/** \fn int sha1_hmac_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) -+ * \ingroup LQ_SHA1_HMAC_FUNCTIONS -+ * \brief sets sha1 hmac key -+ * \param tfm linux crypto algo transform -+ * \param key input key -+ * \param keylen key length greater than 64 bytes IS NOT SUPPORTED -+*/ -+static int sha1_hmac_setkey(struct crypto_shash *tfm, -+ const u8 *key, -+ unsigned int keylen) -+{ -+ volatile struct deu_hash *hash = (struct deu_hash *) HASH_START; -+ int i, j; -+ u32 *in_key = (u32 *)key; -+ -+ hash->KIDX = 0x80000000; /* reset all 16 words of the key to '0' */ -+ asm("sync"); -+ -+ j = 0; -+ for (i = 0; i < keylen; i+=4) -+ { -+ hash->KIDX = j; -+ asm("sync"); -+ hash->KEY = *((u32 *) in_key + j); -+ j++; -+ } -+ -+ return 0; -+} -+ -+static int sha1_hmac_export(struct shash_desc *desc, void *out) -+{ -+ struct sha1_hmac_ctx *sctx = shash_desc_ctx(desc); -+ -+ memcpy(out, sctx, sizeof(*sctx)); -+ return 0; -+} -+ -+static int sha1_hmac_import(struct shash_desc *desc, const void *in) -+{ -+ struct sha1_hmac_ctx *sctx = shash_desc_ctx(desc); -+ -+ memcpy(sctx, in, sizeof(*sctx)); -+ return 0; -+} -+ -+/** \fn void sha1_hmac_init(struct crypto_tfm *tfm) -+ * \ingroup LQ_SHA1_HMAC_FUNCTIONS -+ * \brief initialize sha1 hmac context -+ * \param tfm linux crypto algo transform -+*/ -+static int sha1_hmac_init(struct shash_desc *desc) -+{ -+ struct sha1_hmac_ctx *sctx = shash_desc_ctx(desc); -+ -+ memset(sctx, 0, sizeof(struct sha1_hmac_ctx)); -+ sctx->dbn = 0; /* dbn workaround */ -+ -+ return 0; -+} -+ -+/** \fn static void sha1_hmac_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len) -+ * \ingroup LQ_SHA1_HMAC_FUNCTIONS -+ * \brief on-the-fly sha1 hmac computation -+ * \param tfm linux crypto algo transform -+ * \param data input data -+ * \param len size of input data -+*/ -+static int sha1_hmac_update(struct shash_desc *desc, const u8 *data, -+ unsigned int len) -+{ -+ struct sha1_hmac_ctx *sctx = shash_desc_ctx(desc); -+ unsigned int i, j; -+ -+ j = (sctx->count >> 3) & 0x3f; -+ sctx->count += len << 3; -+ /* printk("sctx->count = %d\n", (sctx->count >> 3)); */ -+ -+ if ((j + len) > 63) { -+ memcpy(&sctx->buffer[j], data, (i = 64 - j)); -+ sha1_hmac_transform(desc, (const u32 *)sctx->buffer); -+ for (; i + 63 < len; i += 64) { -+ sha1_hmac_transform(desc, (const u32 *)&data[i]); -+ } -+ -+ j = 0; -+ } else { -+ i = 0; -+ } -+ -+ memcpy(&sctx->buffer[j], &data[i], len - i); -+ -+ return 0; -+} -+ -+/** \fn static void sha1_hmac_final(struct crypto_tfm *tfm, u8 *out) -+ * \ingroup LQ_SHA1_HMAC_FUNCTIONS -+ * \brief ompute final sha1 hmac value -+ * \param tfm linux crypto algo transform -+ * \param out final sha1 hmac output value -+*/ -+static int sha1_hmac_final(struct shash_desc *desc, u8 *out) -+{ -+ struct sha1_hmac_ctx *sctx = shash_desc_ctx(desc); -+ u32 index, padlen; -+ u64 t; -+ u8 bits[8] = { 0, }; -+ static const u8 padding[64] = { 0x80, }; -+ volatile struct deu_hash *hashs = (struct deu_hash *) HASH_START; -+ ulong flag; -+ int i = 0; -+ int dbn; -+ u32 *in = &sctx->temp[0]; -+ -+ t = sctx->count + 512; /* need to add 512 bit of the IPAD operation */ -+ bits[7] = 0xff & t; -+ t >>= 8; -+ bits[6] = 0xff & t; -+ t >>= 8; -+ bits[5] = 0xff & t; -+ t >>= 8; -+ bits[4] = 0xff & t; -+ t >>= 8; -+ bits[3] = 0xff & t; -+ t >>= 8; -+ bits[2] = 0xff & t; -+ t >>= 8; -+ bits[1] = 0xff & t; -+ t >>= 8; -+ bits[0] = 0xff & t; -+ -+ /* Pad out to 56 mod 64 */ -+ index = (sctx->count >> 3) & 0x3f; -+ padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); -+ sha1_hmac_update(desc, padding, padlen); -+ -+ /* Append length */ -+ sha1_hmac_update(desc, bits, sizeof bits); -+ -+ CRTCL_SECT_START; -+ -+ hashs->DBN = sctx->dbn; -+ -+ /* for vr9 change, ENDI = 1 */ -+ *LQ_HASH_CON = HASH_CON_VALUE; -+ -+ /* wait for processing */ -+ while (hashs->ctrl.BSY) { -+ /* this will not take long */ -+ } -+ -+ for (dbn = 0; dbn < sctx->dbn; dbn++) -+ { -+ for (i = 0; i < 16; i++) { -+ hashs->MR = in[i]; -+ }; -+ -+ hashs->ctrl.GO = 1; -+ asm("sync"); -+ -+ /* wait for processing */ -+ while (hashs->ctrl.BSY) { -+ /* this will not take long */ -+ } -+ -+ in += 16; -+ -+ return 0; -+ } -+ -+#if 1 -+ /* wait for digest ready */ -+ while (! hashs->ctrl.DGRY) { -+ /* this will not take long */ -+ } -+#endif -+ -+ *((u32 *) out + 0) = hashs->D1R; -+ *((u32 *) out + 1) = hashs->D2R; -+ *((u32 *) out + 2) = hashs->D3R; -+ *((u32 *) out + 3) = hashs->D4R; -+ *((u32 *) out + 4) = hashs->D5R; -+ -+ CRTCL_SECT_END; -+} -+ -+/* -+ * \brief SHA1-HMAC function mappings -+*/ -+static struct shash_alg sha1_hmac_alg = { -+ .digestsize = SHA1_DIGEST_SIZE, -+ .init = sha1_hmac_init, -+ .update = sha1_hmac_update, -+ .final = sha1_hmac_final, -+ .export = sha1_hmac_export, -+ .import = sha1_hmac_import, -+ .setkey = sha1_hmac_setkey, -+ .descsize = sizeof(struct sha1_hmac_ctx), -+ .statesize = sizeof(struct sha1_hmac_ctx), -+ .base = { -+ .cra_name = "hmac(sha1)", -+ .cra_driver_name = "lq_deu-sha1_hmac", -+ .cra_flags = CRYPTO_ALG_TYPE_SHASH, -+ .cra_blocksize = SHA1_HMAC_BLOCK_SIZE, -+ .cra_module = THIS_MODULE, -+ } -+}; -+ -+/** \fn int lq_deu_init_sha1_hmac(void) -+ * \ingroup LQ_SHA1_HMAC_FUNCTIONS -+ * \brief initialize sha1 hmac driver -+*/ -+int lq_deu_init_sha1_hmac(void) -+{ -+ int ret; -+ -+ if ((ret = crypto_register_shash(&sha1_hmac_alg))) -+ goto sha1_err; -+ -+ CRTCL_SECT_INIT; -+ -+ printk(KERN_NOTICE "Lantiq DEU SHA1_HMAC initialized%s.\n", -+ disable_deudma ? "" : " (DMA)"); -+ return ret; -+ -+sha1_err: -+ printk(KERN_ERR "Lantiq DEU SHA1_HMAC initialization failed!\n"); -+ return ret; -+} -+ -+/** \fn void lq_deu_fini_sha1_hmac(void) -+ * \ingroup LQ_SHA1_HMAC_FUNCTIONS -+ * \brief unregister sha1 hmac driver -+*/ -+void lq_deu_fini_sha1_hmac(void) -+{ -+ crypto_unregister_shash(&sha1_hmac_alg); -+} -+ -+#endif ---- /dev/null -+++ b/drivers/crypto/lantiq/deu_falcon.c -@@ -0,0 +1,163 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus -+ */ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <asm/io.h> /* dma_cache_inv */ -+#include <linux/platform_device.h> -+ -+#ifdef CONFIG_SOC_LANTIQ_FALCON -+ -+#include "deu.h" -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief Lantiq DEU driver module -+*/ -+ -+/** -+ \file deu_falcon.c -+ \brief Lantiq DEU board specific driver file for ar9 -+*/ -+ -+/** -+ \defgroup BOARD_SPECIFIC_FUNCTIONS LQ_BOARD_SPECIFIC_FUNCTIONS -+ \ingroup LQ_DEU -+ \brief board specific functions -+*/ -+ -+#include <falcon/gpon_reg_base.h> -+#include <falcon/sys1_reg.h> -+#include <falcon/status_reg.h> -+#include <falcon/sysctrl.h> -+ -+#define reg_r32(reg) __raw_readl(reg) -+#define reg_w32(val, reg) __raw_writel(val, reg) -+#define reg_w32_mask(clear, set, reg) reg_w32((reg_r32(reg) & ~(clear)) | (set), reg) -+ -+static gpon_sys1_t * const sys1 = (gpon_sys1_t *)GPON_SYS1_BASE; -+static gpon_status_t * const status = (gpon_status_t *)GPON_STATUS_BASE; -+ -+/** \fn u32 endian_swap(u32 input) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief Swap data given to the function -+ * \param input Data input to be swapped -+ * \return either the swapped data or the input data depending on whether it is in DMA mode or FPI mode -+*/ -+static u32 endian_swap(u32 input) -+{ -+ return input; -+} -+ -+/** \fn u32 input_swap(u32 input) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief Not used -+ * \return input -+*/ -+static u32 input_swap(u32 input) -+{ -+ return input; -+} -+ -+/** \fn void aes_chip_init(void) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief initialize AES hardware -+*/ -+static void aes_chip_init(void) -+{ -+ volatile struct deu_aes *aes = (struct deu_aes *) AES_START; -+ -+ aes->ctrl.SM = 1; -+ aes->ctrl.ARS = 1; -+} -+ -+/** \fn void des_chip_init(void) -+ * \ingroup BOARD_SPECIFIC_FUNCTIONS -+ * \brief initialize DES hardware -+*/ -+static void des_chip_init(void) -+{ -+} -+ -+static u32 chip_init(void) -+{ -+ sys1_hw_clk_enable(CLKEN_SHA1_SET | CLKEN_AES_SET); -+ sys1_hw_activate(ACT_SHA1_SET | ACT_AES_SET); -+ -+ return LQ_DEU_ID_AES | LQ_DEU_ID_HASH; -+} -+ -+static int lq_crypto_probe(struct platform_device *pdev) -+{ -+#ifdef CONFIG_CRYPTO_DEV_LANTIQ_DMA -+ lq_crypto_ops.dma_init = NULL; -+ lq_crypto_ops.dma_exit = NULL; -+ lq_crypto_ops.aes_dma_memcpy = NULL; -+ lq_crypto_ops.des_dma_memcpy = NULL; -+ lq_crypto_ops.aes_dma_malloc = NULL; -+ lq_crypto_ops.des_dma_malloc = NULL; -+ lq_crypto_ops.dma_align = NULL; -+ lq_crypto_ops.dma_free = NULL; -+#endif -+ -+ lq_crypto_ops.endian_swap = endian_swap; -+ lq_crypto_ops.input_swap = input_swap; -+ lq_crypto_ops.aes_chip_init = aes_chip_init; -+ lq_crypto_ops.des_chip_init = des_chip_init; -+ lq_crypto_ops.chip_init = chip_init; -+ -+ printk("lq_falcon_deu: driver loaded!\n"); -+ -+ lq_deu_init(); -+ -+ return 0; -+} -+ -+static int lq_crypto_remove(struct platform_device *pdev) -+{ -+ lq_deu_exit(); -+ -+ return 0; -+} -+ -+static struct platform_driver lq_crypto = { -+ .probe = lq_crypto_probe, -+ .remove = lq_crypto_remove, -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "lq_falcon_deu" -+ } -+}; -+ -+static int __init lq_crypto_init(void) -+{ -+ return platform_driver_register(&lq_crypto); -+} -+module_init(lq_crypto_init); -+ -+static void __exit lq_crypto_exit(void) -+{ -+ platform_driver_unregister(&lq_crypto); -+} -+module_exit(lq_crypto_exit); -+ -+#endif ---- /dev/null -+++ b/drivers/crypto/lantiq/deu_falcon.h -@@ -0,0 +1,281 @@ -+/* -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com> -+ * Copyright (C) 2009 Mohammad Firdaus / Infineon Technologies -+ */ -+ -+/** -+ \defgroup LQ_DEU LQ_DEU_DRIVERS -+ \ingroup API -+ \brief DEU driver module -+*/ -+ -+/** -+ \defgroup LQ_DEU_DEFINITIONS LQ_DEU_DEFINITIONS -+ \ingroup LQ_DEU -+ \brief Lantiq DEU definitions -+*/ -+ -+/** -+ \file deu_falcon.h -+ \brief DEU driver header file -+*/ -+ -+ -+#ifndef DEU_FALCON_H -+#define DEU_FALCON_H -+ -+#define HASH_START 0xbd008100 -+#define AES_START 0xbd008000 -+ -+#ifdef CONFIG_CRYPTO_DEV_DMA -+# include "deu_dma.h" -+# define DEU_DWORD_REORDERING(ptr, buffer, in_out, bytes) \ -+ deu_dma_align(ptr, buffer, in_out, bytes) -+# define AES_MEMORY_COPY(outcopy, out_dma, out_arg, nbytes) \ -+ deu_aes_dma_memcpy(outcopy, out_dma, out_arg, nbytes) -+# define DES_MEMORY_COPY(outcopy, out_dma, out_arg, nbytes) \ -+ deu_des_dma_memcpy(outcopy, out_dma, out_arg, nbytes) -+# define BUFFER_IN 1 -+# define BUFFER_OUT 0 -+# define AES_ALGO 1 -+# define DES_ALGO 0 -+# define ALLOCATE_MEMORY(val, type) 1 -+# define FREE_MEMORY(buff) -+extern struct lq_deu_device lq_deu[1]; -+#endif /* CONFIG_CRYPTO_DEV_DMA */ -+ -+/* SHA CONSTANTS */ -+#define HASH_CON_VALUE 0x0700002C -+ -+#define INPUT_ENDIAN_SWAP(input) deu_input_swap(input) -+#define DEU_ENDIAN_SWAP(input) deu_endian_swap(input) -+#define DELAY_PERIOD 10 -+#define FIND_DEU_CHIP_VERSION chip_version() -+ -+#define WAIT_AES_DMA_READY() \ -+ do { \ -+ int i; \ -+ volatile struct deu_dma *dma = \ -+ (struct deu_dma *) LQ_DEU_DMA_CON; \ -+ volatile struct deu_aes *aes = \ -+ (volatile struct deu_aes *) AES_START; \ -+ for (i = 0; i < 10; i++) \ -+ udelay(DELAY_PERIOD); \ -+ while (dma->ctrl.BSY) {}; \ -+ while (aes->ctrl.BUS) {}; \ -+ } while (0) -+ -+#define WAIT_DES_DMA_READY() \ -+ do { \ -+ int i; \ -+ volatile struct deu_dma *dma = \ -+ (struct deu_dma *) LQ_DEU_DMA_CON; \ -+ volatile struct deu_des *des = \ -+ (struct deu_des *) DES_3DES_START; \ -+ for (i = 0; i < 10; i++) \ -+ udelay(DELAY_PERIOD); \ -+ while (dma->ctrl.BSY) {}; \ -+ while (des->ctrl.BUS) {}; \ -+ } while (0) -+ -+#define AES_DMA_MISC_CONFIG() \ -+ do { \ -+ volatile struct deu_aes *aes = \ -+ (volatile struct deu_aes *) AES_START; \ -+ aes->ctrl.KRE = 1; \ -+ aes->ctrl.GO = 1; \ -+ } while(0) -+ -+#define SHA_HASH_INIT \ -+ do { \ -+ volatile struct deu_hash *hash = \ -+ (struct deu_hash *) HASH_START; \ -+ hash->ctrl.SM = 1; \ -+ hash->ctrl.ALGO = 0; \ -+ hash->ctrl.INIT = 1; \ -+ } while(0) -+ -+/* DEU Common Structures for Falcon*/ -+ -+struct deu_clk_ctrl { -+ u32 Res:26; -+ u32 FSOE:1; -+ u32 SBWE:1; -+ u32 EDIS:1; -+ u32 SPEN:1; -+ u32 DISS:1; -+ u32 DISR:1; -+}; -+ -+struct deu_des { -+ struct deu_des_ctrl { /* 10h */ -+ u32 KRE:1; -+ u32 reserved1:5; -+ u32 GO:1; -+ u32 STP:1; -+ u32 Res2:6; -+ u32 NDC:1; -+ u32 ENDI:1; -+ u32 Res3:2; -+ u32 F:3; -+ u32 O:3; -+ u32 BUS:1; -+ u32 DAU:1; -+ u32 ARS:1; -+ u32 SM:1; -+ u32 E_D:1; -+ u32 M:3; -+ } ctrl; -+ -+ u32 IHR; /* 14h */ -+ u32 ILR; /* 18h */ -+ u32 K1HR; /* 1c */ -+ u32 K1LR; -+ u32 K2HR; -+ u32 K2LR; -+ u32 K3HR; -+ u32 K3LR; /* 30h */ -+ u32 IVHR; /* 34h */ -+ u32 IVLR; /* 38 */ -+ u32 OHR; /* 3c */ -+ u32 OLR; /* 40 */ -+}; -+ -+struct deu_aes { -+ struct deu_aes_ctrl { -+ u32 KRE:1; -+ u32 reserved1:4; -+ u32 PNK:1; -+ u32 GO:1; -+ u32 STP:1; -+ u32 reserved2:6; -+ u32 NDC:1; -+ u32 ENDI:1; -+ u32 reserved3:2; -+ u32 F:3; /* fbs */ -+ u32 O:3; /* om */ -+ u32 BUS:1; /* bsy */ -+ u32 DAU:1; -+ u32 ARS:1; -+ u32 SM:1; -+ u32 E_D:1; -+ u32 KV:1; -+ u32 K:2; /* KL */ -+ } ctrl; -+ -+ u32 ID3R; /* 80h */ -+ u32 ID2R; /* 84h */ -+ u32 ID1R; /* 88h */ -+ u32 ID0R; /* 8Ch */ -+ u32 K7R; /* 90h */ -+ u32 K6R; /* 94h */ -+ u32 K5R; /* 98h */ -+ u32 K4R; /* 9Ch */ -+ u32 K3R; /* A0h */ -+ u32 K2R; /* A4h */ -+ u32 K1R; /* A8h */ -+ u32 K0R; /* ACh */ -+ u32 IV3R; /* B0h */ -+ u32 IV2R; /* B4h */ -+ u32 IV1R; /* B8h */ -+ u32 IV0R; /* BCh */ -+ u32 OD3R; /* D4h */ -+ u32 OD2R; /* D8h */ -+ u32 OD1R; /* DCh */ -+ u32 OD0R; /* E0h */ -+}; -+ -+struct deu_arc4 { -+ struct arc4_controlr { -+ u32 KRE:1; -+ u32 KLEN:4; -+ u32 KSAE:1; -+ u32 GO:1; -+ u32 STP:1; -+ u32 reserved1:6; -+ u32 NDC:1; -+ u32 ENDI:1; -+ u32 reserved2:8; -+ u32 BUS:1; /* bsy */ -+ u32 reserved3:1; -+ u32 ARS:1; -+ u32 SM:1; -+ u32 reserved4:4; -+ } ctrl; -+ -+ u32 K3R; /* 104h */ -+ u32 K2R; /* 108h */ -+ u32 K1R; /* 10Ch */ -+ u32 K0R; /* 110h */ -+ u32 IDLEN; /* 114h */ -+ u32 ID3R; /* 118h */ -+ u32 ID2R; /* 11Ch */ -+ u32 ID1R; /* 120h */ -+ u32 ID0R; /* 124h */ -+ u32 OD3R; /* 128h */ -+ u32 OD2R; /* 12Ch */ -+ u32 OD1R; /* 130h */ -+ u32 OD0R; /* 134h */ -+}; -+ -+struct deu_hash { -+ struct deu_hash_ctrl { -+ u32 reserved1:5; -+ u32 KHS:1; -+ u32 GO:1; -+ u32 INIT:1; -+ u32 reserved2:6; -+ u32 NDC:1; -+ u32 ENDI:1; -+ u32 reserved3:7; -+ u32 DGRY:1; -+ u32 BSY:1; -+ u32 reserved4:1; -+ u32 IRCL:1; -+ u32 SM:1; -+ u32 KYUE:1; -+ u32 HMEN:1; -+ u32 SSEN:1; -+ u32 ALGO:1; -+ } ctrl; -+ -+ u32 MR; /* B4h */ -+ u32 D1R; /* B8h */ -+ u32 D2R; /* BCh */ -+ u32 D3R; /* C0h */ -+ u32 D4R; /* C4h */ -+ u32 D5R; /* C8h */ -+ u32 dummy; /* CCh */ -+ u32 KIDX; /* D0h */ -+ u32 KEY; /* D4h */ -+ u32 DBN; /* D8h */ -+}; -+ -+struct deu_dma { -+ struct deu_dma_ctrl { -+ u32 reserved1:22; -+ u32 BS:2; -+ u32 BSY:1; -+ u32 reserved2:1; -+ u32 ALGO:2; -+ u32 RXCLS:2; -+ u32 reserved3:1; -+ u32 EN:1; -+ } ctrl; -+}; -+ -+#endif /* DEU_FALCON_H */ ---- a/arch/mips/lantiq/xway/devices.h -+++ b/arch/mips/lantiq/xway/devices.h -@@ -24,5 +24,6 @@ - extern void __init lq_register_ethernet(struct lq_eth_data *eth); - extern void __init lq_register_asc(int port); - extern void __init lq_register_gpio_buttons(struct gpio_button *buttons, int cnt); -+extern void __init lq_register_crypto(const char *name); - - #endif ---- a/arch/mips/lantiq/xway/mach-easy50712.c -+++ b/arch/mips/lantiq/xway/mach-easy50712.c -@@ -74,6 +74,7 @@ - lq_register_wdt(); - lq_register_pci(&lq_pci_data); - lq_register_ethernet(&lq_eth_data); -+ lq_register_crypto("lq_danube_deu"); - } - - MIPS_MACHINE(LANTIQ_MACH_EASY50712, ---- a/arch/mips/lantiq/xway/mach-easy50812.c -+++ b/arch/mips/lantiq/xway/mach-easy50812.c -@@ -73,6 +73,7 @@ - lq_register_wdt(); - lq_register_pci(&lq_pci_data); - lq_register_ethernet(&lq_eth_data); -+ lq_register_crypto("lq_ar9_deu"); - } - - MIPS_MACHINE(LANTIQ_MACH_EASY50812, |