Commit 13802005d8f2db244ec1f5d7f6923de8f7a463db

Authored by Nicolas Royer
Committed by Herbert Xu
1 parent bd3c7b5c2a

crypto: atmel - add Atmel DES/TDES driver

Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Acked-by: Eric Bénard <eric@eukrea.com>
Tested-by: Eric Bénard <eric@eukrea.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Showing 4 changed files with 1321 additions and 0 deletions Side-by-side Diff

drivers/crypto/Kconfig
... ... @@ -349,5 +349,21 @@
349 349 To compile this driver as a module, choose M here: the module
350 350 will be called atmel-aes.
351 351  
  352 +config CRYPTO_DEV_ATMEL_TDES
  353 + tristate "Support for Atmel DES/TDES hw accelerator"
  354 + depends on ARCH_AT91
  355 + select CRYPTO_DES
  356 + select CRYPTO_CBC
  357 + select CRYPTO_ECB
  358 + select CRYPTO_ALGAPI
  359 + select CRYPTO_BLKCIPHER
  360 + help
  361 + Some Atmel processors have DES/TDES hw accelerator.
  362 + Select this if you want to use the Atmel module for
  363 + DES/TDES algorithms.
  364 +
  365 + To compile this driver as a module, choose M here: the module
  366 + will be called atmel-tdes.
  367 +
352 368 endif # CRYPTO_HW
drivers/crypto/Makefile
... ... @@ -18,4 +18,5 @@
18 18 obj-$(CONFIG_CRYPTO_DEV_BFIN_CRC) += bfin_crc.o
19 19 obj-$(CONFIG_CRYPTO_DEV_NX) += nx/
20 20 obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o
  21 +obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o
drivers/crypto/atmel-tdes-regs.h
  1 +#ifndef __ATMEL_TDES_REGS_H__
  2 +#define __ATMEL_TDES_REGS_H__
  3 +
  4 +#define TDES_CR 0x00
  5 +#define TDES_CR_START (1 << 0)
  6 +#define TDES_CR_SWRST (1 << 8)
  7 +#define TDES_CR_LOADSEED (1 << 16)
  8 +
  9 +#define TDES_MR 0x04
  10 +#define TDES_MR_CYPHER_DEC (0 << 0)
  11 +#define TDES_MR_CYPHER_ENC (1 << 0)
  12 +#define TDES_MR_TDESMOD_MASK (0x3 << 1)
  13 +#define TDES_MR_TDESMOD_DES (0x0 << 1)
  14 +#define TDES_MR_TDESMOD_TDES (0x1 << 1)
  15 +#define TDES_MR_TDESMOD_XTEA (0x2 << 1)
  16 +#define TDES_MR_KEYMOD_3KEY (0 << 4)
  17 +#define TDES_MR_KEYMOD_2KEY (1 << 4)
  18 +#define TDES_MR_SMOD_MASK (0x3 << 8)
  19 +#define TDES_MR_SMOD_MANUAL (0x0 << 8)
  20 +#define TDES_MR_SMOD_AUTO (0x1 << 8)
  21 +#define TDES_MR_SMOD_PDC (0x2 << 8)
  22 +#define TDES_MR_OPMOD_MASK (0x3 << 12)
  23 +#define TDES_MR_OPMOD_ECB (0x0 << 12)
  24 +#define TDES_MR_OPMOD_CBC (0x1 << 12)
  25 +#define TDES_MR_OPMOD_OFB (0x2 << 12)
  26 +#define TDES_MR_OPMOD_CFB (0x3 << 12)
  27 +#define TDES_MR_LOD (0x1 << 15)
  28 +#define TDES_MR_CFBS_MASK (0x3 << 16)
  29 +#define TDES_MR_CFBS_64b (0x0 << 16)
  30 +#define TDES_MR_CFBS_32b (0x1 << 16)
  31 +#define TDES_MR_CFBS_16b (0x2 << 16)
  32 +#define TDES_MR_CFBS_8b (0x3 << 16)
  33 +#define TDES_MR_CKEY_MASK (0xF << 20)
  34 +#define TDES_MR_CKEY_OFFSET 20
  35 +#define TDES_MR_CTYPE_MASK (0x3F << 24)
  36 +#define TDES_MR_CTYPE_OFFSET 24
  37 +
  38 +#define TDES_IER 0x10
  39 +#define TDES_IDR 0x14
  40 +#define TDES_IMR 0x18
  41 +#define TDES_ISR 0x1C
  42 +#define TDES_INT_DATARDY (1 << 0)
  43 +#define TDES_INT_ENDRX (1 << 1)
  44 +#define TDES_INT_ENDTX (1 << 2)
  45 +#define TDES_INT_RXBUFF (1 << 3)
  46 +#define TDES_INT_TXBUFE (1 << 4)
  47 +#define TDES_INT_URAD (1 << 8)
  48 +#define TDES_ISR_URAT_MASK (0x3 << 12)
  49 +#define TDES_ISR_URAT_IDR (0x0 << 12)
  50 +#define TDES_ISR_URAT_ODR (0x1 << 12)
  51 +#define TDES_ISR_URAT_MR (0x2 << 12)
  52 +#define TDES_ISR_URAT_WO (0x3 << 12)
  53 +
  54 +
  55 +#define TDES_KEY1W1R 0x20
  56 +#define TDES_KEY1W2R 0x24
  57 +#define TDES_KEY2W1R 0x28
  58 +#define TDES_KEY2W2R 0x2C
  59 +#define TDES_KEY3W1R 0x30
  60 +#define TDES_KEY3W2R 0x34
  61 +#define TDES_IDATA1R 0x40
  62 +#define TDES_IDATA2R 0x44
  63 +#define TDES_ODATA1R 0x50
  64 +#define TDES_ODATA2R 0x54
  65 +#define TDES_IV1R 0x60
  66 +#define TDES_IV2R 0x64
  67 +
  68 +#define TDES_XTEARNDR 0x70
  69 +#define TDES_XTEARNDR_XTEA_RNDS_MASK (0x3F << 0)
  70 +#define TDES_XTEARNDR_XTEA_RNDS_OFFSET 0
  71 +
  72 +#define TDES_RPR 0x100
  73 +#define TDES_RCR 0x104
  74 +#define TDES_TPR 0x108
  75 +#define TDES_TCR 0x10C
  76 +#define TDES_RNPR 0x118
  77 +#define TDES_RNCR 0x11C
  78 +#define TDES_TNPR 0x118
  79 +#define TDES_TNCR 0x11C
  80 +#define TDES_PTCR 0x120
  81 +#define TDES_PTCR_RXTEN (1 << 0)
  82 +#define TDES_PTCR_RXTDIS (1 << 1)
  83 +#define TDES_PTCR_TXTEN (1 << 8)
  84 +#define TDES_PTCR_TXTDIS (1 << 9)
  85 +#define TDES_PTSR 0x124
  86 +#define TDES_PTSR_RXTEN (1 << 0)
  87 +#define TDES_PTSR_TXTEN (1 << 8)
  88 +
  89 +#endif /* __ATMEL_TDES_REGS_H__ */
