1bd3c7b5cSNicolas Royer /* 2bd3c7b5cSNicolas Royer * Cryptographic API. 3bd3c7b5cSNicolas Royer * 4bd3c7b5cSNicolas Royer * Support for ATMEL AES HW acceleration. 5bd3c7b5cSNicolas Royer * 6bd3c7b5cSNicolas Royer * Copyright (c) 2012 Eukréa Electromatique - ATMEL 7bd3c7b5cSNicolas Royer * Author: Nicolas Royer <nicolas@eukrea.com> 8bd3c7b5cSNicolas Royer * 9bd3c7b5cSNicolas Royer * This program is free software; you can redistribute it and/or modify 10bd3c7b5cSNicolas Royer * it under the terms of the GNU General Public License version 2 as published 11bd3c7b5cSNicolas Royer * by the Free Software Foundation. 12bd3c7b5cSNicolas Royer * 13bd3c7b5cSNicolas Royer * Some ideas are from omap-aes.c driver. 14bd3c7b5cSNicolas Royer */ 15bd3c7b5cSNicolas Royer 16bd3c7b5cSNicolas Royer 17bd3c7b5cSNicolas Royer #include <linux/kernel.h> 18bd3c7b5cSNicolas Royer #include <linux/module.h> 19bd3c7b5cSNicolas Royer #include <linux/slab.h> 20bd3c7b5cSNicolas Royer #include <linux/err.h> 21bd3c7b5cSNicolas Royer #include <linux/clk.h> 22bd3c7b5cSNicolas Royer #include <linux/io.h> 23bd3c7b5cSNicolas Royer #include <linux/hw_random.h> 24bd3c7b5cSNicolas Royer #include <linux/platform_device.h> 25bd3c7b5cSNicolas Royer 26bd3c7b5cSNicolas Royer #include <linux/device.h> 27bd3c7b5cSNicolas Royer #include <linux/init.h> 28bd3c7b5cSNicolas Royer #include <linux/errno.h> 29bd3c7b5cSNicolas Royer #include <linux/interrupt.h> 30bd3c7b5cSNicolas Royer #include <linux/irq.h> 31bd3c7b5cSNicolas Royer #include <linux/scatterlist.h> 32bd3c7b5cSNicolas Royer #include <linux/dma-mapping.h> 33be943c7dSNicolas Ferre #include <linux/of_device.h> 34bd3c7b5cSNicolas Royer #include <linux/delay.h> 35bd3c7b5cSNicolas Royer #include <linux/crypto.h> 36bd3c7b5cSNicolas Royer #include <crypto/scatterwalk.h> 37bd3c7b5cSNicolas Royer #include <crypto/algapi.h> 38bd3c7b5cSNicolas Royer #include <crypto/aes.h> 39cadc4ab8SNicolas Royer #include <linux/platform_data/crypto-atmel.h> 40be943c7dSNicolas Ferre #include <dt-bindings/dma/at91.h> 41bd3c7b5cSNicolas Royer #include "atmel-aes-regs.h" 42bd3c7b5cSNicolas Royer 4388efd9a9SCyrille Pitchen #define ATMEL_AES_PRIORITY 300 4488efd9a9SCyrille Pitchen 45bbe628edSCyrille Pitchen #define ATMEL_AES_BUFFER_ORDER 2 46bbe628edSCyrille Pitchen #define ATMEL_AES_BUFFER_SIZE (PAGE_SIZE << ATMEL_AES_BUFFER_ORDER) 47bbe628edSCyrille Pitchen 48bd3c7b5cSNicolas Royer #define CFB8_BLOCK_SIZE 1 49bd3c7b5cSNicolas Royer #define CFB16_BLOCK_SIZE 2 50bd3c7b5cSNicolas Royer #define CFB32_BLOCK_SIZE 4 51bd3c7b5cSNicolas Royer #define CFB64_BLOCK_SIZE 8 52bd3c7b5cSNicolas Royer 53bbe628edSCyrille Pitchen #define SIZE_IN_WORDS(x) ((x) >> 2) 54bbe628edSCyrille Pitchen 55bd3c7b5cSNicolas Royer /* AES flags */ 5677dacf5fSCyrille Pitchen /* Reserve bits [18:16] [14:12] [0] for mode (same as for AES_MR) */ 5777dacf5fSCyrille Pitchen #define AES_FLAGS_ENCRYPT AES_MR_CYPHER_ENC 5877dacf5fSCyrille Pitchen #define AES_FLAGS_OPMODE_MASK (AES_MR_OPMOD_MASK | AES_MR_CFBS_MASK) 5977dacf5fSCyrille Pitchen #define AES_FLAGS_ECB AES_MR_OPMOD_ECB 6077dacf5fSCyrille Pitchen #define AES_FLAGS_CBC AES_MR_OPMOD_CBC 6177dacf5fSCyrille Pitchen #define AES_FLAGS_OFB AES_MR_OPMOD_OFB 6277dacf5fSCyrille Pitchen #define AES_FLAGS_CFB128 (AES_MR_OPMOD_CFB | AES_MR_CFBS_128b) 6377dacf5fSCyrille Pitchen #define AES_FLAGS_CFB64 (AES_MR_OPMOD_CFB | AES_MR_CFBS_64b) 6477dacf5fSCyrille Pitchen #define AES_FLAGS_CFB32 (AES_MR_OPMOD_CFB | AES_MR_CFBS_32b) 6577dacf5fSCyrille Pitchen #define AES_FLAGS_CFB16 (AES_MR_OPMOD_CFB | AES_MR_CFBS_16b) 6677dacf5fSCyrille Pitchen #define AES_FLAGS_CFB8 (AES_MR_OPMOD_CFB | AES_MR_CFBS_8b) 6777dacf5fSCyrille Pitchen #define AES_FLAGS_CTR AES_MR_OPMOD_CTR 68bd3c7b5cSNicolas Royer 6977dacf5fSCyrille Pitchen #define AES_FLAGS_MODE_MASK (AES_FLAGS_OPMODE_MASK | \ 7077dacf5fSCyrille Pitchen AES_FLAGS_ENCRYPT) 7177dacf5fSCyrille Pitchen 7277dacf5fSCyrille Pitchen #define AES_FLAGS_INIT BIT(2) 7377dacf5fSCyrille Pitchen #define AES_FLAGS_BUSY BIT(3) 7477dacf5fSCyrille Pitchen 7577dacf5fSCyrille Pitchen #define AES_FLAGS_PERSISTENT (AES_FLAGS_INIT | AES_FLAGS_BUSY) 76bd3c7b5cSNicolas Royer 77cadc4ab8SNicolas Royer #define ATMEL_AES_QUEUE_LENGTH 50 78bd3c7b5cSNicolas Royer 79bd3c7b5cSNicolas Royer #define ATMEL_AES_DMA_THRESHOLD 16 80bd3c7b5cSNicolas Royer 81bd3c7b5cSNicolas Royer 82cadc4ab8SNicolas Royer struct atmel_aes_caps { 83cadc4ab8SNicolas Royer bool has_dualbuff; 84cadc4ab8SNicolas Royer bool has_cfb64; 85cadc4ab8SNicolas Royer u32 max_burst_size; 86cadc4ab8SNicolas Royer }; 87cadc4ab8SNicolas Royer 88bd3c7b5cSNicolas Royer struct atmel_aes_dev; 89bd3c7b5cSNicolas Royer 90ccbf7298SCyrille Pitchen 91ccbf7298SCyrille Pitchen typedef int (*atmel_aes_fn_t)(struct atmel_aes_dev *); 92ccbf7298SCyrille Pitchen 93ccbf7298SCyrille Pitchen 94ccbf7298SCyrille Pitchen struct atmel_aes_base_ctx { 95bd3c7b5cSNicolas Royer struct atmel_aes_dev *dd; 96ccbf7298SCyrille Pitchen atmel_aes_fn_t start; 97bd3c7b5cSNicolas Royer 98bd3c7b5cSNicolas Royer int keylen; 99bd3c7b5cSNicolas Royer u32 key[AES_KEYSIZE_256 / sizeof(u32)]; 100cadc4ab8SNicolas Royer 101cadc4ab8SNicolas Royer u16 block_size; 102bd3c7b5cSNicolas Royer }; 103bd3c7b5cSNicolas Royer 104ccbf7298SCyrille Pitchen struct atmel_aes_ctx { 105ccbf7298SCyrille Pitchen struct atmel_aes_base_ctx base; 106ccbf7298SCyrille Pitchen }; 107ccbf7298SCyrille Pitchen 108bd3c7b5cSNicolas Royer struct atmel_aes_reqctx { 109bd3c7b5cSNicolas Royer unsigned long mode; 110bd3c7b5cSNicolas Royer }; 111bd3c7b5cSNicolas Royer 112bd3c7b5cSNicolas Royer struct atmel_aes_dma { 113bd3c7b5cSNicolas Royer struct dma_chan *chan; 114bbe628edSCyrille Pitchen struct scatterlist *sg; 115bbe628edSCyrille Pitchen int nents; 116bbe628edSCyrille Pitchen unsigned int remainder; 117bbe628edSCyrille Pitchen unsigned int sg_len; 118bd3c7b5cSNicolas Royer }; 119bd3c7b5cSNicolas Royer 120bd3c7b5cSNicolas Royer struct atmel_aes_dev { 121bd3c7b5cSNicolas Royer struct list_head list; 122bd3c7b5cSNicolas Royer unsigned long phys_base; 123bd3c7b5cSNicolas Royer void __iomem *io_base; 124bd3c7b5cSNicolas Royer 125ccbf7298SCyrille Pitchen struct crypto_async_request *areq; 126ccbf7298SCyrille Pitchen struct atmel_aes_base_ctx *ctx; 127ccbf7298SCyrille Pitchen 12810f12c1bSCyrille Pitchen bool is_async; 12910f12c1bSCyrille Pitchen atmel_aes_fn_t resume; 130bbe628edSCyrille Pitchen atmel_aes_fn_t cpu_transfer_complete; 13110f12c1bSCyrille Pitchen 132bd3c7b5cSNicolas Royer struct device *dev; 133bd3c7b5cSNicolas Royer struct clk *iclk; 134bd3c7b5cSNicolas Royer int irq; 135bd3c7b5cSNicolas Royer 136bd3c7b5cSNicolas Royer unsigned long flags; 137bd3c7b5cSNicolas Royer 138bd3c7b5cSNicolas Royer spinlock_t lock; 139bd3c7b5cSNicolas Royer struct crypto_queue queue; 140bd3c7b5cSNicolas Royer 141bd3c7b5cSNicolas Royer struct tasklet_struct done_task; 142bd3c7b5cSNicolas Royer struct tasklet_struct queue_task; 143bd3c7b5cSNicolas Royer 144bd3c7b5cSNicolas Royer size_t total; 145bbe628edSCyrille Pitchen size_t datalen; 146bbe628edSCyrille Pitchen u32 *data; 147bd3c7b5cSNicolas Royer 148bbe628edSCyrille Pitchen struct atmel_aes_dma src; 149bbe628edSCyrille Pitchen struct atmel_aes_dma dst; 150bd3c7b5cSNicolas Royer 151cadc4ab8SNicolas Royer size_t buflen; 152bbe628edSCyrille Pitchen void *buf; 153bbe628edSCyrille Pitchen struct scatterlist aligned_sg; 154bbe628edSCyrille Pitchen struct scatterlist *real_dst; 155bd3c7b5cSNicolas Royer 156cadc4ab8SNicolas Royer struct atmel_aes_caps caps; 157cadc4ab8SNicolas Royer 158bd3c7b5cSNicolas Royer u32 hw_version; 159bd3c7b5cSNicolas Royer }; 160bd3c7b5cSNicolas Royer 161bd3c7b5cSNicolas Royer struct atmel_aes_drv { 162bd3c7b5cSNicolas Royer struct list_head dev_list; 163bd3c7b5cSNicolas Royer spinlock_t lock; 164bd3c7b5cSNicolas Royer }; 165bd3c7b5cSNicolas Royer 166bd3c7b5cSNicolas Royer static struct atmel_aes_drv atmel_aes = { 167bd3c7b5cSNicolas Royer .dev_list = LIST_HEAD_INIT(atmel_aes.dev_list), 168bd3c7b5cSNicolas Royer .lock = __SPIN_LOCK_UNLOCKED(atmel_aes.lock), 169bd3c7b5cSNicolas Royer }; 170bd3c7b5cSNicolas Royer 171cadc4ab8SNicolas Royer 172bd3c7b5cSNicolas Royer static inline u32 atmel_aes_read(struct atmel_aes_dev *dd, u32 offset) 173bd3c7b5cSNicolas Royer { 174bd3c7b5cSNicolas Royer return readl_relaxed(dd->io_base + offset); 175bd3c7b5cSNicolas Royer } 176bd3c7b5cSNicolas Royer 177bd3c7b5cSNicolas Royer static inline void atmel_aes_write(struct atmel_aes_dev *dd, 178bd3c7b5cSNicolas Royer u32 offset, u32 value) 179bd3c7b5cSNicolas Royer { 180bd3c7b5cSNicolas Royer writel_relaxed(value, dd->io_base + offset); 181bd3c7b5cSNicolas Royer } 182bd3c7b5cSNicolas Royer 183bd3c7b5cSNicolas Royer static void atmel_aes_read_n(struct atmel_aes_dev *dd, u32 offset, 184bd3c7b5cSNicolas Royer u32 *value, int count) 185bd3c7b5cSNicolas Royer { 186bd3c7b5cSNicolas Royer for (; count--; value++, offset += 4) 187bd3c7b5cSNicolas Royer *value = atmel_aes_read(dd, offset); 188bd3c7b5cSNicolas Royer } 189bd3c7b5cSNicolas Royer 190bd3c7b5cSNicolas Royer static void atmel_aes_write_n(struct atmel_aes_dev *dd, u32 offset, 191c0b28d8cSCyrille Pitchen const u32 *value, int count) 192bd3c7b5cSNicolas Royer { 193bd3c7b5cSNicolas Royer for (; count--; value++, offset += 4) 194bd3c7b5cSNicolas Royer atmel_aes_write(dd, offset, *value); 195bd3c7b5cSNicolas Royer } 196bd3c7b5cSNicolas Royer 197bbe628edSCyrille Pitchen static inline void atmel_aes_read_block(struct atmel_aes_dev *dd, u32 offset, 198bbe628edSCyrille Pitchen u32 *value) 199bbe628edSCyrille Pitchen { 200bbe628edSCyrille Pitchen atmel_aes_read_n(dd, offset, value, SIZE_IN_WORDS(AES_BLOCK_SIZE)); 201bbe628edSCyrille Pitchen } 202bbe628edSCyrille Pitchen 203bbe628edSCyrille Pitchen static inline void atmel_aes_write_block(struct atmel_aes_dev *dd, u32 offset, 204bbe628edSCyrille Pitchen const u32 *value) 205bbe628edSCyrille Pitchen { 206bbe628edSCyrille Pitchen atmel_aes_write_n(dd, offset, value, SIZE_IN_WORDS(AES_BLOCK_SIZE)); 207bbe628edSCyrille Pitchen } 208bbe628edSCyrille Pitchen 209bbe628edSCyrille Pitchen static inline int atmel_aes_wait_for_data_ready(struct atmel_aes_dev *dd, 210bbe628edSCyrille Pitchen atmel_aes_fn_t resume) 211bbe628edSCyrille Pitchen { 212bbe628edSCyrille Pitchen u32 isr = atmel_aes_read(dd, AES_ISR); 213bbe628edSCyrille Pitchen 214bbe628edSCyrille Pitchen if (unlikely(isr & AES_INT_DATARDY)) 215bbe628edSCyrille Pitchen return resume(dd); 216bbe628edSCyrille Pitchen 217bbe628edSCyrille Pitchen dd->resume = resume; 218bbe628edSCyrille Pitchen atmel_aes_write(dd, AES_IER, AES_INT_DATARDY); 219bbe628edSCyrille Pitchen return -EINPROGRESS; 220bbe628edSCyrille Pitchen } 221bbe628edSCyrille Pitchen 222bbe628edSCyrille Pitchen static inline size_t atmel_aes_padlen(size_t len, size_t block_size) 223bbe628edSCyrille Pitchen { 224bbe628edSCyrille Pitchen len &= block_size - 1; 225bbe628edSCyrille Pitchen return len ? block_size - len : 0; 226bbe628edSCyrille Pitchen } 227bbe628edSCyrille Pitchen 228ccbf7298SCyrille Pitchen static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_base_ctx *ctx) 229bd3c7b5cSNicolas Royer { 230bd3c7b5cSNicolas Royer struct atmel_aes_dev *aes_dd = NULL; 231bd3c7b5cSNicolas Royer struct atmel_aes_dev *tmp; 232bd3c7b5cSNicolas Royer 233bd3c7b5cSNicolas Royer spin_lock_bh(&atmel_aes.lock); 234bd3c7b5cSNicolas Royer if (!ctx->dd) { 235bd3c7b5cSNicolas Royer list_for_each_entry(tmp, &atmel_aes.dev_list, list) { 236bd3c7b5cSNicolas Royer aes_dd = tmp; 237bd3c7b5cSNicolas Royer break; 238bd3c7b5cSNicolas Royer } 239bd3c7b5cSNicolas Royer ctx->dd = aes_dd; 240bd3c7b5cSNicolas Royer } else { 241bd3c7b5cSNicolas Royer aes_dd = ctx->dd; 242bd3c7b5cSNicolas Royer } 243bd3c7b5cSNicolas Royer 244bd3c7b5cSNicolas Royer spin_unlock_bh(&atmel_aes.lock); 245bd3c7b5cSNicolas Royer 246bd3c7b5cSNicolas Royer return aes_dd; 247bd3c7b5cSNicolas Royer } 248bd3c7b5cSNicolas Royer 249bd3c7b5cSNicolas Royer static int atmel_aes_hw_init(struct atmel_aes_dev *dd) 250bd3c7b5cSNicolas Royer { 2519d83d299SLABBE Corentin int err; 2529d83d299SLABBE Corentin 2539d83d299SLABBE Corentin err = clk_prepare_enable(dd->iclk); 2549d83d299SLABBE Corentin if (err) 2559d83d299SLABBE Corentin return err; 256bd3c7b5cSNicolas Royer 257bd3c7b5cSNicolas Royer if (!(dd->flags & AES_FLAGS_INIT)) { 258bd3c7b5cSNicolas Royer atmel_aes_write(dd, AES_CR, AES_CR_SWRST); 259cadc4ab8SNicolas Royer atmel_aes_write(dd, AES_MR, 0xE << AES_MR_CKEY_OFFSET); 260bd3c7b5cSNicolas Royer dd->flags |= AES_FLAGS_INIT; 261bd3c7b5cSNicolas Royer } 262bd3c7b5cSNicolas Royer 263bd3c7b5cSNicolas Royer return 0; 264bd3c7b5cSNicolas Royer } 265bd3c7b5cSNicolas Royer 266cadc4ab8SNicolas Royer static inline unsigned int atmel_aes_get_version(struct atmel_aes_dev *dd) 267cadc4ab8SNicolas Royer { 268cadc4ab8SNicolas Royer return atmel_aes_read(dd, AES_HW_VERSION) & 0x00000fff; 269cadc4ab8SNicolas Royer } 270cadc4ab8SNicolas Royer 271aab0a39bSCyrille Pitchen static int atmel_aes_hw_version_init(struct atmel_aes_dev *dd) 272bd3c7b5cSNicolas Royer { 273aab0a39bSCyrille Pitchen int err; 274aab0a39bSCyrille Pitchen 275aab0a39bSCyrille Pitchen err = atmel_aes_hw_init(dd); 276aab0a39bSCyrille Pitchen if (err) 277aab0a39bSCyrille Pitchen return err; 278bd3c7b5cSNicolas Royer 279cadc4ab8SNicolas Royer dd->hw_version = atmel_aes_get_version(dd); 280cadc4ab8SNicolas Royer 281aab0a39bSCyrille Pitchen dev_info(dd->dev, "version: 0x%x\n", dd->hw_version); 282bd3c7b5cSNicolas Royer 283bd3c7b5cSNicolas Royer clk_disable_unprepare(dd->iclk); 284aab0a39bSCyrille Pitchen return 0; 285bd3c7b5cSNicolas Royer } 286bd3c7b5cSNicolas Royer 28777dacf5fSCyrille Pitchen static inline void atmel_aes_set_mode(struct atmel_aes_dev *dd, 28877dacf5fSCyrille Pitchen const struct atmel_aes_reqctx *rctx) 28977dacf5fSCyrille Pitchen { 29077dacf5fSCyrille Pitchen /* Clear all but persistent flags and set request flags. */ 29177dacf5fSCyrille Pitchen dd->flags = (dd->flags & AES_FLAGS_PERSISTENT) | rctx->mode; 29277dacf5fSCyrille Pitchen } 29377dacf5fSCyrille Pitchen 29410f12c1bSCyrille Pitchen static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err) 295bd3c7b5cSNicolas Royer { 296bd3c7b5cSNicolas Royer clk_disable_unprepare(dd->iclk); 297bd3c7b5cSNicolas Royer dd->flags &= ~AES_FLAGS_BUSY; 298bd3c7b5cSNicolas Royer 29910f12c1bSCyrille Pitchen if (dd->is_async) 30010f12c1bSCyrille Pitchen dd->areq->complete(dd->areq, err); 30110f12c1bSCyrille Pitchen 30210f12c1bSCyrille Pitchen tasklet_schedule(&dd->queue_task); 30310f12c1bSCyrille Pitchen 30410f12c1bSCyrille Pitchen return err; 305bd3c7b5cSNicolas Royer } 306bd3c7b5cSNicolas Royer 307bd3c7b5cSNicolas Royer 308bbe628edSCyrille Pitchen /* CPU transfer */ 309bbe628edSCyrille Pitchen 310bbe628edSCyrille Pitchen static int atmel_aes_cpu_transfer(struct atmel_aes_dev *dd) 311bbe628edSCyrille Pitchen { 312bbe628edSCyrille Pitchen int err = 0; 313bbe628edSCyrille Pitchen u32 isr; 314bbe628edSCyrille Pitchen 315bbe628edSCyrille Pitchen for (;;) { 316bbe628edSCyrille Pitchen atmel_aes_read_block(dd, AES_ODATAR(0), dd->data); 317bbe628edSCyrille Pitchen dd->data += 4; 318bbe628edSCyrille Pitchen dd->datalen -= AES_BLOCK_SIZE; 319bbe628edSCyrille Pitchen 320bbe628edSCyrille Pitchen if (dd->datalen < AES_BLOCK_SIZE) 321bbe628edSCyrille Pitchen break; 322bbe628edSCyrille Pitchen 323bbe628edSCyrille Pitchen atmel_aes_write_block(dd, AES_IDATAR(0), dd->data); 324bbe628edSCyrille Pitchen 325bbe628edSCyrille Pitchen isr = atmel_aes_read(dd, AES_ISR); 326bbe628edSCyrille Pitchen if (!(isr & AES_INT_DATARDY)) { 327bbe628edSCyrille Pitchen dd->resume = atmel_aes_cpu_transfer; 328bbe628edSCyrille Pitchen atmel_aes_write(dd, AES_IER, AES_INT_DATARDY); 329bbe628edSCyrille Pitchen return -EINPROGRESS; 330bbe628edSCyrille Pitchen } 331bd3c7b5cSNicolas Royer } 332bd3c7b5cSNicolas Royer 333bbe628edSCyrille Pitchen if (!sg_copy_from_buffer(dd->real_dst, sg_nents(dd->real_dst), 334bbe628edSCyrille Pitchen dd->buf, dd->total)) 335bbe628edSCyrille Pitchen err = -EINVAL; 336bbe628edSCyrille Pitchen 337bbe628edSCyrille Pitchen if (err) 338bbe628edSCyrille Pitchen return atmel_aes_complete(dd, err); 339bbe628edSCyrille Pitchen 340bbe628edSCyrille Pitchen return dd->cpu_transfer_complete(dd); 341bbe628edSCyrille Pitchen } 342bbe628edSCyrille Pitchen 343bbe628edSCyrille Pitchen static int atmel_aes_cpu_start(struct atmel_aes_dev *dd, 344bbe628edSCyrille Pitchen struct scatterlist *src, 345bbe628edSCyrille Pitchen struct scatterlist *dst, 346bbe628edSCyrille Pitchen size_t len, 347bbe628edSCyrille Pitchen atmel_aes_fn_t resume) 348bd3c7b5cSNicolas Royer { 349bbe628edSCyrille Pitchen size_t padlen = atmel_aes_padlen(len, AES_BLOCK_SIZE); 350bbe628edSCyrille Pitchen 351bbe628edSCyrille Pitchen if (unlikely(len == 0)) 352bbe628edSCyrille Pitchen return -EINVAL; 353bbe628edSCyrille Pitchen 354bbe628edSCyrille Pitchen sg_copy_to_buffer(src, sg_nents(src), dd->buf, len); 355bbe628edSCyrille Pitchen 356bbe628edSCyrille Pitchen dd->total = len; 357bbe628edSCyrille Pitchen dd->real_dst = dst; 358bbe628edSCyrille Pitchen dd->cpu_transfer_complete = resume; 359bbe628edSCyrille Pitchen dd->datalen = len + padlen; 360bbe628edSCyrille Pitchen dd->data = (u32 *)dd->buf; 361bbe628edSCyrille Pitchen atmel_aes_write_block(dd, AES_IDATAR(0), dd->data); 362bbe628edSCyrille Pitchen return atmel_aes_wait_for_data_ready(dd, atmel_aes_cpu_transfer); 363bbe628edSCyrille Pitchen } 364bbe628edSCyrille Pitchen 365bbe628edSCyrille Pitchen 366bbe628edSCyrille Pitchen /* DMA transfer */ 367bbe628edSCyrille Pitchen 368bbe628edSCyrille Pitchen static void atmel_aes_dma_callback(void *data); 369bbe628edSCyrille Pitchen 370bbe628edSCyrille Pitchen static bool atmel_aes_check_aligned(struct atmel_aes_dev *dd, 371bbe628edSCyrille Pitchen struct scatterlist *sg, 372bbe628edSCyrille Pitchen size_t len, 373bbe628edSCyrille Pitchen struct atmel_aes_dma *dma) 374bbe628edSCyrille Pitchen { 375bbe628edSCyrille Pitchen int nents; 376bbe628edSCyrille Pitchen 377bbe628edSCyrille Pitchen if (!IS_ALIGNED(len, dd->ctx->block_size)) 378bbe628edSCyrille Pitchen return false; 379bbe628edSCyrille Pitchen 380bbe628edSCyrille Pitchen for (nents = 0; sg; sg = sg_next(sg), ++nents) { 381bbe628edSCyrille Pitchen if (!IS_ALIGNED(sg->offset, sizeof(u32))) 382bbe628edSCyrille Pitchen return false; 383bbe628edSCyrille Pitchen 384bbe628edSCyrille Pitchen if (len <= sg->length) { 385bbe628edSCyrille Pitchen if (!IS_ALIGNED(len, dd->ctx->block_size)) 386bbe628edSCyrille Pitchen return false; 387bbe628edSCyrille Pitchen 388bbe628edSCyrille Pitchen dma->nents = nents+1; 389bbe628edSCyrille Pitchen dma->remainder = sg->length - len; 390bbe628edSCyrille Pitchen sg->length = len; 391bbe628edSCyrille Pitchen return true; 392bbe628edSCyrille Pitchen } 393bbe628edSCyrille Pitchen 394bbe628edSCyrille Pitchen if (!IS_ALIGNED(sg->length, dd->ctx->block_size)) 395bbe628edSCyrille Pitchen return false; 396bbe628edSCyrille Pitchen 397bbe628edSCyrille Pitchen len -= sg->length; 398bbe628edSCyrille Pitchen } 399bbe628edSCyrille Pitchen 400bbe628edSCyrille Pitchen return false; 401bbe628edSCyrille Pitchen } 402bbe628edSCyrille Pitchen 403bbe628edSCyrille Pitchen static inline void atmel_aes_restore_sg(const struct atmel_aes_dma *dma) 404bbe628edSCyrille Pitchen { 405bbe628edSCyrille Pitchen struct scatterlist *sg = dma->sg; 406bbe628edSCyrille Pitchen int nents = dma->nents; 407bbe628edSCyrille Pitchen 408bbe628edSCyrille Pitchen if (!dma->remainder) 409bbe628edSCyrille Pitchen return; 410bbe628edSCyrille Pitchen 411bbe628edSCyrille Pitchen while (--nents > 0 && sg) 412bbe628edSCyrille Pitchen sg = sg_next(sg); 413bbe628edSCyrille Pitchen 414bbe628edSCyrille Pitchen if (!sg) 415bbe628edSCyrille Pitchen return; 416bbe628edSCyrille Pitchen 417bbe628edSCyrille Pitchen sg->length += dma->remainder; 418bbe628edSCyrille Pitchen } 419bbe628edSCyrille Pitchen 420bbe628edSCyrille Pitchen static int atmel_aes_map(struct atmel_aes_dev *dd, 421bbe628edSCyrille Pitchen struct scatterlist *src, 422bbe628edSCyrille Pitchen struct scatterlist *dst, 423bbe628edSCyrille Pitchen size_t len) 424bbe628edSCyrille Pitchen { 425bbe628edSCyrille Pitchen bool src_aligned, dst_aligned; 426bbe628edSCyrille Pitchen size_t padlen; 427bbe628edSCyrille Pitchen 428bbe628edSCyrille Pitchen dd->total = len; 429bbe628edSCyrille Pitchen dd->src.sg = src; 430bbe628edSCyrille Pitchen dd->dst.sg = dst; 431bbe628edSCyrille Pitchen dd->real_dst = dst; 432bbe628edSCyrille Pitchen 433bbe628edSCyrille Pitchen src_aligned = atmel_aes_check_aligned(dd, src, len, &dd->src); 434bbe628edSCyrille Pitchen if (src == dst) 435bbe628edSCyrille Pitchen dst_aligned = src_aligned; 436bbe628edSCyrille Pitchen else 437bbe628edSCyrille Pitchen dst_aligned = atmel_aes_check_aligned(dd, dst, len, &dd->dst); 438bbe628edSCyrille Pitchen if (!src_aligned || !dst_aligned) { 439bbe628edSCyrille Pitchen padlen = atmel_aes_padlen(len, dd->ctx->block_size); 440bbe628edSCyrille Pitchen 441bbe628edSCyrille Pitchen if (dd->buflen < len + padlen) 442bbe628edSCyrille Pitchen return -ENOMEM; 443bbe628edSCyrille Pitchen 444bbe628edSCyrille Pitchen if (!src_aligned) { 445bbe628edSCyrille Pitchen sg_copy_to_buffer(src, sg_nents(src), dd->buf, len); 446bbe628edSCyrille Pitchen dd->src.sg = &dd->aligned_sg; 447bbe628edSCyrille Pitchen dd->src.nents = 1; 448bbe628edSCyrille Pitchen dd->src.remainder = 0; 449bbe628edSCyrille Pitchen } 450bbe628edSCyrille Pitchen 451bbe628edSCyrille Pitchen if (!dst_aligned) { 452bbe628edSCyrille Pitchen dd->dst.sg = &dd->aligned_sg; 453bbe628edSCyrille Pitchen dd->dst.nents = 1; 454bbe628edSCyrille Pitchen dd->dst.remainder = 0; 455bbe628edSCyrille Pitchen } 456bbe628edSCyrille Pitchen 457bbe628edSCyrille Pitchen sg_init_table(&dd->aligned_sg, 1); 458bbe628edSCyrille Pitchen sg_set_buf(&dd->aligned_sg, dd->buf, len + padlen); 459bbe628edSCyrille Pitchen } 460bbe628edSCyrille Pitchen 461bbe628edSCyrille Pitchen if (dd->src.sg == dd->dst.sg) { 462bbe628edSCyrille Pitchen dd->src.sg_len = dma_map_sg(dd->dev, dd->src.sg, dd->src.nents, 463bbe628edSCyrille Pitchen DMA_BIDIRECTIONAL); 464bbe628edSCyrille Pitchen dd->dst.sg_len = dd->src.sg_len; 465bbe628edSCyrille Pitchen if (!dd->src.sg_len) 466bbe628edSCyrille Pitchen return -EFAULT; 467bbe628edSCyrille Pitchen } else { 468bbe628edSCyrille Pitchen dd->src.sg_len = dma_map_sg(dd->dev, dd->src.sg, dd->src.nents, 469bbe628edSCyrille Pitchen DMA_TO_DEVICE); 470bbe628edSCyrille Pitchen if (!dd->src.sg_len) 471bbe628edSCyrille Pitchen return -EFAULT; 472bbe628edSCyrille Pitchen 473bbe628edSCyrille Pitchen dd->dst.sg_len = dma_map_sg(dd->dev, dd->dst.sg, dd->dst.nents, 474bbe628edSCyrille Pitchen DMA_FROM_DEVICE); 475bbe628edSCyrille Pitchen if (!dd->dst.sg_len) { 476bbe628edSCyrille Pitchen dma_unmap_sg(dd->dev, dd->src.sg, dd->src.nents, 477bbe628edSCyrille Pitchen DMA_TO_DEVICE); 478bbe628edSCyrille Pitchen return -EFAULT; 479bbe628edSCyrille Pitchen } 480bbe628edSCyrille Pitchen } 481bbe628edSCyrille Pitchen 482bbe628edSCyrille Pitchen return 0; 483bbe628edSCyrille Pitchen } 484bbe628edSCyrille Pitchen 485bbe628edSCyrille Pitchen static void atmel_aes_unmap(struct atmel_aes_dev *dd) 486bbe628edSCyrille Pitchen { 487bbe628edSCyrille Pitchen if (dd->src.sg == dd->dst.sg) { 488bbe628edSCyrille Pitchen dma_unmap_sg(dd->dev, dd->src.sg, dd->src.nents, 489bbe628edSCyrille Pitchen DMA_BIDIRECTIONAL); 490bbe628edSCyrille Pitchen 491bbe628edSCyrille Pitchen if (dd->src.sg != &dd->aligned_sg) 492bbe628edSCyrille Pitchen atmel_aes_restore_sg(&dd->src); 493bbe628edSCyrille Pitchen } else { 494bbe628edSCyrille Pitchen dma_unmap_sg(dd->dev, dd->dst.sg, dd->dst.nents, 495bbe628edSCyrille Pitchen DMA_FROM_DEVICE); 496bbe628edSCyrille Pitchen 497bbe628edSCyrille Pitchen if (dd->dst.sg != &dd->aligned_sg) 498bbe628edSCyrille Pitchen atmel_aes_restore_sg(&dd->dst); 499bbe628edSCyrille Pitchen 500bbe628edSCyrille Pitchen dma_unmap_sg(dd->dev, dd->src.sg, dd->src.nents, 501bbe628edSCyrille Pitchen DMA_TO_DEVICE); 502bbe628edSCyrille Pitchen 503bbe628edSCyrille Pitchen if (dd->src.sg != &dd->aligned_sg) 504bbe628edSCyrille Pitchen atmel_aes_restore_sg(&dd->src); 505bbe628edSCyrille Pitchen } 506bbe628edSCyrille Pitchen 507bbe628edSCyrille Pitchen if (dd->dst.sg == &dd->aligned_sg) 508bbe628edSCyrille Pitchen sg_copy_from_buffer(dd->real_dst, sg_nents(dd->real_dst), 509bbe628edSCyrille Pitchen dd->buf, dd->total); 510bbe628edSCyrille Pitchen } 511bbe628edSCyrille Pitchen 512bbe628edSCyrille Pitchen static int atmel_aes_dma_transfer_start(struct atmel_aes_dev *dd, 513bbe628edSCyrille Pitchen enum dma_slave_buswidth addr_width, 514bbe628edSCyrille Pitchen enum dma_transfer_direction dir, 515bbe628edSCyrille Pitchen u32 maxburst) 516bbe628edSCyrille Pitchen { 517bbe628edSCyrille Pitchen struct dma_async_tx_descriptor *desc; 518bbe628edSCyrille Pitchen struct dma_slave_config config; 519bbe628edSCyrille Pitchen dma_async_tx_callback callback; 520bbe628edSCyrille Pitchen struct atmel_aes_dma *dma; 521bbe628edSCyrille Pitchen int err; 522bbe628edSCyrille Pitchen 523bbe628edSCyrille Pitchen memset(&config, 0, sizeof(config)); 524bbe628edSCyrille Pitchen config.direction = dir; 525bbe628edSCyrille Pitchen config.src_addr_width = addr_width; 526bbe628edSCyrille Pitchen config.dst_addr_width = addr_width; 527bbe628edSCyrille Pitchen config.src_maxburst = maxburst; 528bbe628edSCyrille Pitchen config.dst_maxburst = maxburst; 529bbe628edSCyrille Pitchen 530bbe628edSCyrille Pitchen switch (dir) { 531bbe628edSCyrille Pitchen case DMA_MEM_TO_DEV: 532bbe628edSCyrille Pitchen dma = &dd->src; 533bbe628edSCyrille Pitchen callback = NULL; 534bbe628edSCyrille Pitchen config.dst_addr = dd->phys_base + AES_IDATAR(0); 535bbe628edSCyrille Pitchen break; 536bbe628edSCyrille Pitchen 537bbe628edSCyrille Pitchen case DMA_DEV_TO_MEM: 538bbe628edSCyrille Pitchen dma = &dd->dst; 539bbe628edSCyrille Pitchen callback = atmel_aes_dma_callback; 540bbe628edSCyrille Pitchen config.src_addr = dd->phys_base + AES_ODATAR(0); 541bbe628edSCyrille Pitchen break; 542bbe628edSCyrille Pitchen 543bbe628edSCyrille Pitchen default: 544bbe628edSCyrille Pitchen return -EINVAL; 545bbe628edSCyrille Pitchen } 546bbe628edSCyrille Pitchen 547bbe628edSCyrille Pitchen err = dmaengine_slave_config(dma->chan, &config); 548bbe628edSCyrille Pitchen if (err) 549bbe628edSCyrille Pitchen return err; 550bbe628edSCyrille Pitchen 551bbe628edSCyrille Pitchen desc = dmaengine_prep_slave_sg(dma->chan, dma->sg, dma->sg_len, dir, 552bbe628edSCyrille Pitchen DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 553bbe628edSCyrille Pitchen if (!desc) 554bbe628edSCyrille Pitchen return -ENOMEM; 555bbe628edSCyrille Pitchen 556bbe628edSCyrille Pitchen desc->callback = callback; 557bbe628edSCyrille Pitchen desc->callback_param = dd; 558bbe628edSCyrille Pitchen dmaengine_submit(desc); 559bbe628edSCyrille Pitchen dma_async_issue_pending(dma->chan); 560bbe628edSCyrille Pitchen 561bbe628edSCyrille Pitchen return 0; 562bbe628edSCyrille Pitchen } 563bbe628edSCyrille Pitchen 564bbe628edSCyrille Pitchen static void atmel_aes_dma_transfer_stop(struct atmel_aes_dev *dd, 565bbe628edSCyrille Pitchen enum dma_transfer_direction dir) 566bbe628edSCyrille Pitchen { 567bbe628edSCyrille Pitchen struct atmel_aes_dma *dma; 568bbe628edSCyrille Pitchen 569bbe628edSCyrille Pitchen switch (dir) { 570bbe628edSCyrille Pitchen case DMA_MEM_TO_DEV: 571bbe628edSCyrille Pitchen dma = &dd->src; 572bbe628edSCyrille Pitchen break; 573bbe628edSCyrille Pitchen 574bbe628edSCyrille Pitchen case DMA_DEV_TO_MEM: 575bbe628edSCyrille Pitchen dma = &dd->dst; 576bbe628edSCyrille Pitchen break; 577bbe628edSCyrille Pitchen 578bbe628edSCyrille Pitchen default: 579bbe628edSCyrille Pitchen return; 580bbe628edSCyrille Pitchen } 581bbe628edSCyrille Pitchen 582bbe628edSCyrille Pitchen dmaengine_terminate_all(dma->chan); 583bbe628edSCyrille Pitchen } 584bbe628edSCyrille Pitchen 585bbe628edSCyrille Pitchen static int atmel_aes_dma_start(struct atmel_aes_dev *dd, 586bbe628edSCyrille Pitchen struct scatterlist *src, 587bbe628edSCyrille Pitchen struct scatterlist *dst, 588bbe628edSCyrille Pitchen size_t len, 589bbe628edSCyrille Pitchen atmel_aes_fn_t resume) 590bbe628edSCyrille Pitchen { 59177dacf5fSCyrille Pitchen enum dma_slave_buswidth addr_width; 59277dacf5fSCyrille Pitchen u32 maxburst; 593bbe628edSCyrille Pitchen int err; 59477dacf5fSCyrille Pitchen 59577dacf5fSCyrille Pitchen switch (dd->ctx->block_size) { 59677dacf5fSCyrille Pitchen case CFB8_BLOCK_SIZE: 59777dacf5fSCyrille Pitchen addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 59877dacf5fSCyrille Pitchen maxburst = 1; 59977dacf5fSCyrille Pitchen break; 60077dacf5fSCyrille Pitchen 60177dacf5fSCyrille Pitchen case CFB16_BLOCK_SIZE: 60277dacf5fSCyrille Pitchen addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; 60377dacf5fSCyrille Pitchen maxburst = 1; 60477dacf5fSCyrille Pitchen break; 60577dacf5fSCyrille Pitchen 60677dacf5fSCyrille Pitchen case CFB32_BLOCK_SIZE: 60777dacf5fSCyrille Pitchen case CFB64_BLOCK_SIZE: 60877dacf5fSCyrille Pitchen addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 60977dacf5fSCyrille Pitchen maxburst = 1; 61077dacf5fSCyrille Pitchen break; 61177dacf5fSCyrille Pitchen 61277dacf5fSCyrille Pitchen case AES_BLOCK_SIZE: 61377dacf5fSCyrille Pitchen addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 61477dacf5fSCyrille Pitchen maxburst = dd->caps.max_burst_size; 61577dacf5fSCyrille Pitchen break; 61677dacf5fSCyrille Pitchen 61777dacf5fSCyrille Pitchen default: 618bbe628edSCyrille Pitchen err = -EINVAL; 619bbe628edSCyrille Pitchen goto exit; 62077dacf5fSCyrille Pitchen } 621bd3c7b5cSNicolas Royer 622bbe628edSCyrille Pitchen err = atmel_aes_map(dd, src, dst, len); 623bbe628edSCyrille Pitchen if (err) 624bbe628edSCyrille Pitchen goto exit; 625bd3c7b5cSNicolas Royer 626bbe628edSCyrille Pitchen dd->resume = resume; 627bd3c7b5cSNicolas Royer 628bbe628edSCyrille Pitchen /* Set output DMA transfer first */ 629bbe628edSCyrille Pitchen err = atmel_aes_dma_transfer_start(dd, addr_width, DMA_DEV_TO_MEM, 630bbe628edSCyrille Pitchen maxburst); 631bbe628edSCyrille Pitchen if (err) 632bbe628edSCyrille Pitchen goto unmap; 633cadc4ab8SNicolas Royer 634bbe628edSCyrille Pitchen /* Then set input DMA transfer */ 635bbe628edSCyrille Pitchen err = atmel_aes_dma_transfer_start(dd, addr_width, DMA_MEM_TO_DEV, 636bbe628edSCyrille Pitchen maxburst); 637bbe628edSCyrille Pitchen if (err) 638bbe628edSCyrille Pitchen goto output_transfer_stop; 639cadc4ab8SNicolas Royer 64010f12c1bSCyrille Pitchen return -EINPROGRESS; 641bbe628edSCyrille Pitchen 642bbe628edSCyrille Pitchen output_transfer_stop: 643bbe628edSCyrille Pitchen atmel_aes_dma_transfer_stop(dd, DMA_DEV_TO_MEM); 644bbe628edSCyrille Pitchen unmap: 645bbe628edSCyrille Pitchen atmel_aes_unmap(dd); 646bbe628edSCyrille Pitchen exit: 647bbe628edSCyrille Pitchen return atmel_aes_complete(dd, err); 648bd3c7b5cSNicolas Royer } 649bd3c7b5cSNicolas Royer 650bbe628edSCyrille Pitchen static void atmel_aes_dma_stop(struct atmel_aes_dev *dd) 651bd3c7b5cSNicolas Royer { 652bbe628edSCyrille Pitchen atmel_aes_dma_transfer_stop(dd, DMA_MEM_TO_DEV); 653bbe628edSCyrille Pitchen atmel_aes_dma_transfer_stop(dd, DMA_DEV_TO_MEM); 654bbe628edSCyrille Pitchen atmel_aes_unmap(dd); 655bd3c7b5cSNicolas Royer } 656bd3c7b5cSNicolas Royer 657bbe628edSCyrille Pitchen static void atmel_aes_dma_callback(void *data) 658bbe628edSCyrille Pitchen { 659bbe628edSCyrille Pitchen struct atmel_aes_dev *dd = data; 660bd3c7b5cSNicolas Royer 661bbe628edSCyrille Pitchen atmel_aes_dma_stop(dd); 662bbe628edSCyrille Pitchen dd->is_async = true; 663bbe628edSCyrille Pitchen (void)dd->resume(dd); 664bd3c7b5cSNicolas Royer } 665bd3c7b5cSNicolas Royer 666cdfab4a7SCyrille Pitchen static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma, 667cdfab4a7SCyrille Pitchen const u32 *iv) 668bd3c7b5cSNicolas Royer { 669794595d2SCyrille Pitchen u32 valmr = 0; 670bd3c7b5cSNicolas Royer 671bd3c7b5cSNicolas Royer /* MR register must be set before IV registers */ 672bd3c7b5cSNicolas Royer if (dd->ctx->keylen == AES_KEYSIZE_128) 673bd3c7b5cSNicolas Royer valmr |= AES_MR_KEYSIZE_128; 674bd3c7b5cSNicolas Royer else if (dd->ctx->keylen == AES_KEYSIZE_192) 675bd3c7b5cSNicolas Royer valmr |= AES_MR_KEYSIZE_192; 676bd3c7b5cSNicolas Royer else 677bd3c7b5cSNicolas Royer valmr |= AES_MR_KEYSIZE_256; 678bd3c7b5cSNicolas Royer 67977dacf5fSCyrille Pitchen valmr |= dd->flags & AES_FLAGS_MODE_MASK; 680bd3c7b5cSNicolas Royer 681cdfab4a7SCyrille Pitchen if (use_dma) { 682bd3c7b5cSNicolas Royer valmr |= AES_MR_SMOD_IDATAR0; 683cadc4ab8SNicolas Royer if (dd->caps.has_dualbuff) 684bd3c7b5cSNicolas Royer valmr |= AES_MR_DUALBUFF; 685bd3c7b5cSNicolas Royer } else { 686bd3c7b5cSNicolas Royer valmr |= AES_MR_SMOD_AUTO; 687bd3c7b5cSNicolas Royer } 688bd3c7b5cSNicolas Royer 689bd3c7b5cSNicolas Royer atmel_aes_write(dd, AES_MR, valmr); 690bd3c7b5cSNicolas Royer 691bd3c7b5cSNicolas Royer atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key, 692bd3c7b5cSNicolas Royer dd->ctx->keylen >> 2); 693bd3c7b5cSNicolas Royer 69477dacf5fSCyrille Pitchen if (iv && (valmr & AES_MR_OPMOD_MASK) != AES_MR_OPMOD_ECB) 695cdfab4a7SCyrille Pitchen atmel_aes_write_n(dd, AES_IVR(0), iv, 4); 696bd3c7b5cSNicolas Royer } 697bd3c7b5cSNicolas Royer 698bd3c7b5cSNicolas Royer static int atmel_aes_handle_queue(struct atmel_aes_dev *dd, 699ccbf7298SCyrille Pitchen struct crypto_async_request *new_areq) 700bd3c7b5cSNicolas Royer { 701ccbf7298SCyrille Pitchen struct crypto_async_request *areq, *backlog; 702ccbf7298SCyrille Pitchen struct atmel_aes_base_ctx *ctx; 703bd3c7b5cSNicolas Royer unsigned long flags; 704bd3c7b5cSNicolas Royer int err, ret = 0; 705bd3c7b5cSNicolas Royer 706bd3c7b5cSNicolas Royer spin_lock_irqsave(&dd->lock, flags); 707ccbf7298SCyrille Pitchen if (new_areq) 708ccbf7298SCyrille Pitchen ret = crypto_enqueue_request(&dd->queue, new_areq); 709bd3c7b5cSNicolas Royer if (dd->flags & AES_FLAGS_BUSY) { 710bd3c7b5cSNicolas Royer spin_unlock_irqrestore(&dd->lock, flags); 711bd3c7b5cSNicolas Royer return ret; 712bd3c7b5cSNicolas Royer } 713bd3c7b5cSNicolas Royer backlog = crypto_get_backlog(&dd->queue); 714ccbf7298SCyrille Pitchen areq = crypto_dequeue_request(&dd->queue); 715ccbf7298SCyrille Pitchen if (areq) 716bd3c7b5cSNicolas Royer dd->flags |= AES_FLAGS_BUSY; 717bd3c7b5cSNicolas Royer spin_unlock_irqrestore(&dd->lock, flags); 718bd3c7b5cSNicolas Royer 719ccbf7298SCyrille Pitchen if (!areq) 720bd3c7b5cSNicolas Royer return ret; 721bd3c7b5cSNicolas Royer 722bd3c7b5cSNicolas Royer if (backlog) 723bd3c7b5cSNicolas Royer backlog->complete(backlog, -EINPROGRESS); 724bd3c7b5cSNicolas Royer 725ccbf7298SCyrille Pitchen ctx = crypto_tfm_ctx(areq->tfm); 726ccbf7298SCyrille Pitchen 727ccbf7298SCyrille Pitchen dd->areq = areq; 728ccbf7298SCyrille Pitchen dd->ctx = ctx; 72910f12c1bSCyrille Pitchen dd->is_async = (areq != new_areq); 730ccbf7298SCyrille Pitchen 731ccbf7298SCyrille Pitchen err = ctx->start(dd); 73210f12c1bSCyrille Pitchen return (dd->is_async) ? ret : err; 733ccbf7298SCyrille Pitchen } 734ccbf7298SCyrille Pitchen 735bbe628edSCyrille Pitchen static int atmel_aes_transfer_complete(struct atmel_aes_dev *dd) 736bbe628edSCyrille Pitchen { 737bbe628edSCyrille Pitchen return atmel_aes_complete(dd, 0); 738bbe628edSCyrille Pitchen } 739bbe628edSCyrille Pitchen 740ccbf7298SCyrille Pitchen static int atmel_aes_start(struct atmel_aes_dev *dd) 741ccbf7298SCyrille Pitchen { 742ccbf7298SCyrille Pitchen struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq); 743bbe628edSCyrille Pitchen struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req); 744bbe628edSCyrille Pitchen bool use_dma = (req->nbytes >= ATMEL_AES_DMA_THRESHOLD || 745bbe628edSCyrille Pitchen dd->ctx->block_size != AES_BLOCK_SIZE); 746ccbf7298SCyrille Pitchen int err; 747bd3c7b5cSNicolas Royer 74877dacf5fSCyrille Pitchen atmel_aes_set_mode(dd, rctx); 749bd3c7b5cSNicolas Royer 750cdfab4a7SCyrille Pitchen err = atmel_aes_hw_init(dd); 751bbe628edSCyrille Pitchen if (err) 752bbe628edSCyrille Pitchen return atmel_aes_complete(dd, err); 753bbe628edSCyrille Pitchen 754cdfab4a7SCyrille Pitchen atmel_aes_write_ctrl(dd, use_dma, req->info); 755cdfab4a7SCyrille Pitchen if (use_dma) 756bbe628edSCyrille Pitchen return atmel_aes_dma_start(dd, req->src, req->dst, req->nbytes, 757bbe628edSCyrille Pitchen atmel_aes_transfer_complete); 758bd3c7b5cSNicolas Royer 759bbe628edSCyrille Pitchen return atmel_aes_cpu_start(dd, req->src, req->dst, req->nbytes, 760bbe628edSCyrille Pitchen atmel_aes_transfer_complete); 761bd3c7b5cSNicolas Royer } 762bd3c7b5cSNicolas Royer 763cadc4ab8SNicolas Royer 764cadc4ab8SNicolas Royer static int atmel_aes_buff_init(struct atmel_aes_dev *dd) 765cadc4ab8SNicolas Royer { 766bbe628edSCyrille Pitchen dd->buf = (void *)__get_free_pages(GFP_KERNEL, ATMEL_AES_BUFFER_ORDER); 767bbe628edSCyrille Pitchen dd->buflen = ATMEL_AES_BUFFER_SIZE; 768cadc4ab8SNicolas Royer dd->buflen &= ~(AES_BLOCK_SIZE - 1); 769cadc4ab8SNicolas Royer 770bbe628edSCyrille Pitchen if (!dd->buf) { 771cadc4ab8SNicolas Royer dev_err(dd->dev, "unable to alloc pages.\n"); 772bbe628edSCyrille Pitchen return -ENOMEM; 773cadc4ab8SNicolas Royer } 774cadc4ab8SNicolas Royer 775cadc4ab8SNicolas Royer return 0; 776cadc4ab8SNicolas Royer } 777cadc4ab8SNicolas Royer 778cadc4ab8SNicolas Royer static void atmel_aes_buff_cleanup(struct atmel_aes_dev *dd) 779cadc4ab8SNicolas Royer { 780bbe628edSCyrille Pitchen free_page((unsigned long)dd->buf); 781cadc4ab8SNicolas Royer } 782cadc4ab8SNicolas Royer 783bd3c7b5cSNicolas Royer static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode) 784bd3c7b5cSNicolas Royer { 785ccbf7298SCyrille Pitchen struct atmel_aes_base_ctx *ctx = crypto_ablkcipher_ctx( 786bd3c7b5cSNicolas Royer crypto_ablkcipher_reqtfm(req)); 787bd3c7b5cSNicolas Royer struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req); 788bd3c7b5cSNicolas Royer struct atmel_aes_dev *dd; 789bd3c7b5cSNicolas Royer 79077dacf5fSCyrille Pitchen switch (mode & AES_FLAGS_OPMODE_MASK) { 79177dacf5fSCyrille Pitchen case AES_FLAGS_CFB8: 792cadc4ab8SNicolas Royer ctx->block_size = CFB8_BLOCK_SIZE; 79377dacf5fSCyrille Pitchen break; 79477dacf5fSCyrille Pitchen 79577dacf5fSCyrille Pitchen case AES_FLAGS_CFB16: 796cadc4ab8SNicolas Royer ctx->block_size = CFB16_BLOCK_SIZE; 79777dacf5fSCyrille Pitchen break; 79877dacf5fSCyrille Pitchen 79977dacf5fSCyrille Pitchen case AES_FLAGS_CFB32: 800cadc4ab8SNicolas Royer ctx->block_size = CFB32_BLOCK_SIZE; 80177dacf5fSCyrille Pitchen break; 80277dacf5fSCyrille Pitchen 80377dacf5fSCyrille Pitchen case AES_FLAGS_CFB64: 8049f84951fSLeilei Zhao ctx->block_size = CFB64_BLOCK_SIZE; 80577dacf5fSCyrille Pitchen break; 80677dacf5fSCyrille Pitchen 80777dacf5fSCyrille Pitchen default: 808cadc4ab8SNicolas Royer ctx->block_size = AES_BLOCK_SIZE; 80977dacf5fSCyrille Pitchen break; 810cadc4ab8SNicolas Royer } 811bd3c7b5cSNicolas Royer 812bd3c7b5cSNicolas Royer dd = atmel_aes_find_dev(ctx); 813bd3c7b5cSNicolas Royer if (!dd) 814bd3c7b5cSNicolas Royer return -ENODEV; 815bd3c7b5cSNicolas Royer 816bd3c7b5cSNicolas Royer rctx->mode = mode; 817bd3c7b5cSNicolas Royer 818ccbf7298SCyrille Pitchen return atmel_aes_handle_queue(dd, &req->base); 819bd3c7b5cSNicolas Royer } 820bd3c7b5cSNicolas Royer 821bd3c7b5cSNicolas Royer static bool atmel_aes_filter(struct dma_chan *chan, void *slave) 822bd3c7b5cSNicolas Royer { 823bd3c7b5cSNicolas Royer struct at_dma_slave *sl = slave; 824bd3c7b5cSNicolas Royer 825bd3c7b5cSNicolas Royer if (sl && sl->dma_dev == chan->device->dev) { 826bd3c7b5cSNicolas Royer chan->private = sl; 827bd3c7b5cSNicolas Royer return true; 828bd3c7b5cSNicolas Royer } else { 829bd3c7b5cSNicolas Royer return false; 830bd3c7b5cSNicolas Royer } 831bd3c7b5cSNicolas Royer } 832bd3c7b5cSNicolas Royer 833cadc4ab8SNicolas Royer static int atmel_aes_dma_init(struct atmel_aes_dev *dd, 834cadc4ab8SNicolas Royer struct crypto_platform_data *pdata) 835bd3c7b5cSNicolas Royer { 836bbe628edSCyrille Pitchen struct at_dma_slave *slave; 837bd3c7b5cSNicolas Royer int err = -ENOMEM; 838be943c7dSNicolas Ferre dma_cap_mask_t mask; 839bd3c7b5cSNicolas Royer 840be943c7dSNicolas Ferre dma_cap_zero(mask); 841be943c7dSNicolas Ferre dma_cap_set(DMA_SLAVE, mask); 842bd3c7b5cSNicolas Royer 843bd3c7b5cSNicolas Royer /* Try to grab 2 DMA channels */ 844bbe628edSCyrille Pitchen slave = &pdata->dma_slave->rxdata; 845bbe628edSCyrille Pitchen dd->src.chan = dma_request_slave_channel_compat(mask, atmel_aes_filter, 846bbe628edSCyrille Pitchen slave, dd->dev, "tx"); 847bbe628edSCyrille Pitchen if (!dd->src.chan) 848bd3c7b5cSNicolas Royer goto err_dma_in; 849bd3c7b5cSNicolas Royer 850bbe628edSCyrille Pitchen slave = &pdata->dma_slave->txdata; 851bbe628edSCyrille Pitchen dd->dst.chan = dma_request_slave_channel_compat(mask, atmel_aes_filter, 852bbe628edSCyrille Pitchen slave, dd->dev, "rx"); 853bbe628edSCyrille Pitchen if (!dd->dst.chan) 854bd3c7b5cSNicolas Royer goto err_dma_out; 855bd3c7b5cSNicolas Royer 856bd3c7b5cSNicolas Royer return 0; 857bd3c7b5cSNicolas Royer 858bd3c7b5cSNicolas Royer err_dma_out: 859bbe628edSCyrille Pitchen dma_release_channel(dd->src.chan); 860bd3c7b5cSNicolas Royer err_dma_in: 861be943c7dSNicolas Ferre dev_warn(dd->dev, "no DMA channel available\n"); 862bd3c7b5cSNicolas Royer return err; 863bd3c7b5cSNicolas Royer } 864bd3c7b5cSNicolas Royer 865bd3c7b5cSNicolas Royer static void atmel_aes_dma_cleanup(struct atmel_aes_dev *dd) 866bd3c7b5cSNicolas Royer { 867bbe628edSCyrille Pitchen dma_release_channel(dd->dst.chan); 868bbe628edSCyrille Pitchen dma_release_channel(dd->src.chan); 869bd3c7b5cSNicolas Royer } 870bd3c7b5cSNicolas Royer 871bd3c7b5cSNicolas Royer static int atmel_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, 872bd3c7b5cSNicolas Royer unsigned int keylen) 873bd3c7b5cSNicolas Royer { 874ccbf7298SCyrille Pitchen struct atmel_aes_base_ctx *ctx = crypto_ablkcipher_ctx(tfm); 875bd3c7b5cSNicolas Royer 876bd3c7b5cSNicolas Royer if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 && 877bd3c7b5cSNicolas Royer keylen != AES_KEYSIZE_256) { 878bd3c7b5cSNicolas Royer crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 879bd3c7b5cSNicolas Royer return -EINVAL; 880bd3c7b5cSNicolas Royer } 881bd3c7b5cSNicolas Royer 882bd3c7b5cSNicolas Royer memcpy(ctx->key, key, keylen); 883bd3c7b5cSNicolas Royer ctx->keylen = keylen; 884bd3c7b5cSNicolas Royer 885bd3c7b5cSNicolas Royer return 0; 886bd3c7b5cSNicolas Royer } 887bd3c7b5cSNicolas Royer 888bd3c7b5cSNicolas Royer static int atmel_aes_ecb_encrypt(struct ablkcipher_request *req) 889bd3c7b5cSNicolas Royer { 89077dacf5fSCyrille Pitchen return atmel_aes_crypt(req, AES_FLAGS_ECB | AES_FLAGS_ENCRYPT); 891bd3c7b5cSNicolas Royer } 892bd3c7b5cSNicolas Royer 893bd3c7b5cSNicolas Royer static int atmel_aes_ecb_decrypt(struct ablkcipher_request *req) 894bd3c7b5cSNicolas Royer { 89577dacf5fSCyrille Pitchen return atmel_aes_crypt(req, AES_FLAGS_ECB); 896bd3c7b5cSNicolas Royer } 897bd3c7b5cSNicolas Royer 898bd3c7b5cSNicolas Royer static int atmel_aes_cbc_encrypt(struct ablkcipher_request *req) 899bd3c7b5cSNicolas Royer { 900bd3c7b5cSNicolas Royer return atmel_aes_crypt(req, 901bd3c7b5cSNicolas Royer AES_FLAGS_ENCRYPT | AES_FLAGS_CBC); 902bd3c7b5cSNicolas Royer } 903bd3c7b5cSNicolas Royer 904bd3c7b5cSNicolas Royer static int atmel_aes_cbc_decrypt(struct ablkcipher_request *req) 905bd3c7b5cSNicolas Royer { 906bd3c7b5cSNicolas Royer return atmel_aes_crypt(req, 907bd3c7b5cSNicolas Royer AES_FLAGS_CBC); 908bd3c7b5cSNicolas Royer } 909bd3c7b5cSNicolas Royer 910bd3c7b5cSNicolas Royer static int atmel_aes_ofb_encrypt(struct ablkcipher_request *req) 911bd3c7b5cSNicolas Royer { 912bd3c7b5cSNicolas Royer return atmel_aes_crypt(req, 913bd3c7b5cSNicolas Royer AES_FLAGS_ENCRYPT | AES_FLAGS_OFB); 914bd3c7b5cSNicolas Royer } 915bd3c7b5cSNicolas Royer 916bd3c7b5cSNicolas Royer static int atmel_aes_ofb_decrypt(struct ablkcipher_request *req) 917bd3c7b5cSNicolas Royer { 918bd3c7b5cSNicolas Royer return atmel_aes_crypt(req, 919bd3c7b5cSNicolas Royer AES_FLAGS_OFB); 920bd3c7b5cSNicolas Royer } 921bd3c7b5cSNicolas Royer 922bd3c7b5cSNicolas Royer static int atmel_aes_cfb_encrypt(struct ablkcipher_request *req) 923bd3c7b5cSNicolas Royer { 92477dacf5fSCyrille Pitchen return atmel_aes_crypt(req, AES_FLAGS_CFB128 | AES_FLAGS_ENCRYPT); 925bd3c7b5cSNicolas Royer } 926bd3c7b5cSNicolas Royer 927bd3c7b5cSNicolas Royer static int atmel_aes_cfb_decrypt(struct ablkcipher_request *req) 928bd3c7b5cSNicolas Royer { 92977dacf5fSCyrille Pitchen return atmel_aes_crypt(req, AES_FLAGS_CFB128); 930bd3c7b5cSNicolas Royer } 931bd3c7b5cSNicolas Royer 932bd3c7b5cSNicolas Royer static int atmel_aes_cfb64_encrypt(struct ablkcipher_request *req) 933bd3c7b5cSNicolas Royer { 93477dacf5fSCyrille Pitchen return atmel_aes_crypt(req, AES_FLAGS_CFB64 | AES_FLAGS_ENCRYPT); 935bd3c7b5cSNicolas Royer } 936bd3c7b5cSNicolas Royer 937bd3c7b5cSNicolas Royer static int atmel_aes_cfb64_decrypt(struct ablkcipher_request *req) 938bd3c7b5cSNicolas Royer { 93977dacf5fSCyrille Pitchen return atmel_aes_crypt(req, AES_FLAGS_CFB64); 940bd3c7b5cSNicolas Royer } 941bd3c7b5cSNicolas Royer 942bd3c7b5cSNicolas Royer static int atmel_aes_cfb32_encrypt(struct ablkcipher_request *req) 943bd3c7b5cSNicolas Royer { 94477dacf5fSCyrille Pitchen return atmel_aes_crypt(req, AES_FLAGS_CFB32 | AES_FLAGS_ENCRYPT); 945bd3c7b5cSNicolas Royer } 946bd3c7b5cSNicolas Royer 947bd3c7b5cSNicolas Royer static int atmel_aes_cfb32_decrypt(struct ablkcipher_request *req) 948bd3c7b5cSNicolas Royer { 94977dacf5fSCyrille Pitchen return atmel_aes_crypt(req, AES_FLAGS_CFB32); 950bd3c7b5cSNicolas Royer } 951bd3c7b5cSNicolas Royer 952bd3c7b5cSNicolas Royer static int atmel_aes_cfb16_encrypt(struct ablkcipher_request *req) 953bd3c7b5cSNicolas Royer { 95477dacf5fSCyrille Pitchen return atmel_aes_crypt(req, AES_FLAGS_CFB16 | AES_FLAGS_ENCRYPT); 955bd3c7b5cSNicolas Royer } 956bd3c7b5cSNicolas Royer 957bd3c7b5cSNicolas Royer static int atmel_aes_cfb16_decrypt(struct ablkcipher_request *req) 958bd3c7b5cSNicolas Royer { 95977dacf5fSCyrille Pitchen return atmel_aes_crypt(req, AES_FLAGS_CFB16); 960bd3c7b5cSNicolas Royer } 961bd3c7b5cSNicolas Royer 962bd3c7b5cSNicolas Royer static int atmel_aes_cfb8_encrypt(struct ablkcipher_request *req) 963bd3c7b5cSNicolas Royer { 96477dacf5fSCyrille Pitchen return atmel_aes_crypt(req, AES_FLAGS_CFB8 | AES_FLAGS_ENCRYPT); 965bd3c7b5cSNicolas Royer } 966bd3c7b5cSNicolas Royer 967bd3c7b5cSNicolas Royer static int atmel_aes_cfb8_decrypt(struct ablkcipher_request *req) 968bd3c7b5cSNicolas Royer { 96977dacf5fSCyrille Pitchen return atmel_aes_crypt(req, AES_FLAGS_CFB8); 970bd3c7b5cSNicolas Royer } 971bd3c7b5cSNicolas Royer 972bd3c7b5cSNicolas Royer static int atmel_aes_ctr_encrypt(struct ablkcipher_request *req) 973bd3c7b5cSNicolas Royer { 974bd3c7b5cSNicolas Royer return atmel_aes_crypt(req, 975bd3c7b5cSNicolas Royer AES_FLAGS_ENCRYPT | AES_FLAGS_CTR); 976bd3c7b5cSNicolas Royer } 977bd3c7b5cSNicolas Royer 978bd3c7b5cSNicolas Royer static int atmel_aes_ctr_decrypt(struct ablkcipher_request *req) 979bd3c7b5cSNicolas Royer { 980bd3c7b5cSNicolas Royer return atmel_aes_crypt(req, 981bd3c7b5cSNicolas Royer AES_FLAGS_CTR); 982bd3c7b5cSNicolas Royer } 983bd3c7b5cSNicolas Royer 984bd3c7b5cSNicolas Royer static int atmel_aes_cra_init(struct crypto_tfm *tfm) 985bd3c7b5cSNicolas Royer { 986ccbf7298SCyrille Pitchen struct atmel_aes_ctx *ctx = crypto_tfm_ctx(tfm); 987ccbf7298SCyrille Pitchen 988bd3c7b5cSNicolas Royer tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_aes_reqctx); 989ccbf7298SCyrille Pitchen ctx->base.start = atmel_aes_start; 990bd3c7b5cSNicolas Royer 991bd3c7b5cSNicolas Royer return 0; 992bd3c7b5cSNicolas Royer } 993bd3c7b5cSNicolas Royer 994bd3c7b5cSNicolas Royer static void atmel_aes_cra_exit(struct crypto_tfm *tfm) 995bd3c7b5cSNicolas Royer { 996bd3c7b5cSNicolas Royer } 997bd3c7b5cSNicolas Royer 998bd3c7b5cSNicolas Royer static struct crypto_alg aes_algs[] = { 999bd3c7b5cSNicolas Royer { 1000bd3c7b5cSNicolas Royer .cra_name = "ecb(aes)", 1001bd3c7b5cSNicolas Royer .cra_driver_name = "atmel-ecb-aes", 100288efd9a9SCyrille Pitchen .cra_priority = ATMEL_AES_PRIORITY, 1003bd3c7b5cSNicolas Royer .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 1004bd3c7b5cSNicolas Royer .cra_blocksize = AES_BLOCK_SIZE, 1005bd3c7b5cSNicolas Royer .cra_ctxsize = sizeof(struct atmel_aes_ctx), 1006cadc4ab8SNicolas Royer .cra_alignmask = 0xf, 1007bd3c7b5cSNicolas Royer .cra_type = &crypto_ablkcipher_type, 1008bd3c7b5cSNicolas Royer .cra_module = THIS_MODULE, 1009bd3c7b5cSNicolas Royer .cra_init = atmel_aes_cra_init, 1010bd3c7b5cSNicolas Royer .cra_exit = atmel_aes_cra_exit, 1011bd3c7b5cSNicolas Royer .cra_u.ablkcipher = { 1012bd3c7b5cSNicolas Royer .min_keysize = AES_MIN_KEY_SIZE, 1013bd3c7b5cSNicolas Royer .max_keysize = AES_MAX_KEY_SIZE, 1014bd3c7b5cSNicolas Royer .setkey = atmel_aes_setkey, 1015bd3c7b5cSNicolas Royer .encrypt = atmel_aes_ecb_encrypt, 1016bd3c7b5cSNicolas Royer .decrypt = atmel_aes_ecb_decrypt, 1017bd3c7b5cSNicolas Royer } 1018bd3c7b5cSNicolas Royer }, 1019bd3c7b5cSNicolas Royer { 1020bd3c7b5cSNicolas Royer .cra_name = "cbc(aes)", 1021bd3c7b5cSNicolas Royer .cra_driver_name = "atmel-cbc-aes", 102288efd9a9SCyrille Pitchen .cra_priority = ATMEL_AES_PRIORITY, 1023bd3c7b5cSNicolas Royer .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 1024bd3c7b5cSNicolas Royer .cra_blocksize = AES_BLOCK_SIZE, 1025bd3c7b5cSNicolas Royer .cra_ctxsize = sizeof(struct atmel_aes_ctx), 1026cadc4ab8SNicolas Royer .cra_alignmask = 0xf, 1027bd3c7b5cSNicolas Royer .cra_type = &crypto_ablkcipher_type, 1028bd3c7b5cSNicolas Royer .cra_module = THIS_MODULE, 1029bd3c7b5cSNicolas Royer .cra_init = atmel_aes_cra_init, 1030bd3c7b5cSNicolas Royer .cra_exit = atmel_aes_cra_exit, 1031bd3c7b5cSNicolas Royer .cra_u.ablkcipher = { 1032bd3c7b5cSNicolas Royer .min_keysize = AES_MIN_KEY_SIZE, 1033bd3c7b5cSNicolas Royer .max_keysize = AES_MAX_KEY_SIZE, 1034bd3c7b5cSNicolas Royer .ivsize = AES_BLOCK_SIZE, 1035bd3c7b5cSNicolas Royer .setkey = atmel_aes_setkey, 1036bd3c7b5cSNicolas Royer .encrypt = atmel_aes_cbc_encrypt, 1037bd3c7b5cSNicolas Royer .decrypt = atmel_aes_cbc_decrypt, 1038bd3c7b5cSNicolas Royer } 1039bd3c7b5cSNicolas Royer }, 1040bd3c7b5cSNicolas Royer { 1041bd3c7b5cSNicolas Royer .cra_name = "ofb(aes)", 1042bd3c7b5cSNicolas Royer .cra_driver_name = "atmel-ofb-aes", 104388efd9a9SCyrille Pitchen .cra_priority = ATMEL_AES_PRIORITY, 1044bd3c7b5cSNicolas Royer .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 1045bd3c7b5cSNicolas Royer .cra_blocksize = AES_BLOCK_SIZE, 1046bd3c7b5cSNicolas Royer .cra_ctxsize = sizeof(struct atmel_aes_ctx), 1047cadc4ab8SNicolas Royer .cra_alignmask = 0xf, 1048bd3c7b5cSNicolas Royer .cra_type = &crypto_ablkcipher_type, 1049bd3c7b5cSNicolas Royer .cra_module = THIS_MODULE, 1050bd3c7b5cSNicolas Royer .cra_init = atmel_aes_cra_init, 1051bd3c7b5cSNicolas Royer .cra_exit = atmel_aes_cra_exit, 1052bd3c7b5cSNicolas Royer .cra_u.ablkcipher = { 1053bd3c7b5cSNicolas Royer .min_keysize = AES_MIN_KEY_SIZE, 1054bd3c7b5cSNicolas Royer .max_keysize = AES_MAX_KEY_SIZE, 1055bd3c7b5cSNicolas Royer .ivsize = AES_BLOCK_SIZE, 1056bd3c7b5cSNicolas Royer .setkey = atmel_aes_setkey, 1057bd3c7b5cSNicolas Royer .encrypt = atmel_aes_ofb_encrypt, 1058bd3c7b5cSNicolas Royer .decrypt = atmel_aes_ofb_decrypt, 1059bd3c7b5cSNicolas Royer } 1060bd3c7b5cSNicolas Royer }, 1061bd3c7b5cSNicolas Royer { 1062bd3c7b5cSNicolas Royer .cra_name = "cfb(aes)", 1063bd3c7b5cSNicolas Royer .cra_driver_name = "atmel-cfb-aes", 106488efd9a9SCyrille Pitchen .cra_priority = ATMEL_AES_PRIORITY, 1065bd3c7b5cSNicolas Royer .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 1066bd3c7b5cSNicolas Royer .cra_blocksize = AES_BLOCK_SIZE, 1067bd3c7b5cSNicolas Royer .cra_ctxsize = sizeof(struct atmel_aes_ctx), 1068cadc4ab8SNicolas Royer .cra_alignmask = 0xf, 1069bd3c7b5cSNicolas Royer .cra_type = &crypto_ablkcipher_type, 1070bd3c7b5cSNicolas Royer .cra_module = THIS_MODULE, 1071bd3c7b5cSNicolas Royer .cra_init = atmel_aes_cra_init, 1072bd3c7b5cSNicolas Royer .cra_exit = atmel_aes_cra_exit, 1073bd3c7b5cSNicolas Royer .cra_u.ablkcipher = { 1074bd3c7b5cSNicolas Royer .min_keysize = AES_MIN_KEY_SIZE, 1075bd3c7b5cSNicolas Royer .max_keysize = AES_MAX_KEY_SIZE, 1076bd3c7b5cSNicolas Royer .ivsize = AES_BLOCK_SIZE, 1077bd3c7b5cSNicolas Royer .setkey = atmel_aes_setkey, 1078bd3c7b5cSNicolas Royer .encrypt = atmel_aes_cfb_encrypt, 1079bd3c7b5cSNicolas Royer .decrypt = atmel_aes_cfb_decrypt, 1080bd3c7b5cSNicolas Royer } 1081bd3c7b5cSNicolas Royer }, 1082bd3c7b5cSNicolas Royer { 1083bd3c7b5cSNicolas Royer .cra_name = "cfb32(aes)", 1084bd3c7b5cSNicolas Royer .cra_driver_name = "atmel-cfb32-aes", 108588efd9a9SCyrille Pitchen .cra_priority = ATMEL_AES_PRIORITY, 1086bd3c7b5cSNicolas Royer .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 1087bd3c7b5cSNicolas Royer .cra_blocksize = CFB32_BLOCK_SIZE, 1088bd3c7b5cSNicolas Royer .cra_ctxsize = sizeof(struct atmel_aes_ctx), 1089cadc4ab8SNicolas Royer .cra_alignmask = 0x3, 1090bd3c7b5cSNicolas Royer .cra_type = &crypto_ablkcipher_type, 1091bd3c7b5cSNicolas Royer .cra_module = THIS_MODULE, 1092bd3c7b5cSNicolas Royer .cra_init = atmel_aes_cra_init, 1093bd3c7b5cSNicolas Royer .cra_exit = atmel_aes_cra_exit, 1094bd3c7b5cSNicolas Royer .cra_u.ablkcipher = { 1095bd3c7b5cSNicolas Royer .min_keysize = AES_MIN_KEY_SIZE, 1096bd3c7b5cSNicolas Royer .max_keysize = AES_MAX_KEY_SIZE, 1097bd3c7b5cSNicolas Royer .ivsize = AES_BLOCK_SIZE, 1098bd3c7b5cSNicolas Royer .setkey = atmel_aes_setkey, 1099bd3c7b5cSNicolas Royer .encrypt = atmel_aes_cfb32_encrypt, 1100bd3c7b5cSNicolas Royer .decrypt = atmel_aes_cfb32_decrypt, 1101bd3c7b5cSNicolas Royer } 1102bd3c7b5cSNicolas Royer }, 1103bd3c7b5cSNicolas Royer { 1104bd3c7b5cSNicolas Royer .cra_name = "cfb16(aes)", 1105bd3c7b5cSNicolas Royer .cra_driver_name = "atmel-cfb16-aes", 110688efd9a9SCyrille Pitchen .cra_priority = ATMEL_AES_PRIORITY, 1107bd3c7b5cSNicolas Royer .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 1108bd3c7b5cSNicolas Royer .cra_blocksize = CFB16_BLOCK_SIZE, 1109bd3c7b5cSNicolas Royer .cra_ctxsize = sizeof(struct atmel_aes_ctx), 1110cadc4ab8SNicolas Royer .cra_alignmask = 0x1, 1111bd3c7b5cSNicolas Royer .cra_type = &crypto_ablkcipher_type, 1112bd3c7b5cSNicolas Royer .cra_module = THIS_MODULE, 1113bd3c7b5cSNicolas Royer .cra_init = atmel_aes_cra_init, 1114bd3c7b5cSNicolas Royer .cra_exit = atmel_aes_cra_exit, 1115bd3c7b5cSNicolas Royer .cra_u.ablkcipher = { 1116bd3c7b5cSNicolas Royer .min_keysize = AES_MIN_KEY_SIZE, 1117bd3c7b5cSNicolas Royer .max_keysize = AES_MAX_KEY_SIZE, 1118bd3c7b5cSNicolas Royer .ivsize = AES_BLOCK_SIZE, 1119bd3c7b5cSNicolas Royer .setkey = atmel_aes_setkey, 1120bd3c7b5cSNicolas Royer .encrypt = atmel_aes_cfb16_encrypt, 1121bd3c7b5cSNicolas Royer .decrypt = atmel_aes_cfb16_decrypt, 1122bd3c7b5cSNicolas Royer } 1123bd3c7b5cSNicolas Royer }, 1124bd3c7b5cSNicolas Royer { 1125bd3c7b5cSNicolas Royer .cra_name = "cfb8(aes)", 1126bd3c7b5cSNicolas Royer .cra_driver_name = "atmel-cfb8-aes", 112788efd9a9SCyrille Pitchen .cra_priority = ATMEL_AES_PRIORITY, 1128bd3c7b5cSNicolas Royer .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 1129e5d8c961SLeilei Zhao .cra_blocksize = CFB8_BLOCK_SIZE, 1130bd3c7b5cSNicolas Royer .cra_ctxsize = sizeof(struct atmel_aes_ctx), 1131bd3c7b5cSNicolas Royer .cra_alignmask = 0x0, 1132bd3c7b5cSNicolas Royer .cra_type = &crypto_ablkcipher_type, 1133bd3c7b5cSNicolas Royer .cra_module = THIS_MODULE, 1134bd3c7b5cSNicolas Royer .cra_init = atmel_aes_cra_init, 1135bd3c7b5cSNicolas Royer .cra_exit = atmel_aes_cra_exit, 1136bd3c7b5cSNicolas Royer .cra_u.ablkcipher = { 1137bd3c7b5cSNicolas Royer .min_keysize = AES_MIN_KEY_SIZE, 1138bd3c7b5cSNicolas Royer .max_keysize = AES_MAX_KEY_SIZE, 1139bd3c7b5cSNicolas Royer .ivsize = AES_BLOCK_SIZE, 1140bd3c7b5cSNicolas Royer .setkey = atmel_aes_setkey, 1141bd3c7b5cSNicolas Royer .encrypt = atmel_aes_cfb8_encrypt, 1142bd3c7b5cSNicolas Royer .decrypt = atmel_aes_cfb8_decrypt, 1143bd3c7b5cSNicolas Royer } 1144bd3c7b5cSNicolas Royer }, 1145bd3c7b5cSNicolas Royer { 1146bd3c7b5cSNicolas Royer .cra_name = "ctr(aes)", 1147bd3c7b5cSNicolas Royer .cra_driver_name = "atmel-ctr-aes", 114888efd9a9SCyrille Pitchen .cra_priority = ATMEL_AES_PRIORITY, 1149bd3c7b5cSNicolas Royer .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 1150bd3c7b5cSNicolas Royer .cra_blocksize = AES_BLOCK_SIZE, 1151bd3c7b5cSNicolas Royer .cra_ctxsize = sizeof(struct atmel_aes_ctx), 1152cadc4ab8SNicolas Royer .cra_alignmask = 0xf, 1153bd3c7b5cSNicolas Royer .cra_type = &crypto_ablkcipher_type, 1154bd3c7b5cSNicolas Royer .cra_module = THIS_MODULE, 1155bd3c7b5cSNicolas Royer .cra_init = atmel_aes_cra_init, 1156bd3c7b5cSNicolas Royer .cra_exit = atmel_aes_cra_exit, 1157bd3c7b5cSNicolas Royer .cra_u.ablkcipher = { 1158bd3c7b5cSNicolas Royer .min_keysize = AES_MIN_KEY_SIZE, 1159bd3c7b5cSNicolas Royer .max_keysize = AES_MAX_KEY_SIZE, 1160bd3c7b5cSNicolas Royer .ivsize = AES_BLOCK_SIZE, 1161bd3c7b5cSNicolas Royer .setkey = atmel_aes_setkey, 1162bd3c7b5cSNicolas Royer .encrypt = atmel_aes_ctr_encrypt, 1163bd3c7b5cSNicolas Royer .decrypt = atmel_aes_ctr_decrypt, 1164bd3c7b5cSNicolas Royer } 1165bd3c7b5cSNicolas Royer }, 1166bd3c7b5cSNicolas Royer }; 1167bd3c7b5cSNicolas Royer 1168cadc4ab8SNicolas Royer static struct crypto_alg aes_cfb64_alg = { 1169bd3c7b5cSNicolas Royer .cra_name = "cfb64(aes)", 1170bd3c7b5cSNicolas Royer .cra_driver_name = "atmel-cfb64-aes", 117188efd9a9SCyrille Pitchen .cra_priority = ATMEL_AES_PRIORITY, 1172bd3c7b5cSNicolas Royer .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 1173bd3c7b5cSNicolas Royer .cra_blocksize = CFB64_BLOCK_SIZE, 1174bd3c7b5cSNicolas Royer .cra_ctxsize = sizeof(struct atmel_aes_ctx), 1175cadc4ab8SNicolas Royer .cra_alignmask = 0x7, 1176bd3c7b5cSNicolas Royer .cra_type = &crypto_ablkcipher_type, 1177bd3c7b5cSNicolas Royer .cra_module = THIS_MODULE, 1178bd3c7b5cSNicolas Royer .cra_init = atmel_aes_cra_init, 1179bd3c7b5cSNicolas Royer .cra_exit = atmel_aes_cra_exit, 1180bd3c7b5cSNicolas Royer .cra_u.ablkcipher = { 1181bd3c7b5cSNicolas Royer .min_keysize = AES_MIN_KEY_SIZE, 1182bd3c7b5cSNicolas Royer .max_keysize = AES_MAX_KEY_SIZE, 1183bd3c7b5cSNicolas Royer .ivsize = AES_BLOCK_SIZE, 1184bd3c7b5cSNicolas Royer .setkey = atmel_aes_setkey, 1185bd3c7b5cSNicolas Royer .encrypt = atmel_aes_cfb64_encrypt, 1186bd3c7b5cSNicolas Royer .decrypt = atmel_aes_cfb64_decrypt, 1187bd3c7b5cSNicolas Royer } 1188bd3c7b5cSNicolas Royer }; 1189bd3c7b5cSNicolas Royer 1190bd3c7b5cSNicolas Royer static void atmel_aes_queue_task(unsigned long data) 1191bd3c7b5cSNicolas Royer { 1192bd3c7b5cSNicolas Royer struct atmel_aes_dev *dd = (struct atmel_aes_dev *)data; 1193bd3c7b5cSNicolas Royer 1194bd3c7b5cSNicolas Royer atmel_aes_handle_queue(dd, NULL); 1195bd3c7b5cSNicolas Royer } 1196bd3c7b5cSNicolas Royer 1197bd3c7b5cSNicolas Royer static void atmel_aes_done_task(unsigned long data) 1198bd3c7b5cSNicolas Royer { 1199bd3c7b5cSNicolas Royer struct atmel_aes_dev *dd = (struct atmel_aes_dev *) data; 1200bd3c7b5cSNicolas Royer 120110f12c1bSCyrille Pitchen dd->is_async = true; 120210f12c1bSCyrille Pitchen (void)dd->resume(dd); 1203bd3c7b5cSNicolas Royer } 1204bd3c7b5cSNicolas Royer 1205bd3c7b5cSNicolas Royer static irqreturn_t atmel_aes_irq(int irq, void *dev_id) 1206bd3c7b5cSNicolas Royer { 1207bd3c7b5cSNicolas Royer struct atmel_aes_dev *aes_dd = dev_id; 1208bd3c7b5cSNicolas Royer u32 reg; 1209bd3c7b5cSNicolas Royer 1210bd3c7b5cSNicolas Royer reg = atmel_aes_read(aes_dd, AES_ISR); 1211bd3c7b5cSNicolas Royer if (reg & atmel_aes_read(aes_dd, AES_IMR)) { 1212bd3c7b5cSNicolas Royer atmel_aes_write(aes_dd, AES_IDR, reg); 1213bd3c7b5cSNicolas Royer if (AES_FLAGS_BUSY & aes_dd->flags) 1214bd3c7b5cSNicolas Royer tasklet_schedule(&aes_dd->done_task); 1215bd3c7b5cSNicolas Royer else 1216bd3c7b5cSNicolas Royer dev_warn(aes_dd->dev, "AES interrupt when no active requests.\n"); 1217bd3c7b5cSNicolas Royer return IRQ_HANDLED; 1218bd3c7b5cSNicolas Royer } 1219bd3c7b5cSNicolas Royer 1220bd3c7b5cSNicolas Royer return IRQ_NONE; 1221bd3c7b5cSNicolas Royer } 1222bd3c7b5cSNicolas Royer 1223bd3c7b5cSNicolas Royer static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd) 1224bd3c7b5cSNicolas Royer { 1225bd3c7b5cSNicolas Royer int i; 1226bd3c7b5cSNicolas Royer 1227cadc4ab8SNicolas Royer if (dd->caps.has_cfb64) 1228cadc4ab8SNicolas Royer crypto_unregister_alg(&aes_cfb64_alg); 1229924a8bc7SCyrille Pitchen 1230924a8bc7SCyrille Pitchen for (i = 0; i < ARRAY_SIZE(aes_algs); i++) 1231924a8bc7SCyrille Pitchen crypto_unregister_alg(&aes_algs[i]); 1232bd3c7b5cSNicolas Royer } 1233bd3c7b5cSNicolas Royer 1234bd3c7b5cSNicolas Royer static int atmel_aes_register_algs(struct atmel_aes_dev *dd) 1235bd3c7b5cSNicolas Royer { 1236bd3c7b5cSNicolas Royer int err, i, j; 1237bd3c7b5cSNicolas Royer 1238bd3c7b5cSNicolas Royer for (i = 0; i < ARRAY_SIZE(aes_algs); i++) { 1239bd3c7b5cSNicolas Royer err = crypto_register_alg(&aes_algs[i]); 1240bd3c7b5cSNicolas Royer if (err) 1241bd3c7b5cSNicolas Royer goto err_aes_algs; 1242bd3c7b5cSNicolas Royer } 1243bd3c7b5cSNicolas Royer 1244cadc4ab8SNicolas Royer if (dd->caps.has_cfb64) { 1245cadc4ab8SNicolas Royer err = crypto_register_alg(&aes_cfb64_alg); 1246bd3c7b5cSNicolas Royer if (err) 1247bd3c7b5cSNicolas Royer goto err_aes_cfb64_alg; 1248bd3c7b5cSNicolas Royer } 1249bd3c7b5cSNicolas Royer 1250bd3c7b5cSNicolas Royer return 0; 1251bd3c7b5cSNicolas Royer 1252bd3c7b5cSNicolas Royer err_aes_cfb64_alg: 1253bd3c7b5cSNicolas Royer i = ARRAY_SIZE(aes_algs); 1254bd3c7b5cSNicolas Royer err_aes_algs: 1255bd3c7b5cSNicolas Royer for (j = 0; j < i; j++) 1256bd3c7b5cSNicolas Royer crypto_unregister_alg(&aes_algs[j]); 1257bd3c7b5cSNicolas Royer 1258bd3c7b5cSNicolas Royer return err; 1259bd3c7b5cSNicolas Royer } 1260bd3c7b5cSNicolas Royer 1261cadc4ab8SNicolas Royer static void atmel_aes_get_cap(struct atmel_aes_dev *dd) 1262cadc4ab8SNicolas Royer { 1263cadc4ab8SNicolas Royer dd->caps.has_dualbuff = 0; 1264cadc4ab8SNicolas Royer dd->caps.has_cfb64 = 0; 1265cadc4ab8SNicolas Royer dd->caps.max_burst_size = 1; 1266cadc4ab8SNicolas Royer 1267cadc4ab8SNicolas Royer /* keep only major version number */ 1268cadc4ab8SNicolas Royer switch (dd->hw_version & 0xff0) { 1269973e209dSLeilei Zhao case 0x500: 1270973e209dSLeilei Zhao dd->caps.has_dualbuff = 1; 1271973e209dSLeilei Zhao dd->caps.has_cfb64 = 1; 1272973e209dSLeilei Zhao dd->caps.max_burst_size = 4; 1273973e209dSLeilei Zhao break; 1274cf1f0d12SLeilei Zhao case 0x200: 1275cf1f0d12SLeilei Zhao dd->caps.has_dualbuff = 1; 1276cf1f0d12SLeilei Zhao dd->caps.has_cfb64 = 1; 1277cf1f0d12SLeilei Zhao dd->caps.max_burst_size = 4; 1278cf1f0d12SLeilei Zhao break; 1279cadc4ab8SNicolas Royer case 0x130: 1280cadc4ab8SNicolas Royer dd->caps.has_dualbuff = 1; 1281cadc4ab8SNicolas Royer dd->caps.has_cfb64 = 1; 1282cadc4ab8SNicolas Royer dd->caps.max_burst_size = 4; 1283cadc4ab8SNicolas Royer break; 1284cadc4ab8SNicolas Royer case 0x120: 1285cadc4ab8SNicolas Royer break; 1286cadc4ab8SNicolas Royer default: 1287cadc4ab8SNicolas Royer dev_warn(dd->dev, 1288cadc4ab8SNicolas Royer "Unmanaged aes version, set minimum capabilities\n"); 1289cadc4ab8SNicolas Royer break; 1290cadc4ab8SNicolas Royer } 1291cadc4ab8SNicolas Royer } 1292cadc4ab8SNicolas Royer 1293be943c7dSNicolas Ferre #if defined(CONFIG_OF) 1294be943c7dSNicolas Ferre static const struct of_device_id atmel_aes_dt_ids[] = { 1295be943c7dSNicolas Ferre { .compatible = "atmel,at91sam9g46-aes" }, 1296be943c7dSNicolas Ferre { /* sentinel */ } 1297be943c7dSNicolas Ferre }; 1298be943c7dSNicolas Ferre MODULE_DEVICE_TABLE(of, atmel_aes_dt_ids); 1299be943c7dSNicolas Ferre 1300be943c7dSNicolas Ferre static struct crypto_platform_data *atmel_aes_of_init(struct platform_device *pdev) 1301be943c7dSNicolas Ferre { 1302be943c7dSNicolas Ferre struct device_node *np = pdev->dev.of_node; 1303be943c7dSNicolas Ferre struct crypto_platform_data *pdata; 1304be943c7dSNicolas Ferre 1305be943c7dSNicolas Ferre if (!np) { 1306be943c7dSNicolas Ferre dev_err(&pdev->dev, "device node not found\n"); 1307be943c7dSNicolas Ferre return ERR_PTR(-EINVAL); 1308be943c7dSNicolas Ferre } 1309be943c7dSNicolas Ferre 1310be943c7dSNicolas Ferre pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 1311be943c7dSNicolas Ferre if (!pdata) { 1312be943c7dSNicolas Ferre dev_err(&pdev->dev, "could not allocate memory for pdata\n"); 1313be943c7dSNicolas Ferre return ERR_PTR(-ENOMEM); 1314be943c7dSNicolas Ferre } 1315be943c7dSNicolas Ferre 1316be943c7dSNicolas Ferre pdata->dma_slave = devm_kzalloc(&pdev->dev, 1317be943c7dSNicolas Ferre sizeof(*(pdata->dma_slave)), 1318be943c7dSNicolas Ferre GFP_KERNEL); 1319be943c7dSNicolas Ferre if (!pdata->dma_slave) { 1320be943c7dSNicolas Ferre dev_err(&pdev->dev, "could not allocate memory for dma_slave\n"); 1321be943c7dSNicolas Ferre devm_kfree(&pdev->dev, pdata); 1322be943c7dSNicolas Ferre return ERR_PTR(-ENOMEM); 1323be943c7dSNicolas Ferre } 1324be943c7dSNicolas Ferre 1325be943c7dSNicolas Ferre return pdata; 1326be943c7dSNicolas Ferre } 1327be943c7dSNicolas Ferre #else 1328be943c7dSNicolas Ferre static inline struct crypto_platform_data *atmel_aes_of_init(struct platform_device *pdev) 1329be943c7dSNicolas Ferre { 1330be943c7dSNicolas Ferre return ERR_PTR(-EINVAL); 1331be943c7dSNicolas Ferre } 1332be943c7dSNicolas Ferre #endif 1333be943c7dSNicolas Ferre 133449cfe4dbSGreg Kroah-Hartman static int atmel_aes_probe(struct platform_device *pdev) 1335bd3c7b5cSNicolas Royer { 1336bd3c7b5cSNicolas Royer struct atmel_aes_dev *aes_dd; 1337cadc4ab8SNicolas Royer struct crypto_platform_data *pdata; 1338bd3c7b5cSNicolas Royer struct device *dev = &pdev->dev; 1339bd3c7b5cSNicolas Royer struct resource *aes_res; 1340bd3c7b5cSNicolas Royer int err; 1341bd3c7b5cSNicolas Royer 1342bd3c7b5cSNicolas Royer pdata = pdev->dev.platform_data; 1343bd3c7b5cSNicolas Royer if (!pdata) { 1344be943c7dSNicolas Ferre pdata = atmel_aes_of_init(pdev); 1345be943c7dSNicolas Ferre if (IS_ERR(pdata)) { 1346be943c7dSNicolas Ferre err = PTR_ERR(pdata); 1347be943c7dSNicolas Ferre goto aes_dd_err; 1348be943c7dSNicolas Ferre } 1349be943c7dSNicolas Ferre } 1350be943c7dSNicolas Ferre 1351be943c7dSNicolas Ferre if (!pdata->dma_slave) { 1352bd3c7b5cSNicolas Royer err = -ENXIO; 1353bd3c7b5cSNicolas Royer goto aes_dd_err; 1354bd3c7b5cSNicolas Royer } 1355bd3c7b5cSNicolas Royer 1356b0e8b341SLABBE Corentin aes_dd = devm_kzalloc(&pdev->dev, sizeof(*aes_dd), GFP_KERNEL); 1357bd3c7b5cSNicolas Royer if (aes_dd == NULL) { 1358bd3c7b5cSNicolas Royer dev_err(dev, "unable to alloc data struct.\n"); 1359bd3c7b5cSNicolas Royer err = -ENOMEM; 1360bd3c7b5cSNicolas Royer goto aes_dd_err; 1361bd3c7b5cSNicolas Royer } 1362bd3c7b5cSNicolas Royer 1363bd3c7b5cSNicolas Royer aes_dd->dev = dev; 1364bd3c7b5cSNicolas Royer 1365bd3c7b5cSNicolas Royer platform_set_drvdata(pdev, aes_dd); 1366bd3c7b5cSNicolas Royer 1367bd3c7b5cSNicolas Royer INIT_LIST_HEAD(&aes_dd->list); 13688a10eb8dSLeilei Zhao spin_lock_init(&aes_dd->lock); 1369bd3c7b5cSNicolas Royer 1370bd3c7b5cSNicolas Royer tasklet_init(&aes_dd->done_task, atmel_aes_done_task, 1371bd3c7b5cSNicolas Royer (unsigned long)aes_dd); 1372bd3c7b5cSNicolas Royer tasklet_init(&aes_dd->queue_task, atmel_aes_queue_task, 1373bd3c7b5cSNicolas Royer (unsigned long)aes_dd); 1374bd3c7b5cSNicolas Royer 1375bd3c7b5cSNicolas Royer crypto_init_queue(&aes_dd->queue, ATMEL_AES_QUEUE_LENGTH); 1376bd3c7b5cSNicolas Royer 1377bd3c7b5cSNicolas Royer aes_dd->irq = -1; 1378bd3c7b5cSNicolas Royer 1379bd3c7b5cSNicolas Royer /* Get the base address */ 1380bd3c7b5cSNicolas Royer aes_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1381bd3c7b5cSNicolas Royer if (!aes_res) { 1382bd3c7b5cSNicolas Royer dev_err(dev, "no MEM resource info\n"); 1383bd3c7b5cSNicolas Royer err = -ENODEV; 1384bd3c7b5cSNicolas Royer goto res_err; 1385bd3c7b5cSNicolas Royer } 1386bd3c7b5cSNicolas Royer aes_dd->phys_base = aes_res->start; 1387bd3c7b5cSNicolas Royer 1388bd3c7b5cSNicolas Royer /* Get the IRQ */ 1389bd3c7b5cSNicolas Royer aes_dd->irq = platform_get_irq(pdev, 0); 1390bd3c7b5cSNicolas Royer if (aes_dd->irq < 0) { 1391bd3c7b5cSNicolas Royer dev_err(dev, "no IRQ resource info\n"); 1392bd3c7b5cSNicolas Royer err = aes_dd->irq; 1393b0e8b341SLABBE Corentin goto res_err; 1394bd3c7b5cSNicolas Royer } 1395bd3c7b5cSNicolas Royer 1396b0e8b341SLABBE Corentin err = devm_request_irq(&pdev->dev, aes_dd->irq, atmel_aes_irq, 1397b0e8b341SLABBE Corentin IRQF_SHARED, "atmel-aes", aes_dd); 1398bd3c7b5cSNicolas Royer if (err) { 1399bd3c7b5cSNicolas Royer dev_err(dev, "unable to request aes irq.\n"); 1400b0e8b341SLABBE Corentin goto res_err; 1401bd3c7b5cSNicolas Royer } 1402bd3c7b5cSNicolas Royer 1403bd3c7b5cSNicolas Royer /* Initializing the clock */ 1404b0e8b341SLABBE Corentin aes_dd->iclk = devm_clk_get(&pdev->dev, "aes_clk"); 1405bd3c7b5cSNicolas Royer if (IS_ERR(aes_dd->iclk)) { 1406be208356SColin Ian King dev_err(dev, "clock initialization failed.\n"); 1407bd3c7b5cSNicolas Royer err = PTR_ERR(aes_dd->iclk); 1408b0e8b341SLABBE Corentin goto res_err; 1409bd3c7b5cSNicolas Royer } 1410bd3c7b5cSNicolas Royer 1411b0e8b341SLABBE Corentin aes_dd->io_base = devm_ioremap_resource(&pdev->dev, aes_res); 1412bd3c7b5cSNicolas Royer if (!aes_dd->io_base) { 1413bd3c7b5cSNicolas Royer dev_err(dev, "can't ioremap\n"); 1414bd3c7b5cSNicolas Royer err = -ENOMEM; 1415b0e8b341SLABBE Corentin goto res_err; 1416bd3c7b5cSNicolas Royer } 1417bd3c7b5cSNicolas Royer 1418aab0a39bSCyrille Pitchen err = atmel_aes_hw_version_init(aes_dd); 1419aab0a39bSCyrille Pitchen if (err) 1420aab0a39bSCyrille Pitchen goto res_err; 1421cadc4ab8SNicolas Royer 1422cadc4ab8SNicolas Royer atmel_aes_get_cap(aes_dd); 1423cadc4ab8SNicolas Royer 1424cadc4ab8SNicolas Royer err = atmel_aes_buff_init(aes_dd); 1425cadc4ab8SNicolas Royer if (err) 1426cadc4ab8SNicolas Royer goto err_aes_buff; 1427cadc4ab8SNicolas Royer 1428cadc4ab8SNicolas Royer err = atmel_aes_dma_init(aes_dd, pdata); 1429bd3c7b5cSNicolas Royer if (err) 1430bd3c7b5cSNicolas Royer goto err_aes_dma; 1431bd3c7b5cSNicolas Royer 1432bd3c7b5cSNicolas Royer spin_lock(&atmel_aes.lock); 1433bd3c7b5cSNicolas Royer list_add_tail(&aes_dd->list, &atmel_aes.dev_list); 1434bd3c7b5cSNicolas Royer spin_unlock(&atmel_aes.lock); 1435bd3c7b5cSNicolas Royer 1436bd3c7b5cSNicolas Royer err = atmel_aes_register_algs(aes_dd); 1437bd3c7b5cSNicolas Royer if (err) 1438bd3c7b5cSNicolas Royer goto err_algs; 1439bd3c7b5cSNicolas Royer 1440be943c7dSNicolas Ferre dev_info(dev, "Atmel AES - Using %s, %s for DMA transfers\n", 1441bbe628edSCyrille Pitchen dma_chan_name(aes_dd->src.chan), 1442bbe628edSCyrille Pitchen dma_chan_name(aes_dd->dst.chan)); 1443bd3c7b5cSNicolas Royer 1444bd3c7b5cSNicolas Royer return 0; 1445bd3c7b5cSNicolas Royer 1446bd3c7b5cSNicolas Royer err_algs: 1447bd3c7b5cSNicolas Royer spin_lock(&atmel_aes.lock); 1448bd3c7b5cSNicolas Royer list_del(&aes_dd->list); 1449bd3c7b5cSNicolas Royer spin_unlock(&atmel_aes.lock); 1450bd3c7b5cSNicolas Royer atmel_aes_dma_cleanup(aes_dd); 1451bd3c7b5cSNicolas Royer err_aes_dma: 1452cadc4ab8SNicolas Royer atmel_aes_buff_cleanup(aes_dd); 1453cadc4ab8SNicolas Royer err_aes_buff: 1454bd3c7b5cSNicolas Royer res_err: 1455bd3c7b5cSNicolas Royer tasklet_kill(&aes_dd->done_task); 1456bd3c7b5cSNicolas Royer tasklet_kill(&aes_dd->queue_task); 1457bd3c7b5cSNicolas Royer aes_dd_err: 1458bd3c7b5cSNicolas Royer dev_err(dev, "initialization failed.\n"); 1459bd3c7b5cSNicolas Royer 1460bd3c7b5cSNicolas Royer return err; 1461bd3c7b5cSNicolas Royer } 1462bd3c7b5cSNicolas Royer 146349cfe4dbSGreg Kroah-Hartman static int atmel_aes_remove(struct platform_device *pdev) 1464bd3c7b5cSNicolas Royer { 1465bd3c7b5cSNicolas Royer static struct atmel_aes_dev *aes_dd; 1466bd3c7b5cSNicolas Royer 1467bd3c7b5cSNicolas Royer aes_dd = platform_get_drvdata(pdev); 1468bd3c7b5cSNicolas Royer if (!aes_dd) 1469bd3c7b5cSNicolas Royer return -ENODEV; 1470bd3c7b5cSNicolas Royer spin_lock(&atmel_aes.lock); 1471bd3c7b5cSNicolas Royer list_del(&aes_dd->list); 1472bd3c7b5cSNicolas Royer spin_unlock(&atmel_aes.lock); 1473bd3c7b5cSNicolas Royer 1474bd3c7b5cSNicolas Royer atmel_aes_unregister_algs(aes_dd); 1475bd3c7b5cSNicolas Royer 1476bd3c7b5cSNicolas Royer tasklet_kill(&aes_dd->done_task); 1477bd3c7b5cSNicolas Royer tasklet_kill(&aes_dd->queue_task); 1478bd3c7b5cSNicolas Royer 1479bd3c7b5cSNicolas Royer atmel_aes_dma_cleanup(aes_dd); 14802a377828SCyrille Pitchen atmel_aes_buff_cleanup(aes_dd); 1481bd3c7b5cSNicolas Royer 1482bd3c7b5cSNicolas Royer return 0; 1483bd3c7b5cSNicolas Royer } 1484bd3c7b5cSNicolas Royer 1485bd3c7b5cSNicolas Royer static struct platform_driver atmel_aes_driver = { 1486bd3c7b5cSNicolas Royer .probe = atmel_aes_probe, 148749cfe4dbSGreg Kroah-Hartman .remove = atmel_aes_remove, 1488bd3c7b5cSNicolas Royer .driver = { 1489bd3c7b5cSNicolas Royer .name = "atmel_aes", 1490be943c7dSNicolas Ferre .of_match_table = of_match_ptr(atmel_aes_dt_ids), 1491bd3c7b5cSNicolas Royer }, 1492bd3c7b5cSNicolas Royer }; 1493bd3c7b5cSNicolas Royer 1494bd3c7b5cSNicolas Royer module_platform_driver(atmel_aes_driver); 1495bd3c7b5cSNicolas Royer 1496bd3c7b5cSNicolas Royer MODULE_DESCRIPTION("Atmel AES hw acceleration support."); 1497bd3c7b5cSNicolas Royer MODULE_LICENSE("GPL v2"); 1498bd3c7b5cSNicolas Royer MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique"); 1499