drivers/crypto/atmel-tdes.c
Changes suppressed. Click to show
  1 +/*
  2 + * Cryptographic API.
  3 + *
  4 + * Support for ATMEL DES/TDES HW acceleration.
  5 + *
  6 + * Copyright (c) 2012 Eukréa Electromatique - ATMEL
  7 + * Author: Nicolas Royer <nicolas@eukrea.com>
  8 + *
  9 + * This program is free software; you can redistribute it and/or modify
  10 + * it under the terms of the GNU General Public License version 2 as published
  11 + * by the Free Software Foundation.
  12 + *
  13 + * Some ideas are from omap-aes.c drivers.
  14 + */
  15 +
  16 +
  17 +#include <linux/kernel.h>
  18 +#include <linux/module.h>
  19 +#include <linux/slab.h>
  20 +#include <linux/err.h>
  21 +#include <linux/clk.h>
  22 +#include <linux/io.h>
  23 +#include <linux/hw_random.h>
  24 +#include <linux/platform_device.h>
  25 +
  26 +#include <linux/device.h>
  27 +#include <linux/module.h>
  28 +#include <linux/init.h>
  29 +#include <linux/errno.h>
  30 +#include <linux/interrupt.h>
  31 +#include <linux/kernel.h>
  32 +#include <linux/clk.h>
  33 +#include <linux/irq.h>
  34 +#include <linux/io.h>
  35 +#include <linux/platform_device.h>
  36 +#include <linux/scatterlist.h>
  37 +#include <linux/dma-mapping.h>
  38 +#include <linux/delay.h>
  39 +#include <linux/crypto.h>
  40 +#include <linux/cryptohash.h>
  41 +#include <crypto/scatterwalk.h>
  42 +#include <crypto/algapi.h>
  43 +#include <crypto/des.h>
  44 +#include <crypto/hash.h>
  45 +#include <crypto/internal/hash.h>
  46 +#include "atmel-tdes-regs.h"
  47 +
  48 +/* TDES flags */
  49 +#define TDES_FLAGS_MODE_MASK 0x007f
  50 +#define TDES_FLAGS_ENCRYPT BIT(0)
  51 +#define TDES_FLAGS_CBC BIT(1)
  52 +#define TDES_FLAGS_CFB BIT(2)
  53 +#define TDES_FLAGS_CFB8 BIT(3)
  54 +#define TDES_FLAGS_CFB16 BIT(4)
  55 +#define TDES_FLAGS_CFB32 BIT(5)
  56 +#define TDES_FLAGS_OFB BIT(6)
  57 +
  58 +#define TDES_FLAGS_INIT BIT(16)
  59 +#define TDES_FLAGS_FAST BIT(17)
  60 +#define TDES_FLAGS_BUSY BIT(18)
  61 +
  62 +#define ATMEL_TDES_QUEUE_LENGTH 1
  63 +
  64 +#define CFB8_BLOCK_SIZE 1
  65 +#define CFB16_BLOCK_SIZE 2
  66 +#define CFB32_BLOCK_SIZE 4
  67 +#define CFB64_BLOCK_SIZE 8
  68 +
  69 +
  70 +struct atmel_tdes_dev;
  71 +
  72 +struct atmel_tdes_ctx {
  73 + struct atmel_tdes_dev *dd;
  74 +
  75 + int keylen;
  76 + u32 key[3*DES_KEY_SIZE / sizeof(u32)];
  77 + unsigned long flags;
  78 +};
  79 +
  80 +struct atmel_tdes_reqctx {
  81 + unsigned long mode;
  82 +};
  83 +
  84 +struct atmel_tdes_dev {
  85 + struct list_head list;
  86 + unsigned long phys_base;
  87 + void __iomem *io_base;
  88 +
  89 + struct atmel_tdes_ctx *ctx;
  90 + struct device *dev;
  91 + struct clk *iclk;
  92 + int irq;
  93 +
  94 + unsigned long flags;
  95 + int err;
  96 +
  97 + spinlock_t lock;
  98 + struct crypto_queue queue;
  99 +
  100 + struct tasklet_struct done_task;
  101 + struct tasklet_struct queue_task;
  102 +
  103 + struct ablkcipher_request *req;
  104 + size_t total;
  105 +
  106 + struct scatterlist *in_sg;
  107 + size_t in_offset;
  108 + struct scatterlist *out_sg;
  109 + size_t out_offset;
  110 +
  111 + size_t buflen;
  112 + size_t dma_size;
  113 +
  114 + void *buf_in;
  115 + int dma_in;
  116 + dma_addr_t dma_addr_in;
  117 +
  118 + void *buf_out;
  119 + int dma_out;
  120 + dma_addr_t dma_addr_out;
  121 +};
  122 +
  123 +struct atmel_tdes_drv {
  124 + struct list_head dev_list;
  125 + spinlock_t lock;
  126 +};
  127 +
  128 +static struct atmel_tdes_drv atmel_tdes = {
  129 + .dev_list = LIST_HEAD_INIT(atmel_tdes.dev_list),
  130 + .lock = __SPIN_LOCK_UNLOCKED(atmel_tdes.lock),
  131 +};
  132 +
  133 +static int atmel_tdes_sg_copy(struct scatterlist **sg, size_t *offset,
  134 + void *buf, size_t buflen, size_t total, int out)
  135 +{
  136 + unsigned int count, off = 0;
  137 +
  138 + while (buflen && total) {
  139 + count = min((*sg)->length - *offset, total);
  140 + count = min(count, buflen);
  141 +
  142 + if (!count)
  143 + return off;
  144 +
  145 + scatterwalk_map_and_copy(buf + off, *sg, *offset, count, out);
  146 +
  147 + off += count;
  148 + buflen -= count;
  149 + *offset += count;
  150 + total -= count;
  151 +
  152 + if (*offset == (*sg)->length) {
  153 + *sg = sg_next(*sg);
  154 + if (*sg)
  155 + *offset = 0;
  156 + else
  157 + total = 0;
  158 + }
  159 + }
  160 +
  161 + return off;
  162 +}
  163 +
  164 +static inline u32 atmel_tdes_read(struct atmel_tdes_dev *dd, u32 offset)
  165 +{
  166 + return readl_relaxed(dd->io_base + offset);
  167 +}
  168 +
  169 +static inline void atmel_tdes_write(struct atmel_tdes_dev *dd,
  170 + u32 offset, u32 value)
  171 +{
  172 + writel_relaxed(value, dd->io_base + offset);
  173 +}
  174 +
  175 +static void atmel_tdes_write_n(struct atmel_tdes_dev *dd, u32 offset,
  176 + u32 *value, int count)
  177 +{
  178 + for (; count--; value++, offset += 4)
  179 + atmel_tdes_write(dd, offset, *value);
  180 +}
  181 +
  182 +static struct atmel_tdes_dev *atmel_tdes_find_dev(struct atmel_tdes_ctx *ctx)
  183 +{
  184 + struct atmel_tdes_dev *tdes_dd = NULL;
  185 + struct atmel_tdes_dev *tmp;
  186 +
  187 + spin_lock_bh(&atmel_tdes.lock);
  188 + if (!ctx->dd) {
  189 + list_for_each_entry(tmp, &atmel_tdes.dev_list, list) {
  190 + tdes_dd = tmp;
  191 + break;
  192 + }
  193 + ctx->dd = tdes_dd;
  194 + } else {
  195 + tdes_dd = ctx->dd;
  196 + }
  197 + spin_unlock_bh(&atmel_tdes.lock);
  198 +
  199 + return tdes_dd;
  200 +}
  201 +
  202 +static int atmel_tdes_hw_init(struct atmel_tdes_dev *dd)
  203 +{
  204 + clk_prepare_enable(dd->iclk);
  205 +
  206 + if (!(dd->flags & TDES_FLAGS_INIT)) {
  207 + atmel_tdes_write(dd, TDES_CR, TDES_CR_SWRST);
  208 + dd->flags |= TDES_FLAGS_INIT;
  209 + dd->err = 0;
  210 + }
  211 +
  212 + return 0;
  213 +}
  214 +
  215 +static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
  216 +{
  217 + int err;
  218 + u32 valcr = 0, valmr = TDES_MR_SMOD_PDC;
  219 +
  220 + err = atmel_tdes_hw_init(dd);
  221 +
  222 + if (err)
  223 + return err;
  224 +
  225 + atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
  226 +
  227 + /* MR register must be set before IV registers */
  228 + if (dd->ctx->keylen > (DES_KEY_SIZE << 1)) {
  229 + valmr |= TDES_MR_KEYMOD_3KEY;
  230 + valmr |= TDES_MR_TDESMOD_TDES;
  231 + } else if (dd->ctx->keylen > DES_KEY_SIZE) {
  232 + valmr |= TDES_MR_KEYMOD_2KEY;
  233 + valmr |= TDES_MR_TDESMOD_TDES;
  234 + } else {
  235 + valmr |= TDES_MR_TDESMOD_DES;
  236 + }
  237 +
  238 + if (dd->flags & TDES_FLAGS_CBC) {
  239 + valmr |= TDES_MR_OPMOD_CBC;
  240 + } else if (dd->flags & TDES_FLAGS_CFB) {
  241 + valmr |= TDES_MR_OPMOD_CFB;
  242 +
  243 + if (dd->flags & TDES_FLAGS_CFB8)
  244 + valmr |= TDES_MR_CFBS_8b;
  245 + else if (dd->flags & TDES_FLAGS_CFB16)
  246 + valmr |= TDES_MR_CFBS_16b;
  247 + else if (dd->flags & TDES_FLAGS_CFB32)
  248 + valmr |= TDES_MR_CFBS_32b;
  249 + } else if (dd->flags & TDES_FLAGS_OFB) {
  250 + valmr |= TDES_MR_OPMOD_OFB;
  251 + }
  252 +
  253 + if ((dd->flags & TDES_FLAGS_ENCRYPT) || (dd->flags & TDES_FLAGS_OFB))
  254 + valmr |= TDES_MR_CYPHER_ENC;
  255 +
  256 + atmel_tdes_write(dd, TDES_CR, valcr);
  257 + atmel_tdes_write(dd, TDES_MR, valmr);
  258 +
  259 + atmel_tdes_write_n(dd, TDES_KEY1W1R, dd->ctx->key,
  260 + dd->ctx->keylen >> 2);
  261 +
  262 + if (((dd->flags & TDES_FLAGS_CBC) || (dd->flags & TDES_FLAGS_CFB) ||
  263 + (dd->flags & TDES_FLAGS_OFB)) && dd->req->info) {
  264 + atmel_tdes_write_n(dd, TDES_IV1R, dd->req->info, 2);
  265 + }
  266 +
  267 + return 0;
  268 +}
  269 +
  270 +static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd)
  271 +{
  272 + int err = 0;
  273 + size_t count;
  274 +
  275 + atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
  276 +
  277 + if (dd->flags & TDES_FLAGS_FAST) {
  278 + dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
  279 + dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
  280 + } else {
  281 + dma_sync_single_for_device(dd->dev, dd->dma_addr_out,
  282 + dd->dma_size, DMA_FROM_DEVICE);
  283 +
  284 + /* copy data */
  285 + count = atmel_tdes_sg_copy(&dd->out_sg, &dd->out_offset,
  286 + dd->buf_out, dd->buflen, dd->dma_size, 1);
  287 + if (count != dd->dma_size) {
  288 + err = -EINVAL;
  289 + pr_err("not all data converted: %u\n", count);
  290 + }
  291 + }
  292 +
  293 + return err;
  294 +}
  295 +
  296 +static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd)
  297 +{
  298 + int err = -ENOMEM;
  299 +
  300 + dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0);
  301 + dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, 0);
  302 + dd->buflen = PAGE_SIZE;
  303 + dd->buflen &= ~(DES_BLOCK_SIZE - 1);
  304 +
  305 + if (!dd->buf_in || !dd->buf_out) {
  306 + dev_err(dd->dev, "unable to alloc pages.\n");
  307 + goto err_alloc;
  308 + }
  309 +
  310 + /* MAP here */
  311 + dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in,
  312 + dd->buflen, DMA_TO_DEVICE);
  313 + if (dma_mapping_error(dd->dev, dd->dma_addr_in)) {
  314 + dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
  315 + err = -EINVAL;
  316 + goto err_map_in;
  317 + }
  318 +
  319 + dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out,
  320 + dd->buflen, DMA_FROM_DEVICE);
  321 + if (dma_mapping_error(dd->dev, dd->dma_addr_out)) {
  322 + dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
  323 + err = -EINVAL;
  324 + goto err_map_out;
  325 + }
  326 +
  327 + return 0;
  328 +
  329 +err_map_out:
  330 + dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen,
  331 + DMA_TO_DEVICE);
  332 +err_map_in:
  333 + free_page((unsigned long)dd->buf_out);
  334 + free_page((unsigned long)dd->buf_in);
  335 +err_alloc:
  336 + if (err)
  337 + pr_err("error: %d\n", err);
  338 + return err;
  339 +}
  340 +
  341 +static void atmel_tdes_dma_cleanup(struct atmel_tdes_dev *dd)
  342 +{
  343 + dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
  344 + DMA_FROM_DEVICE);
  345 + dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen,
  346 + DMA_TO_DEVICE);
  347 + free_page((unsigned long)dd->buf_out);
  348 + free_page((unsigned long)dd->buf_in);
  349 +}
  350 +
  351 +static int atmel_tdes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
  352 + dma_addr_t dma_addr_out, int length)
  353 +{
  354 + struct atmel_tdes_ctx *ctx = crypto_tfm_ctx(tfm);
  355 + struct atmel_tdes_dev *dd = ctx->dd;
  356 + int len32;
  357 +
  358 + dd->dma_size = length;
  359 +
  360 + if (!(dd->flags & TDES_FLAGS_FAST)) {
  361 + dma_sync_single_for_device(dd->dev, dma_addr_in, length,
  362 + DMA_TO_DEVICE);
  363 + }
  364 +
  365 + if ((dd->flags & TDES_FLAGS_CFB) && (dd->flags & TDES_FLAGS_CFB8))
  366 + len32 = DIV_ROUND_UP(length, sizeof(u8));
  367 + else if ((dd->flags & TDES_FLAGS_CFB) && (dd->flags & TDES_FLAGS_CFB16))
  368 + len32 = DIV_ROUND_UP(length, sizeof(u16));
  369 + else
  370 + len32 = DIV_ROUND_UP(length, sizeof(u32));
  371 +
  372 + atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
  373 + atmel_tdes_write(dd, TDES_TPR, dma_addr_in);
  374 + atmel_tdes_write(dd, TDES_TCR, len32);
  375 + atmel_tdes_write(dd, TDES_RPR, dma_addr_out);
  376 + atmel_tdes_write(dd, TDES_RCR, len32);
  377 +
  378 + /* Enable Interrupt */
  379 + atmel_tdes_write(dd, TDES_IER, TDES_INT_ENDRX);
  380 +
  381 + /* Start DMA transfer */
  382 + atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTEN | TDES_PTCR_RXTEN);
  383 +
  384 + return 0;
  385 +}
  386 +
  387 +static int atmel_tdes_crypt_dma_start(struct atmel_tdes_dev *dd)
  388 +{
  389 + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(
  390 + crypto_ablkcipher_reqtfm(dd->req));
  391 + int err, fast = 0, in, out;
  392 + size_t count;
  393 + dma_addr_t addr_in, addr_out;
  394 +
  395 + if (sg_is_last(dd->in_sg) && sg_is_last(dd->out_sg)) {
  396 + /* check for alignment */
  397 + in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32));
  398 + out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32));
  399 +
  400 + fast = in && out;
  401 + }
  402 +
  403 + if (fast) {
  404 + count = min(dd->total, sg_dma_len(dd->in_sg));
  405 + count = min(count, sg_dma_len(dd->out_sg));
  406 +
  407 + if (count != dd->total) {
  408 + pr_err("request length != buffer length\n");
  409 + return -EINVAL;
  410 + }
  411 +
  412 + err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
  413 + if (!err) {
  414 + dev_err(dd->dev, "dma_map_sg() error\n");
  415 + return -EINVAL;
  416 + }
  417 +
  418 + err = dma_map_sg(dd->dev, dd->out_sg, 1,
  419 + DMA_FROM_DEVICE);
  420 + if (!err) {
  421 + dev_err(dd->dev, "dma_map_sg() error\n");
  422 + dma_unmap_sg(dd->dev, dd->in_sg, 1,
  423 + DMA_TO_DEVICE);
  424 + return -EINVAL;
  425 + }
  426 +
  427 + addr_in = sg_dma_address(dd->in_sg);
  428 + addr_out = sg_dma_address(dd->out_sg);
  429 +
  430 + dd->flags |= TDES_FLAGS_FAST;
  431 +
  432 + } else {
  433 + /* use cache buffers */
  434 + count = atmel_tdes_sg_copy(&dd->in_sg, &dd->in_offset,
  435 + dd->buf_in, dd->buflen, dd->total, 0);
  436 +
  437 + addr_in = dd->dma_addr_in;
  438 + addr_out = dd->dma_addr_out;
  439 +
  440 + dd->flags &= ~TDES_FLAGS_FAST;
  441 +
  442 + }
  443 +
  444 + dd->total -= count;
  445 +
  446 + err = atmel_tdes_crypt_dma(tfm, addr_in, addr_out, count);
  447 + if (err) {
  448 + dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
  449 + dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
  450 + }
  451 +
  452 + return err;
  453 +}
  454 +
  455 +
  456 +static void atmel_tdes_finish_req(struct atmel_tdes_dev *dd, int err)
  457 +{
  458 + struct ablkcipher_request *req = dd->req;
  459 +
  460 + clk_disable_unprepare(dd->iclk);
  461 +
  462 + dd->flags &= ~TDES_FLAGS_BUSY;
  463 +
  464 + req->base.complete(&req->base, err);
  465 +}
  466 +
  467 +static int atmel_tdes_handle_queue(struct atmel_tdes_dev *dd,
  468 + struct ablkcipher_request *req)
  469 +{
  470 + struct crypto_async_request *async_req, *backlog;
  471 + struct atmel_tdes_ctx *ctx;
  472 + struct atmel_tdes_reqctx *rctx;
  473 + unsigned long flags;
  474 + int err, ret = 0;
  475 +
  476 + spin_lock_irqsave(&dd->lock, flags);
  477 + if (req)
  478 + ret = ablkcipher_enqueue_request(&dd->queue, req);
  479 + if (dd->flags & TDES_FLAGS_BUSY) {
  480 + spin_unlock_irqrestore(&dd->lock, flags);
  481 + return ret;
  482 + }
  483 + backlog = crypto_get_backlog(&dd->queue);
  484 + async_req = crypto_dequeue_request(&dd->queue);
  485 + if (async_req)
  486 + dd->flags |= TDES_FLAGS_BUSY;
  487 + spin_unlock_irqrestore(&dd->lock, flags);
  488 +
  489 + if (!async_req)
  490 + return ret;
  491 +
  492 + if (backlog)
  493 + backlog->complete(backlog, -EINPROGRESS);
  494 +
  495 + req = ablkcipher_request_cast(async_req);
  496 +
  497 + /* assign new request to device */
  498 + dd->req = req;
  499 + dd->total = req->nbytes;
  500 + dd->in_offset = 0;
  501 + dd->in_sg = req->src;
  502 + dd->out_offset = 0;
  503 + dd->out_sg = req->dst;
  504 +
  505 + rctx = ablkcipher_request_ctx(req);
  506 + ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
  507 + rctx->mode &= TDES_FLAGS_MODE_MASK;
  508 + dd->flags = (dd->flags & ~TDES_FLAGS_MODE_MASK) | rctx->mode;
  509 + dd->ctx = ctx;
  510 + ctx->dd = dd;
  511 +
  512 + err = atmel_tdes_write_ctrl(dd);
  513 + if (!err)
  514 + err = atmel_tdes_crypt_dma_start(dd);
  515 + if (err) {
  516 + /* des_task will not finish it, so do it here */
  517 + atmel_tdes_finish_req(dd, err);
  518 + tasklet_schedule(&dd->queue_task);
  519 + }
  520 +
  521 + return ret;
  522 +}
  523 +
  524 +
  525 +static int atmel_tdes_crypt(struct ablkcipher_request *req, unsigned long mode)
  526 +{
  527 + struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(
  528 + crypto_ablkcipher_reqtfm(req));
  529 + struct atmel_tdes_reqctx *rctx = ablkcipher_request_ctx(req);
  530 + struct atmel_tdes_dev *dd;
  531 +
  532 + if (mode & TDES_FLAGS_CFB8) {
  533 + if (!IS_ALIGNED(req->nbytes, CFB8_BLOCK_SIZE)) {
  534 + pr_err("request size is not exact amount of CFB8 blocks\n");
  535 + return -EINVAL;
  536 + }
  537 + } else if (mode & TDES_FLAGS_CFB16) {
  538 + if (!IS_ALIGNED(req->nbytes, CFB16_BLOCK_SIZE)) {
  539 + pr_err("request size is not exact amount of CFB16 blocks\n");
  540 + return -EINVAL;
  541 + }
  542 + } else if (mode & TDES_FLAGS_CFB32) {
  543 + if (!IS_ALIGNED(req->nbytes, CFB32_BLOCK_SIZE)) {
  544 + pr_err("request size is not exact amount of CFB32 blocks\n");
  545 + return -EINVAL;
  546 + }
  547 + } else if (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE)) {
  548 + pr_err("request size is not exact amount of DES blocks\n");
  549 + return -EINVAL;
  550 + }
  551 +
  552 + dd = atmel_tdes_find_dev(ctx);
  553 + if (!dd)
  554 + return -ENODEV;
  555 +
  556 + rctx->mode = mode;
  557 +
  558 + return atmel_tdes_handle_queue(dd, req);
  559 +}
  560 +
  561 +static int atmel_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
  562 + unsigned int keylen)
  563 +{
  564 + u32 tmp[DES_EXPKEY_WORDS];
  565 + int err;
  566 + struct crypto_tfm *ctfm = crypto_ablkcipher_tfm(tfm);
  567 +
  568 + struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
  569 +
  570 + if (keylen != DES_KEY_SIZE) {
  571 + crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
  572 + return -EINVAL;
  573 + }
  574 +
  575 + err = des_ekey(tmp, key);
  576 + if (err == 0 && (ctfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
  577 + ctfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
  578 + return -EINVAL;
  579 + }
  580 +
  581 + memcpy(ctx->key, key, keylen);
  582 + ctx->keylen = keylen;
  583 +
  584 + return 0;
  585 +}
  586 +
  587 +static int atmel_tdes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
  588 + unsigned int keylen)
  589 +{
  590 + struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
  591 + const char *alg_name;
  592 +
  593 + alg_name = crypto_tfm_alg_name(crypto_ablkcipher_tfm(tfm));
  594 +
  595 + /*
  596 + * HW bug in cfb 3-keys mode.
  597 + */
  598 + if (strstr(alg_name, "cfb") && (keylen != 2*DES_KEY_SIZE)) {
  599 + crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
  600 + return -EINVAL;
  601 + } else if ((keylen != 2*DES_KEY_SIZE) && (keylen != 3*DES_KEY_SIZE)) {
  602 + crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
  603 + return -EINVAL;
  604 + }
  605 +
  606 + memcpy(ctx->key, key, keylen);
  607 + ctx->keylen = keylen;
  608 +
  609 + return 0;
  610 +}
  611 +
  612 +static int atmel_tdes_ecb_encrypt(struct ablkcipher_request *req)
  613 +{
  614 + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT);
  615 +}
  616 +
  617 +static int atmel_tdes_ecb_decrypt(struct ablkcipher_request *req)
  618 +{
  619 + return atmel_tdes_crypt(req, 0);
  620 +}
  621 +
  622 +static int atmel_tdes_cbc_encrypt(struct ablkcipher_request *req)
  623 +{
  624 + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CBC);
  625 +}
  626 +
  627 +static int atmel_tdes_cbc_decrypt(struct ablkcipher_request *req)
  628 +{
  629 + return atmel_tdes_crypt(req, TDES_FLAGS_CBC);
  630 +}
  631 +static int atmel_tdes_cfb_encrypt(struct ablkcipher_request *req)
  632 +{
  633 + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB);
  634 +}
  635 +
  636 +static int atmel_tdes_cfb_decrypt(struct ablkcipher_request *req)
  637 +{
  638 + return atmel_tdes_crypt(req, TDES_FLAGS_CFB);
  639 +}
  640 +
  641 +static int atmel_tdes_cfb8_encrypt(struct ablkcipher_request *req)
  642 +{
  643 + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB |
  644 + TDES_FLAGS_CFB8);
  645 +}
  646 +
  647 +static int atmel_tdes_cfb8_decrypt(struct ablkcipher_request *req)
  648 +{
  649 + return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB8);
  650 +}
  651 +
  652 +static int atmel_tdes_cfb16_encrypt(struct ablkcipher_request *req)
  653 +{
  654 + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB |
  655 + TDES_FLAGS_CFB16);
  656 +}
  657 +
  658 +static int atmel_tdes_cfb16_decrypt(struct ablkcipher_request *req)
  659 +{
  660 + return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB16);
  661 +}
  662 +
  663 +static int atmel_tdes_cfb32_encrypt(struct ablkcipher_request *req)
  664 +{
  665 + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB |
  666 + TDES_FLAGS_CFB32);
  667 +}
  668 +
  669 +static int atmel_tdes_cfb32_decrypt(struct ablkcipher_request *req)
  670 +{
  671 + return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB32);
  672 +}
  673 +
  674 +static int atmel_tdes_ofb_encrypt(struct ablkcipher_request *req)
  675 +{
  676 + return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_OFB);
  677 +}
  678 +
  679 +static int atmel_tdes_ofb_decrypt(struct ablkcipher_request *req)
  680 +{
  681 + return atmel_tdes_crypt(req, TDES_FLAGS_OFB);
  682 +}
  683 +
  684 +static int atmel_tdes_cra_init(struct crypto_tfm *tfm)
  685 +{
  686 + tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_tdes_reqctx);
  687 +
  688 + return 0;
  689 +}
  690 +
  691 +static void atmel_tdes_cra_exit(struct crypto_tfm *tfm)
  692 +{
  693 +}
  694 +
  695 +static struct crypto_alg tdes_algs[] = {
  696 +{
  697 + .cra_name = "ecb(des)",
  698 + .cra_driver_name = "atmel-ecb-des",
  699 + .cra_priority = 100,
  700 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  701 + .cra_blocksize = DES_BLOCK_SIZE,
  702 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  703 + .cra_alignmask = 0,
  704 + .cra_type = &crypto_ablkcipher_type,
  705 + .cra_module = THIS_MODULE,
  706 + .cra_init = atmel_tdes_cra_init,
  707 + .cra_exit = atmel_tdes_cra_exit,
  708 + .cra_u.ablkcipher = {
  709 + .min_keysize = DES_KEY_SIZE,
  710 + .max_keysize = DES_KEY_SIZE,
  711 + .setkey = atmel_des_setkey,
  712 + .encrypt = atmel_tdes_ecb_encrypt,
  713 + .decrypt = atmel_tdes_ecb_decrypt,
  714 + }
  715 +},
  716 +{
  717 + .cra_name = "cbc(des)",
  718 + .cra_driver_name = "atmel-cbc-des",
  719 + .cra_priority = 100,
  720 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  721 + .cra_blocksize = DES_BLOCK_SIZE,
  722 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  723 + .cra_alignmask = 0,
  724 + .cra_type = &crypto_ablkcipher_type,
  725 + .cra_module = THIS_MODULE,
  726 + .cra_init = atmel_tdes_cra_init,
  727 + .cra_exit = atmel_tdes_cra_exit,
  728 + .cra_u.ablkcipher = {
  729 + .min_keysize = DES_KEY_SIZE,
  730 + .max_keysize = DES_KEY_SIZE,
  731 + .ivsize = DES_BLOCK_SIZE,
  732 + .setkey = atmel_des_setkey,
  733 + .encrypt = atmel_tdes_cbc_encrypt,
  734 + .decrypt = atmel_tdes_cbc_decrypt,
  735 + }
  736 +},
  737 +{
  738 + .cra_name = "cfb(des)",
  739 + .cra_driver_name = "atmel-cfb-des",
  740 + .cra_priority = 100,
  741 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  742 + .cra_blocksize = DES_BLOCK_SIZE,
  743 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  744 + .cra_alignmask = 0,
  745 + .cra_type = &crypto_ablkcipher_type,
  746 + .cra_module = THIS_MODULE,
  747 + .cra_init = atmel_tdes_cra_init,
  748 + .cra_exit = atmel_tdes_cra_exit,
  749 + .cra_u.ablkcipher = {
  750 + .min_keysize = DES_KEY_SIZE,
  751 + .max_keysize = DES_KEY_SIZE,
  752 + .ivsize = DES_BLOCK_SIZE,
  753 + .setkey = atmel_des_setkey,
  754 + .encrypt = atmel_tdes_cfb_encrypt,
  755 + .decrypt = atmel_tdes_cfb_decrypt,
  756 + }
  757 +},
  758 +{
  759 + .cra_name = "cfb8(des)",
  760 + .cra_driver_name = "atmel-cfb8-des",
  761 + .cra_priority = 100,
  762 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  763 + .cra_blocksize = CFB8_BLOCK_SIZE,
  764 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  765 + .cra_alignmask = 0,
  766 + .cra_type = &crypto_ablkcipher_type,
  767 + .cra_module = THIS_MODULE,
  768 + .cra_init = atmel_tdes_cra_init,
  769 + .cra_exit = atmel_tdes_cra_exit,
  770 + .cra_u.ablkcipher = {
  771 + .min_keysize = DES_KEY_SIZE,
  772 + .max_keysize = DES_KEY_SIZE,
  773 + .ivsize = DES_BLOCK_SIZE,
  774 + .setkey = atmel_des_setkey,
  775 + .encrypt = atmel_tdes_cfb8_encrypt,
  776 + .decrypt = atmel_tdes_cfb8_decrypt,
  777 + }
  778 +},
  779 +{
  780 + .cra_name = "cfb16(des)",
  781 + .cra_driver_name = "atmel-cfb16-des",
  782 + .cra_priority = 100,
  783 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  784 + .cra_blocksize = CFB16_BLOCK_SIZE,
  785 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  786 + .cra_alignmask = 0,
  787 + .cra_type = &crypto_ablkcipher_type,
  788 + .cra_module = THIS_MODULE,
  789 + .cra_init = atmel_tdes_cra_init,
  790 + .cra_exit = atmel_tdes_cra_exit,
  791 + .cra_u.ablkcipher = {
  792 + .min_keysize = DES_KEY_SIZE,
  793 + .max_keysize = DES_KEY_SIZE,
  794 + .ivsize = DES_BLOCK_SIZE,
  795 + .setkey = atmel_des_setkey,
  796 + .encrypt = atmel_tdes_cfb16_encrypt,
  797 + .decrypt = atmel_tdes_cfb16_decrypt,
  798 + }
  799 +},
  800 +{
  801 + .cra_name = "cfb32(des)",
  802 + .cra_driver_name = "atmel-cfb32-des",
  803 + .cra_priority = 100,
  804 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  805 + .cra_blocksize = CFB32_BLOCK_SIZE,
  806 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  807 + .cra_alignmask = 0,
  808 + .cra_type = &crypto_ablkcipher_type,
  809 + .cra_module = THIS_MODULE,
  810 + .cra_init = atmel_tdes_cra_init,
  811 + .cra_exit = atmel_tdes_cra_exit,
  812 + .cra_u.ablkcipher = {
  813 + .min_keysize = DES_KEY_SIZE,
  814 + .max_keysize = DES_KEY_SIZE,
  815 + .ivsize = DES_BLOCK_SIZE,
  816 + .setkey = atmel_des_setkey,
  817 + .encrypt = atmel_tdes_cfb32_encrypt,
  818 + .decrypt = atmel_tdes_cfb32_decrypt,
  819 + }
  820 +},
  821 +{
  822 + .cra_name = "ofb(des)",
  823 + .cra_driver_name = "atmel-ofb-des",
  824 + .cra_priority = 100,
  825 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  826 + .cra_blocksize = DES_BLOCK_SIZE,
  827 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  828 + .cra_alignmask = 0,
  829 + .cra_type = &crypto_ablkcipher_type,
  830 + .cra_module = THIS_MODULE,
  831 + .cra_init = atmel_tdes_cra_init,
  832 + .cra_exit = atmel_tdes_cra_exit,
  833 + .cra_u.ablkcipher = {
  834 + .min_keysize = DES_KEY_SIZE,
  835 + .max_keysize = DES_KEY_SIZE,
  836 + .ivsize = DES_BLOCK_SIZE,
  837 + .setkey = atmel_des_setkey,
  838 + .encrypt = atmel_tdes_ofb_encrypt,
  839 + .decrypt = atmel_tdes_ofb_decrypt,
  840 + }
  841 +},
  842 +{
  843 + .cra_name = "ecb(des3_ede)",
  844 + .cra_driver_name = "atmel-ecb-tdes",
  845 + .cra_priority = 100,
  846 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  847 + .cra_blocksize = DES_BLOCK_SIZE,
  848 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  849 + .cra_alignmask = 0,
  850 + .cra_type = &crypto_ablkcipher_type,
  851 + .cra_module = THIS_MODULE,
  852 + .cra_init = atmel_tdes_cra_init,
  853 + .cra_exit = atmel_tdes_cra_exit,
  854 + .cra_u.ablkcipher = {
  855 + .min_keysize = 2 * DES_KEY_SIZE,
  856 + .max_keysize = 3 * DES_KEY_SIZE,
  857 + .setkey = atmel_tdes_setkey,
  858 + .encrypt = atmel_tdes_ecb_encrypt,
  859 + .decrypt = atmel_tdes_ecb_decrypt,
  860 + }
  861 +},
  862 +{
  863 + .cra_name = "cbc(des3_ede)",
  864 + .cra_driver_name = "atmel-cbc-tdes",
  865 + .cra_priority = 100,
  866 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  867 + .cra_blocksize = DES_BLOCK_SIZE,
  868 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  869 + .cra_alignmask = 0,
  870 + .cra_type = &crypto_ablkcipher_type,
  871 + .cra_module = THIS_MODULE,
  872 + .cra_init = atmel_tdes_cra_init,
  873 + .cra_exit = atmel_tdes_cra_exit,
  874 + .cra_u.ablkcipher = {
  875 + .min_keysize = 2*DES_KEY_SIZE,
  876 + .max_keysize = 3*DES_KEY_SIZE,
  877 + .ivsize = DES_BLOCK_SIZE,
  878 + .setkey = atmel_tdes_setkey,
  879 + .encrypt = atmel_tdes_cbc_encrypt,
  880 + .decrypt = atmel_tdes_cbc_decrypt,
  881 + }
  882 +},
  883 +{
  884 + .cra_name = "cfb(des3_ede)",
  885 + .cra_driver_name = "atmel-cfb-tdes",
  886 + .cra_priority = 100,
  887 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  888 + .cra_blocksize = DES_BLOCK_SIZE,
  889 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  890 + .cra_alignmask = 0,
  891 + .cra_type = &crypto_ablkcipher_type,
  892 + .cra_module = THIS_MODULE,
  893 + .cra_init = atmel_tdes_cra_init,
  894 + .cra_exit = atmel_tdes_cra_exit,
  895 + .cra_u.ablkcipher = {
  896 + .min_keysize = 2*DES_KEY_SIZE,
  897 + .max_keysize = 2*DES_KEY_SIZE,
  898 + .ivsize = DES_BLOCK_SIZE,
  899 + .setkey = atmel_tdes_setkey,
  900 + .encrypt = atmel_tdes_cfb_encrypt,
  901 + .decrypt = atmel_tdes_cfb_decrypt,
  902 + }
  903 +},
  904 +{
  905 + .cra_name = "cfb8(des3_ede)",
  906 + .cra_driver_name = "atmel-cfb8-tdes",
  907 + .cra_priority = 100,
  908 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  909 + .cra_blocksize = CFB8_BLOCK_SIZE,
  910 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  911 + .cra_alignmask = 0,
  912 + .cra_type = &crypto_ablkcipher_type,
  913 + .cra_module = THIS_MODULE,
  914 + .cra_init = atmel_tdes_cra_init,
  915 + .cra_exit = atmel_tdes_cra_exit,
  916 + .cra_u.ablkcipher = {
  917 + .min_keysize = 2*DES_KEY_SIZE,
  918 + .max_keysize = 2*DES_KEY_SIZE,
  919 + .ivsize = DES_BLOCK_SIZE,
  920 + .setkey = atmel_tdes_setkey,
  921 + .encrypt = atmel_tdes_cfb8_encrypt,
  922 + .decrypt = atmel_tdes_cfb8_decrypt,
  923 + }
  924 +},
  925 +{
  926 + .cra_name = "cfb16(des3_ede)",
  927 + .cra_driver_name = "atmel-cfb16-tdes",
  928 + .cra_priority = 100,
  929 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  930 + .cra_blocksize = CFB16_BLOCK_SIZE,
  931 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  932 + .cra_alignmask = 0,
  933 + .cra_type = &crypto_ablkcipher_type,
  934 + .cra_module = THIS_MODULE,
  935 + .cra_init = atmel_tdes_cra_init,
  936 + .cra_exit = atmel_tdes_cra_exit,
  937 + .cra_u.ablkcipher = {
  938 + .min_keysize = 2*DES_KEY_SIZE,
  939 + .max_keysize = 2*DES_KEY_SIZE,
  940 + .ivsize = DES_BLOCK_SIZE,
  941 + .setkey = atmel_tdes_setkey,
  942 + .encrypt = atmel_tdes_cfb16_encrypt,
  943 + .decrypt = atmel_tdes_cfb16_decrypt,
  944 + }
  945 +},
  946 +{
  947 + .cra_name = "cfb32(des3_ede)",
  948 + .cra_driver_name = "atmel-cfb32-tdes",
  949 + .cra_priority = 100,
  950 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  951 + .cra_blocksize = CFB32_BLOCK_SIZE,
  952 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  953 + .cra_alignmask = 0,
  954 + .cra_type = &crypto_ablkcipher_type,
  955 + .cra_module = THIS_MODULE,
  956 + .cra_init = atmel_tdes_cra_init,
  957 + .cra_exit = atmel_tdes_cra_exit,
  958 + .cra_u.ablkcipher = {
  959 + .min_keysize = 2*DES_KEY_SIZE,
  960 + .max_keysize = 2*DES_KEY_SIZE,
  961 + .ivsize = DES_BLOCK_SIZE,
  962 + .setkey = atmel_tdes_setkey,
  963 + .encrypt = atmel_tdes_cfb32_encrypt,
  964 + .decrypt = atmel_tdes_cfb32_decrypt,
  965 + }
  966 +},
  967 +{
  968 + .cra_name = "ofb(des3_ede)",
  969 + .cra_driver_name = "atmel-ofb-tdes",
  970 + .cra_priority = 100,
  971 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  972 + .cra_blocksize = DES_BLOCK_SIZE,
  973 + .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
  974 + .cra_alignmask = 0,
  975 + .cra_type = &crypto_ablkcipher_type,
  976 + .cra_module = THIS_MODULE,
  977 + .cra_init = atmel_tdes_cra_init,
  978 + .cra_exit = atmel_tdes_cra_exit,
  979 + .cra_u.ablkcipher = {
  980 + .min_keysize = 2*DES_KEY_SIZE,
  981 + .max_keysize = 3*DES_KEY_SIZE,
  982 + .ivsize = DES_BLOCK_SIZE,
  983 + .setkey = atmel_tdes_setkey,
  984 + .encrypt = atmel_tdes_ofb_encrypt,
  985 + .decrypt = atmel_tdes_ofb_decrypt,
  986 + }
  987 +},
  988 +};
  989 +
  990 +static void atmel_tdes_queue_task(unsigned long data)
  991 +{
  992 + struct atmel_tdes_dev *dd = (struct atmel_tdes_dev *)data;
  993 +
  994 + atmel_tdes_handle_queue(dd, NULL);
  995 +}
  996 +
  997 +static void atmel_tdes_done_task(unsigned long data)
  998 +{
  999 + struct atmel_tdes_dev *dd = (struct atmel_tdes_dev *) data;
  1000 + int err;
  1001 +
  1002 + err = atmel_tdes_crypt_dma_stop(dd);
  1003 +
  1004 + err = dd->err ? : err;
  1005 +
  1006 + if (dd->total && !err) {
  1007 + err = atmel_tdes_crypt_dma_start(dd);
  1008 + if (!err)
  1009 + return;
  1010 + }
  1011 +
  1012 + atmel_tdes_finish_req(dd, err);
  1013 + atmel_tdes_handle_queue(dd, NULL);
  1014 +}
  1015 +
  1016 +static irqreturn_t atmel_tdes_irq(int irq, void *dev_id)
  1017 +{
  1018 + struct atmel_tdes_dev *tdes_dd = dev_id;
  1019 + u32 reg;
  1020 +
  1021 + reg = atmel_tdes_read(tdes_dd, TDES_ISR);
  1022 + if (reg & atmel_tdes_read(tdes_dd, TDES_IMR)) {
  1023 + atmel_tdes_write(tdes_dd, TDES_IDR, reg);
  1024 + if (TDES_FLAGS_BUSY & tdes_dd->flags)
  1025 + tasklet_schedule(&tdes_dd->done_task);
  1026 + else
  1027 + dev_warn(tdes_dd->dev, "TDES interrupt when no active requests.\n");
  1028 + return IRQ_HANDLED;
  1029 + }
  1030 +
  1031 + return IRQ_NONE;
  1032 +}
  1033 +
  1034 +static void atmel_tdes_unregister_algs(struct atmel_tdes_dev *dd)
  1035 +{
  1036 + int i;
  1037 +
  1038 + for (i = 0; i < ARRAY_SIZE(tdes_algs); i++)
  1039 + crypto_unregister_alg(&tdes_algs[i]);
  1040 +}
  1041 +
  1042 +static int atmel_tdes_register_algs(struct atmel_tdes_dev *dd)
  1043 +{
  1044 + int err, i, j;
  1045 +
  1046 + for (i = 0; i < ARRAY_SIZE(tdes_algs); i++) {
  1047 + INIT_LIST_HEAD(&tdes_algs[i].cra_list);
  1048 + err = crypto_register_alg(&tdes_algs[i]);
  1049 + if (err)
  1050 + goto err_tdes_algs;
  1051 + }
  1052 +
  1053 + return 0;
  1054 +
  1055 +err_tdes_algs:
  1056 + for (j = 0; j < i; j++)
  1057 + crypto_unregister_alg(&tdes_algs[j]);
  1058 +
  1059 + return err;
  1060 +}
  1061 +
  1062 +static int __devinit atmel_tdes_probe(struct platform_device *pdev)
  1063 +{
  1064 + struct atmel_tdes_dev *tdes_dd;
  1065 + struct device *dev = &pdev->dev;
  1066 + struct resource *tdes_res;
  1067 + unsigned long tdes_phys_size;
  1068 + int err;
  1069 +
  1070 + tdes_dd = kzalloc(sizeof(struct atmel_tdes_dev), GFP_KERNEL);
  1071 + if (tdes_dd == NULL) {
  1072 + dev_err(dev, "unable to alloc data struct.\n");
  1073 + err = -ENOMEM;
  1074 + goto tdes_dd_err;
  1075 + }
  1076 +
  1077 + tdes_dd->dev = dev;
  1078 +
  1079 + platform_set_drvdata(pdev, tdes_dd);
  1080 +
  1081 + INIT_LIST_HEAD(&tdes_dd->list);
  1082 +
  1083 + tasklet_init(&tdes_dd->done_task, atmel_tdes_done_task,
  1084 + (unsigned long)tdes_dd);
  1085 + tasklet_init(&tdes_dd->queue_task, atmel_tdes_queue_task,
  1086 + (unsigned long)tdes_dd);
  1087 +
  1088 + crypto_init_queue(&tdes_dd->queue, ATMEL_TDES_QUEUE_LENGTH);
  1089 +
  1090 + tdes_dd->irq = -1;
  1091 +
  1092 + /* Get the base address */
  1093 + tdes_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  1094 + if (!tdes_res) {
  1095 + dev_err(dev, "no MEM resource info\n");
  1096 + err = -ENODEV;
  1097 + goto res_err;
  1098 + }
  1099 + tdes_dd->phys_base = tdes_res->start;
  1100 + tdes_phys_size = resource_size(tdes_res);
  1101 +
  1102 + /* Get the IRQ */
  1103 + tdes_dd->irq = platform_get_irq(pdev, 0);
  1104 + if (tdes_dd->irq < 0) {
  1105 + dev_err(dev, "no IRQ resource info\n");
  1106 + err = tdes_dd->irq;
  1107 + goto res_err;
  1108 + }
  1109 +
  1110 + err = request_irq(tdes_dd->irq, atmel_tdes_irq, IRQF_SHARED,
  1111 + "atmel-tdes", tdes_dd);
  1112 + if (err) {
  1113 + dev_err(dev, "unable to request tdes irq.\n");
  1114 + goto tdes_irq_err;
  1115 + }
  1116 +
  1117 + /* Initializing the clock */
  1118 + tdes_dd->iclk = clk_get(&pdev->dev, NULL);
  1119 + if (IS_ERR(tdes_dd->iclk)) {
  1120 + dev_err(dev, "clock intialization failed.\n");
  1121 + err = PTR_ERR(tdes_dd->iclk);
  1122 + goto clk_err;
  1123 + }
  1124 +
  1125 + tdes_dd->io_base = ioremap(tdes_dd->phys_base, tdes_phys_size);
  1126 + if (!tdes_dd->io_base) {
  1127 + dev_err(dev, "can't ioremap\n");
  1128 + err = -ENOMEM;
  1129 + goto tdes_io_err;
  1130 + }
  1131 +
  1132 + err = atmel_tdes_dma_init(tdes_dd);
  1133 + if (err)
  1134 + goto err_tdes_dma;
  1135 +
  1136 + spin_lock(&atmel_tdes.lock);
  1137 + list_add_tail(&tdes_dd->list, &atmel_tdes.dev_list);
  1138 + spin_unlock(&atmel_tdes.lock);
  1139 +
  1140 + err = atmel_tdes_register_algs(tdes_dd);
  1141 + if (err)
  1142 + goto err_algs;
  1143 +
  1144 + dev_info(dev, "Atmel DES/TDES\n");
  1145 +
  1146 + return 0;
  1147 +
  1148 +err_algs:
  1149 + spin_lock(&atmel_tdes.lock);
  1150 + list_del(&tdes_dd->list);
  1151 + spin_unlock(&atmel_tdes.lock);
  1152 + atmel_tdes_dma_cleanup(tdes_dd);
  1153 +err_tdes_dma:
  1154 + iounmap(tdes_dd->io_base);
  1155 +tdes_io_err:
  1156 + clk_put(tdes_dd->iclk);
  1157 +clk_err:
  1158 + free_irq(tdes_dd->irq, tdes_dd);
  1159 +tdes_irq_err:
  1160 +res_err:
  1161 + tasklet_kill(&tdes_dd->done_task);
  1162 + tasklet_kill(&tdes_dd->queue_task);
  1163 + kfree(tdes_dd);
  1164 + tdes_dd = NULL;
  1165 +tdes_dd_err:
  1166 + dev_err(dev, "initialization failed.\n");
  1167 +
  1168 + return err;
  1169 +}
  1170 +
  1171 +static int __devexit atmel_tdes_remove(struct platform_device *pdev)
  1172 +{
  1173 + static struct atmel_tdes_dev *tdes_dd;
  1174 +
  1175 + tdes_dd = platform_get_drvdata(pdev);
  1176 + if (!tdes_dd)
  1177 + return -ENODEV;
  1178 + spin_lock(&atmel_tdes.lock);
  1179 + list_del(&tdes_dd->list);
  1180 + spin_unlock(&atmel_tdes.lock);
  1181 +
  1182 + atmel_tdes_unregister_algs(tdes_dd);
  1183 +
  1184 + tasklet_kill(&tdes_dd->done_task);
  1185 + tasklet_kill(&tdes_dd->queue_task);
  1186 +
  1187 + atmel_tdes_dma_cleanup(tdes_dd);
  1188 +
  1189 + iounmap(tdes_dd->io_base);
  1190 +
  1191 + clk_put(tdes_dd->iclk);
  1192 +
  1193 + if (tdes_dd->irq >= 0)
  1194 + free_irq(tdes_dd->irq, tdes_dd);
  1195 +
  1196 + kfree(tdes_dd);
  1197 + tdes_dd = NULL;
  1198 +
  1199 + return 0;
  1200 +}
  1201 +
  1202 +static struct platform_driver atmel_tdes_driver = {
  1203 + .probe = atmel_tdes_probe,
  1204 + .remove = __devexit_p(atmel_tdes_remove),
  1205 + .driver = {
  1206 + .name = "atmel_tdes",
  1207 + .owner = THIS_MODULE,
  1208 + },
  1209 +};
  1210 +
  1211 +module_platform_driver(atmel_tdes_driver);
  1212 +
  1213 +MODULE_DESCRIPTION("Atmel DES/TDES hw acceleration support.");
  1214 +MODULE_LICENSE("GPL v2");
  1215 +MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique");