1537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin/* 2537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * Cryptographic API. 3537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * 4537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * Support for OMAP AES HW acceleration. 5537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * 6537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * Copyright (c) 2010 Nokia Corporation 7537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com> 8537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * 9537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * This program is free software; you can redistribute it and/or modify 10537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * it under the terms of the GNU General Public License version 2 as published 11537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * by the Free Software Foundation. 12537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * 13537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin */ 14537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 15537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define pr_fmt(fmt) "%s: " fmt, __func__ 16537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 17537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/err.h> 18537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/module.h> 19537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/init.h> 20537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/errno.h> 21537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/kernel.h> 22537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/clk.h> 23537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/platform_device.h> 24537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/scatterlist.h> 25537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/dma-mapping.h> 26537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/io.h> 27537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/crypto.h> 28537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/interrupt.h> 29537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <crypto/scatterwalk.h> 30537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <crypto/aes.h> 31537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 32537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <plat/cpu.h> 33537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <plat/dma.h> 34537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 35537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin/* OMAP TRM gives bitfields as start:end, where start is the higher bit 36537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin number. For example 7:0 */ 37537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end)) 38537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end)) 39537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 40537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_KEY(x) (0x1C - ((x ^ 0x01) * 0x04)) 41537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_IV(x) (0x20 + ((x) * 0x04)) 42537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 43537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL 0x30 44537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_CTR_WIDTH (1 << 7) 45537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_CTR (1 << 6) 46537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_CBC (1 << 5) 47537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_KEY_SIZE (3 << 3) 48537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_DIRECTION (1 << 2) 49537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_INPUT_READY (1 << 1) 50537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_OUTPUT_READY (1 << 0) 51537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 52537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_DATA 0x34 53537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_DATA_N(x) (0x34 + ((x) * 0x04)) 54537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 55537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_REV 0x44 56537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_REV_MAJOR 0xF0 57537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_REV_MINOR 0x0F 58537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 59537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_MASK 0x48 60537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_MASK_SIDLE (1 << 6) 61537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_MASK_START (1 << 5) 62537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_MASK_DMA_OUT_EN (1 << 3) 63537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_MASK_DMA_IN_EN (1 << 2) 64537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_MASK_SOFTRESET (1 << 1) 65537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_AUTOIDLE (1 << 0) 66537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 67537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_SYSSTATUS 0x4C 68537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_SYSSTATUS_RESETDONE (1 << 0) 69537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 70537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define DEFAULT_TIMEOUT (5*HZ) 71537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 72537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLAGS_MODE_MASK 0x000f 73537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLAGS_ENCRYPT BIT(0) 74537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLAGS_CBC BIT(1) 75537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLAGS_GIV BIT(2) 76537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 7767a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin#define FLAGS_INIT BIT(4) 7867a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin#define FLAGS_FAST BIT(5) 7967a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin#define FLAGS_BUSY BIT(6) 80537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 81537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstruct omap_aes_ctx { 82537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_dev *dd; 83537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 84537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin int keylen; 85537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin u32 key[AES_KEYSIZE_256 / sizeof(u32)]; 86537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin unsigned long flags; 87537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}; 88537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 89537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstruct omap_aes_reqctx { 90537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin unsigned long mode; 91537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}; 92537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 93537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define OMAP_AES_QUEUE_LENGTH 1 94537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define OMAP_AES_CACHE_SIZE 0 95537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 96537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstruct omap_aes_dev { 97537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct list_head list; 98537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin unsigned long phys_base; 99efce41b65f66251d60484781df305e8a85c9507bDmitry Kasatkin void __iomem *io_base; 100537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct clk *iclk; 101537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_ctx *ctx; 102537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct device *dev; 103537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin unsigned long flags; 10421fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin int err; 105537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 10621fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin spinlock_t lock; 10721fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin struct crypto_queue queue; 108537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 10921fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin struct tasklet_struct done_task; 11021fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin struct tasklet_struct queue_task; 111537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 112537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct ablkcipher_request *req; 113537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin size_t total; 114537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct scatterlist *in_sg; 115537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin size_t in_offset; 116537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct scatterlist *out_sg; 117537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin size_t out_offset; 118537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 119537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin size_t buflen; 120537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin void *buf_in; 121537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin size_t dma_size; 122537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin int dma_in; 123537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin int dma_lch_in; 124537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_addr_t dma_addr_in; 125537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin void *buf_out; 126537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin int dma_out; 127537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin int dma_lch_out; 128537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_addr_t dma_addr_out; 129537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}; 130537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 131537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin/* keep registered devices data here */ 132537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic LIST_HEAD(dev_list); 133537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic DEFINE_SPINLOCK(list_lock); 134537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 135537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic inline u32 omap_aes_read(struct omap_aes_dev *dd, u32 offset) 136537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 137537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return __raw_readl(dd->io_base + offset); 138537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 139537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 140537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic inline void omap_aes_write(struct omap_aes_dev *dd, u32 offset, 141537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin u32 value) 142537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 143537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin __raw_writel(value, dd->io_base + offset); 144537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 145537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 146537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic inline void omap_aes_write_mask(struct omap_aes_dev *dd, u32 offset, 147537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin u32 value, u32 mask) 148537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 149537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin u32 val; 150537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 151537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin val = omap_aes_read(dd, offset); 152537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin val &= ~mask; 153537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin val |= value; 154537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_aes_write(dd, offset, val); 155537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 156537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 157537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void omap_aes_write_n(struct omap_aes_dev *dd, u32 offset, 158537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin u32 *value, int count) 159537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 160537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin for (; count--; value++, offset += 4) 161537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_aes_write(dd, offset, *value); 162537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 163537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 164537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_wait(struct omap_aes_dev *dd, u32 offset, u32 bit) 165537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 166537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin unsigned long timeout = jiffies + DEFAULT_TIMEOUT; 167537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 168537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin while (!(omap_aes_read(dd, offset) & bit)) { 169537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (time_is_before_jiffies(timeout)) { 170537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dd->dev, "omap-aes timeout\n"); 171537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return -ETIMEDOUT; 172537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 173537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 174537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return 0; 175537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 176537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 177537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_hw_init(struct omap_aes_dev *dd) 178537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 17983ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin /* 18083ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin * clocks are enabled when request starts and disabled when finished. 18183ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin * It may be long delays between requests. 18283ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin * Device might go to off mode to save power. 18383ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin */ 184537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin clk_enable(dd->iclk); 185eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin 186537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!(dd->flags & FLAGS_INIT)) { 187537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* is it necessary to reset before every operation? */ 188537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET, 189537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin AES_REG_MASK_SOFTRESET); 190537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* 191537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * prevent OCP bus error (SRESP) in case an access to the module 192537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * is performed while the module is coming out of soft reset 193537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin */ 194537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin __asm__ __volatile__("nop"); 195537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin __asm__ __volatile__("nop"); 196537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 197eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin if (omap_aes_wait(dd, AES_REG_SYSSTATUS, 19883ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin AES_REG_SYSSTATUS_RESETDONE)) 199eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin return -ETIMEDOUT; 20083ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin 201eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin dd->flags |= FLAGS_INIT; 20221fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin dd->err = 0; 203537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 204537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 205eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin return 0; 206537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 207537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 20821fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkinstatic int omap_aes_write_ctrl(struct omap_aes_dev *dd) 209537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 210537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin unsigned int key32; 21167a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin int i, err; 212537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin u32 val, mask; 213537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 21421fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin err = omap_aes_hw_init(dd); 21521fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin if (err) 21621fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin return err; 21721fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin 218537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin val = 0; 219537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (dd->dma_lch_out >= 0) 220537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin val |= AES_REG_MASK_DMA_OUT_EN; 221537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (dd->dma_lch_in >= 0) 222537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin val |= AES_REG_MASK_DMA_IN_EN; 223537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 224537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin mask = AES_REG_MASK_DMA_IN_EN | AES_REG_MASK_DMA_OUT_EN; 225537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 226537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_aes_write_mask(dd, AES_REG_MASK, val, mask); 227537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 228537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin key32 = dd->ctx->keylen / sizeof(u32); 22967a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin 23067a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin /* it seems a key should always be set even if it has not changed */ 231537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin for (i = 0; i < key32; i++) { 232537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_aes_write(dd, AES_REG_KEY(i), 233537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin __le32_to_cpu(dd->ctx->key[i])); 234537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 235537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 23667a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin if ((dd->flags & FLAGS_CBC) && dd->req->info) 23767a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin omap_aes_write_n(dd, AES_REG_IV(0), dd->req->info, 4); 23867a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin 23967a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3); 24067a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin if (dd->flags & FLAGS_CBC) 24167a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin val |= AES_REG_CTRL_CBC; 24267a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin if (dd->flags & FLAGS_ENCRYPT) 24367a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin val |= AES_REG_CTRL_DIRECTION; 244537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 245537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION | 246537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin AES_REG_CTRL_KEY_SIZE; 247537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 24867a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin omap_aes_write_mask(dd, AES_REG_CTRL, val, mask); 249537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 25083ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin /* IN */ 25183ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT, 25283ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin dd->phys_base + AES_REG_DATA, 0, 4); 25383ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin 25483ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4); 25583ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4); 25683ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin 25783ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin /* OUT */ 25883ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT, 25983ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin dd->phys_base + AES_REG_DATA, 0, 4); 26083ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin 26183ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4); 26283ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4); 26321fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin 26421fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin return 0; 265537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 266537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 267537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx) 268537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 269537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_dev *dd = NULL, *tmp; 270537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 271537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin spin_lock_bh(&list_lock); 272537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!ctx->dd) { 273537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin list_for_each_entry(tmp, &dev_list, list) { 274537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* FIXME: take fist available aes core */ 275537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd = tmp; 276537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin break; 277537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 278537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin ctx->dd = dd; 279537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } else { 280537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* already found before */ 281537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd = ctx->dd; 282537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 283537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin spin_unlock_bh(&list_lock); 284537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 285537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return dd; 286537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 287537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 288537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void omap_aes_dma_callback(int lch, u16 ch_status, void *data) 289537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 290537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_dev *dd = data; 291537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 29221fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin if (ch_status != OMAP_DMA_BLOCK_IRQ) { 29321fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin pr_err("omap-aes DMA error status: 0x%hx\n", ch_status); 29421fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin dd->err = -EIO; 29521fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin dd->flags &= ~FLAGS_INIT; /* request to re-initialize */ 29621fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin } else if (lch == dd->dma_lch_in) { 29721fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin return; 29821fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin } 29921fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin 30021fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin /* dma_lch_out - completed */ 30121fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin tasklet_schedule(&dd->done_task); 302537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 303537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 304537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_dma_init(struct omap_aes_dev *dd) 305537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 306537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin int err = -ENOMEM; 307537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 308537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->dma_lch_out = -1; 309537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->dma_lch_in = -1; 310537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 311537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE); 312537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE); 313537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->buflen = PAGE_SIZE << OMAP_AES_CACHE_SIZE; 314537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->buflen &= ~(AES_BLOCK_SIZE - 1); 315537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 316537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!dd->buf_in || !dd->buf_out) { 317537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dd->dev, "unable to alloc pages.\n"); 318537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin goto err_alloc; 319537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 320537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 321537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* MAP here */ 322537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in, dd->buflen, 323537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin DMA_TO_DEVICE); 324537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (dma_mapping_error(dd->dev, dd->dma_addr_in)) { 325537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dd->dev, "dma %d bytes error\n", dd->buflen); 326537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin err = -EINVAL; 327537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin goto err_map_in; 328537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 329537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 330537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out, dd->buflen, 331537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin DMA_FROM_DEVICE); 332537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (dma_mapping_error(dd->dev, dd->dma_addr_out)) { 333537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dd->dev, "dma %d bytes error\n", dd->buflen); 334537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin err = -EINVAL; 335537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin goto err_map_out; 336537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 337537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 338537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin err = omap_request_dma(dd->dma_in, "omap-aes-rx", 339537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_aes_dma_callback, dd, &dd->dma_lch_in); 340537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (err) { 341537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dd->dev, "Unable to request DMA channel\n"); 342537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin goto err_dma_in; 343537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 344537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin err = omap_request_dma(dd->dma_out, "omap-aes-tx", 345537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_aes_dma_callback, dd, &dd->dma_lch_out); 346537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (err) { 347537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dd->dev, "Unable to request DMA channel\n"); 348537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin goto err_dma_out; 349537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 350537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 351537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return 0; 352537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 353537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_dma_out: 354537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_free_dma(dd->dma_lch_in); 355537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_dma_in: 356537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen, 357537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin DMA_FROM_DEVICE); 358537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_map_out: 359537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, DMA_TO_DEVICE); 360537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_map_in: 361537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin free_pages((unsigned long)dd->buf_out, OMAP_AES_CACHE_SIZE); 362537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin free_pages((unsigned long)dd->buf_in, OMAP_AES_CACHE_SIZE); 363537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_alloc: 364537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (err) 365537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_err("error: %d\n", err); 366537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return err; 367537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 368537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 369537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void omap_aes_dma_cleanup(struct omap_aes_dev *dd) 370537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 371537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_free_dma(dd->dma_lch_out); 372537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_free_dma(dd->dma_lch_in); 373537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen, 374537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin DMA_FROM_DEVICE); 375537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, DMA_TO_DEVICE); 376537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin free_pages((unsigned long)dd->buf_out, OMAP_AES_CACHE_SIZE); 377537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin free_pages((unsigned long)dd->buf_in, OMAP_AES_CACHE_SIZE); 378537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 379537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 380537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void sg_copy_buf(void *buf, struct scatterlist *sg, 381537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin unsigned int start, unsigned int nbytes, int out) 382537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 383537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct scatter_walk walk; 384537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 385537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!nbytes) 386537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return; 387537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 388537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin scatterwalk_start(&walk, sg); 389537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin scatterwalk_advance(&walk, start); 390537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin scatterwalk_copychunks(buf, &walk, nbytes, out); 391537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin scatterwalk_done(&walk, out, 0); 392537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 393537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 394537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int sg_copy(struct scatterlist **sg, size_t *offset, void *buf, 395537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin size_t buflen, size_t total, int out) 396537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 397537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin unsigned int count, off = 0; 398537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 399537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin while (buflen && total) { 400537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin count = min((*sg)->length - *offset, total); 401537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin count = min(count, buflen); 402537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 403537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!count) 404537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return off; 405537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 40621fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin /* 40721fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin * buflen and total are AES_BLOCK_SIZE size aligned, 40821fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin * so count should be also aligned 40921fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin */ 41021fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin 411537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin sg_copy_buf(buf + off, *sg, *offset, count, out); 412537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 413537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin off += count; 414537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin buflen -= count; 415537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin *offset += count; 416537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin total -= count; 417537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 418537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (*offset == (*sg)->length) { 419537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin *sg = sg_next(*sg); 420537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (*sg) 421537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin *offset = 0; 422537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin else 423537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin total = 0; 424537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 425537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 426537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 427537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return off; 428537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 429537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 430537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in, 431537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_addr_t dma_addr_out, int length) 432537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 433537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm); 434537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_dev *dd = ctx->dd; 435537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin int len32; 436537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 437537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_debug("len: %d\n", length); 438537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 439537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->dma_size = length; 440537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 441537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!(dd->flags & FLAGS_FAST)) 442537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_sync_single_for_device(dd->dev, dma_addr_in, length, 443537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin DMA_TO_DEVICE); 444537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 445537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin len32 = DIV_ROUND_UP(length, sizeof(u32)); 446537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 447537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* IN */ 448537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_set_dma_transfer_params(dd->dma_lch_in, OMAP_DMA_DATA_TYPE_S32, 449537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin len32, 1, OMAP_DMA_SYNC_PACKET, dd->dma_in, 450537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin OMAP_DMA_DST_SYNC); 451537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 452537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_set_dma_src_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_POST_INC, 453537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_addr_in, 0, 0); 454537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 455537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* OUT */ 456537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_set_dma_transfer_params(dd->dma_lch_out, OMAP_DMA_DATA_TYPE_S32, 457537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin len32, 1, OMAP_DMA_SYNC_PACKET, 458537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->dma_out, OMAP_DMA_SRC_SYNC); 459537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 460537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_set_dma_dest_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_POST_INC, 461537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_addr_out, 0, 0); 462537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 463537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_start_dma(dd->dma_lch_in); 464537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_start_dma(dd->dma_lch_out); 465537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 46683ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin /* start DMA or disable idle mode */ 46783ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START, 46883ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin AES_REG_MASK_START); 46983ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin 470537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return 0; 471537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 472537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 473537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_crypt_dma_start(struct omap_aes_dev *dd) 474537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 475537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct crypto_tfm *tfm = crypto_ablkcipher_tfm( 476537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin crypto_ablkcipher_reqtfm(dd->req)); 477537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin int err, fast = 0, in, out; 478537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin size_t count; 479537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_addr_t addr_in, addr_out; 480537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 481537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_debug("total: %d\n", dd->total); 482537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 483537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (sg_is_last(dd->in_sg) && sg_is_last(dd->out_sg)) { 484537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* check for alignment */ 485537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32)); 486537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32)); 487537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 488537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin fast = in && out; 489537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 490537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 491537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (fast) { 492537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin count = min(dd->total, sg_dma_len(dd->in_sg)); 493537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin count = min(count, sg_dma_len(dd->out_sg)); 494537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 49521fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin if (count != dd->total) { 49621fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin pr_err("request length != buffer length\n"); 497537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return -EINVAL; 49821fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin } 499537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 500537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_debug("fast\n"); 501537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 502537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); 503537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!err) { 504537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dd->dev, "dma_map_sg() error\n"); 505537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return -EINVAL; 506537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 507537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 508537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin err = dma_map_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE); 509537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!err) { 510537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dd->dev, "dma_map_sg() error\n"); 511537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); 512537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return -EINVAL; 513537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 514537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 515537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin addr_in = sg_dma_address(dd->in_sg); 516537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin addr_out = sg_dma_address(dd->out_sg); 517537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 518537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->flags |= FLAGS_FAST; 519537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 520537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } else { 521537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* use cache buffers */ 522537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin count = sg_copy(&dd->in_sg, &dd->in_offset, dd->buf_in, 523537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->buflen, dd->total, 0); 524537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 525537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin addr_in = dd->dma_addr_in; 526537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin addr_out = dd->dma_addr_out; 527537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 528537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->flags &= ~FLAGS_FAST; 529537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 530537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 531537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 532537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->total -= count; 533537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 534537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count); 53521fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin if (err) { 53621fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); 53721fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE); 53821fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin } 539537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 540537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return err; 541537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 542537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 543537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void omap_aes_finish_req(struct omap_aes_dev *dd, int err) 544537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 54521fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin struct ablkcipher_request *req = dd->req; 546537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 547537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_debug("err: %d\n", err); 548537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 54983ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin clk_disable(dd->iclk); 550eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin dd->flags &= ~FLAGS_BUSY; 551eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin 55267a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin req->base.complete(&req->base, err); 553537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 554537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 555537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) 556537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 557537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin int err = 0; 558537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin size_t count; 559537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 560537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_debug("total: %d\n", dd->total); 561537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 562537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START); 563537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 564537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_stop_dma(dd->dma_lch_in); 565537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_stop_dma(dd->dma_lch_out); 566537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 567537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (dd->flags & FLAGS_FAST) { 568537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE); 569537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); 570537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } else { 571537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dma_sync_single_for_device(dd->dev, dd->dma_addr_out, 572537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->dma_size, DMA_FROM_DEVICE); 573537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 574537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* copy data */ 575537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin count = sg_copy(&dd->out_sg, &dd->out_offset, dd->buf_out, 576537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->buflen, dd->dma_size, 1); 577537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (count != dd->dma_size) { 578537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin err = -EINVAL; 579537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_err("not all data converted: %u\n", count); 580537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 581537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 582537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 583537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return err; 584537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 585537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 58621fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkinstatic int omap_aes_handle_queue(struct omap_aes_dev *dd, 587eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin struct ablkcipher_request *req) 588537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 589537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct crypto_async_request *async_req, *backlog; 590537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_ctx *ctx; 591537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_reqctx *rctx; 592537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin unsigned long flags; 59321fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin int err, ret = 0; 594537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 595537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin spin_lock_irqsave(&dd->lock, flags); 596eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin if (req) 59721fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin ret = ablkcipher_enqueue_request(&dd->queue, req); 598eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin if (dd->flags & FLAGS_BUSY) { 599eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin spin_unlock_irqrestore(&dd->lock, flags); 60021fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin return ret; 601eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin } 602537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin backlog = crypto_get_backlog(&dd->queue); 603537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin async_req = crypto_dequeue_request(&dd->queue); 604eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin if (async_req) 605eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin dd->flags |= FLAGS_BUSY; 606537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin spin_unlock_irqrestore(&dd->lock, flags); 607537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 608537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!async_req) 60921fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin return ret; 610537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 611537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (backlog) 612537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin backlog->complete(backlog, -EINPROGRESS); 613537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 614537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin req = ablkcipher_request_cast(async_req); 615537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 616537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* assign new request to device */ 617537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->req = req; 618537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->total = req->nbytes; 619537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->in_offset = 0; 620537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->in_sg = req->src; 621537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->out_offset = 0; 622537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->out_sg = req->dst; 623537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 624537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin rctx = ablkcipher_request_ctx(req); 625537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req)); 626537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin rctx->mode &= FLAGS_MODE_MASK; 627537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode; 628537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 62967a730ce449561f6df838f0b38a2b72cbf4e3c4cDmitry Kasatkin dd->ctx = ctx; 630537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin ctx->dd = dd; 631537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 63283ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin err = omap_aes_write_ctrl(dd); 63383ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin if (!err) 63483ea7e0fe1471508ab8e8d7b317e743fe7a05a5fDmitry Kasatkin err = omap_aes_crypt_dma_start(dd); 63521fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin if (err) { 63621fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin /* aes_task will not finish it, so do it here */ 63721fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin omap_aes_finish_req(dd, err); 63821fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin tasklet_schedule(&dd->queue_task); 63921fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin } 640eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin 64121fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin return ret; /* return ret, which is enqueue return value */ 642537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 643537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 64421fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkinstatic void omap_aes_done_task(unsigned long data) 645537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 646537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_dev *dd = (struct omap_aes_dev *)data; 64721fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin int err; 648537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 649537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_debug("enter\n"); 650537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 65121fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin err = omap_aes_crypt_dma_stop(dd); 652537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 65321fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin err = dd->err ? : err; 65421fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin 65521fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin if (dd->total && !err) { 65621fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin err = omap_aes_crypt_dma_start(dd); 65721fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin if (!err) 65821fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin return; /* DMA started. Not fininishing. */ 65921fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin } 66021fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin 66121fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin omap_aes_finish_req(dd, err); 66221fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin omap_aes_handle_queue(dd, NULL); 663537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 664537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_debug("exit\n"); 665537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 666537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 66721fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkinstatic void omap_aes_queue_task(unsigned long data) 66821fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin{ 66921fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin struct omap_aes_dev *dd = (struct omap_aes_dev *)data; 67021fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin 67121fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin omap_aes_handle_queue(dd, NULL); 67221fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin} 67321fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin 674537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode) 675537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 676537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx( 677537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin crypto_ablkcipher_reqtfm(req)); 678537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req); 679537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_dev *dd; 680537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 681537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes, 682537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin !!(mode & FLAGS_ENCRYPT), 683537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin !!(mode & FLAGS_CBC)); 684537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 68521fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) { 68621fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin pr_err("request size is not exact amount of AES blocks\n"); 68721fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin return -EINVAL; 68821fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin } 68921fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin 690537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd = omap_aes_find_dev(ctx); 691537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!dd) 692537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return -ENODEV; 693537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 694537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin rctx->mode = mode; 695537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 69621fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin return omap_aes_handle_queue(dd, req); 697537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 698537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 699537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin/* ********************** ALG API ************************************ */ 700537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 701537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, 702537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin unsigned int keylen) 703537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 704537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); 705537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 706537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 && 707537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin keylen != AES_KEYSIZE_256) 708537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return -EINVAL; 709537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 710537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_debug("enter, keylen: %d\n", keylen); 711537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 712537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin memcpy(ctx->key, key, keylen); 713537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin ctx->keylen = keylen; 714537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 715537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return 0; 716537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 717537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 718537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_ecb_encrypt(struct ablkcipher_request *req) 719537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 720537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return omap_aes_crypt(req, FLAGS_ENCRYPT); 721537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 722537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 723537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_ecb_decrypt(struct ablkcipher_request *req) 724537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 725537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return omap_aes_crypt(req, 0); 726537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 727537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 728537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_cbc_encrypt(struct ablkcipher_request *req) 729537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 730537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return omap_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_CBC); 731537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 732537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 733537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_cbc_decrypt(struct ablkcipher_request *req) 734537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 735537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return omap_aes_crypt(req, FLAGS_CBC); 736537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 737537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 738537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_cra_init(struct crypto_tfm *tfm) 739537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 740537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_debug("enter\n"); 741537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 742537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin tfm->crt_ablkcipher.reqsize = sizeof(struct omap_aes_reqctx); 743537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 744537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return 0; 745537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 746537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 747537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void omap_aes_cra_exit(struct crypto_tfm *tfm) 748537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 749537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_debug("enter\n"); 750537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 751537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 752537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin/* ********************** ALGS ************************************ */ 753537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 754537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic struct crypto_alg algs[] = { 755537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 756537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_name = "ecb(aes)", 757537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_driver_name = "ecb-aes-omap", 758537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_priority = 100, 759d912bb7677f46d78a3cde8a4afd45a3fca4b34e9Nikos Mavrogiannopoulos .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 760d912bb7677f46d78a3cde8a4afd45a3fca4b34e9Nikos Mavrogiannopoulos CRYPTO_ALG_KERN_DRIVER_ONLY | 761d912bb7677f46d78a3cde8a4afd45a3fca4b34e9Nikos Mavrogiannopoulos CRYPTO_ALG_ASYNC, 762537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_blocksize = AES_BLOCK_SIZE, 763537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_ctxsize = sizeof(struct omap_aes_ctx), 764efce41b65f66251d60484781df305e8a85c9507bDmitry Kasatkin .cra_alignmask = 0, 765537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_type = &crypto_ablkcipher_type, 766537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_module = THIS_MODULE, 767537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_init = omap_aes_cra_init, 768537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_exit = omap_aes_cra_exit, 769537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_u.ablkcipher = { 770537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .min_keysize = AES_MIN_KEY_SIZE, 771537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .max_keysize = AES_MAX_KEY_SIZE, 772537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .setkey = omap_aes_setkey, 773537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .encrypt = omap_aes_ecb_encrypt, 774537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .decrypt = omap_aes_ecb_decrypt, 775537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 776537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}, 777537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 778537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_name = "cbc(aes)", 779537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_driver_name = "cbc-aes-omap", 780537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_priority = 100, 781d912bb7677f46d78a3cde8a4afd45a3fca4b34e9Nikos Mavrogiannopoulos .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 782d912bb7677f46d78a3cde8a4afd45a3fca4b34e9Nikos Mavrogiannopoulos CRYPTO_ALG_KERN_DRIVER_ONLY | 783d912bb7677f46d78a3cde8a4afd45a3fca4b34e9Nikos Mavrogiannopoulos CRYPTO_ALG_ASYNC, 784537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_blocksize = AES_BLOCK_SIZE, 785537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_ctxsize = sizeof(struct omap_aes_ctx), 786efce41b65f66251d60484781df305e8a85c9507bDmitry Kasatkin .cra_alignmask = 0, 787537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_type = &crypto_ablkcipher_type, 788537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_module = THIS_MODULE, 789537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_init = omap_aes_cra_init, 790537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_exit = omap_aes_cra_exit, 791537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .cra_u.ablkcipher = { 792537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .min_keysize = AES_MIN_KEY_SIZE, 793537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .max_keysize = AES_MAX_KEY_SIZE, 794537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .ivsize = AES_BLOCK_SIZE, 795537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .setkey = omap_aes_setkey, 796537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .encrypt = omap_aes_cbc_encrypt, 797537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .decrypt = omap_aes_cbc_decrypt, 798537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 799537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 800537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}; 801537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 802537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_probe(struct platform_device *pdev) 803537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 804537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct device *dev = &pdev->dev; 805537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_dev *dd; 806537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct resource *res; 807537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin int err = -ENOMEM, i, j; 808537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin u32 reg; 809537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 810537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd = kzalloc(sizeof(struct omap_aes_dev), GFP_KERNEL); 811537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (dd == NULL) { 812537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dev, "unable to alloc data struct.\n"); 813537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin goto err_data; 814537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 815537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->dev = dev; 816537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin platform_set_drvdata(pdev, dd); 817537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 818537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin spin_lock_init(&dd->lock); 819537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin crypto_init_queue(&dd->queue, OMAP_AES_QUEUE_LENGTH); 820537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 821537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* Get the base address */ 822537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 823537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!res) { 824537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dev, "invalid resource type\n"); 825537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin err = -ENODEV; 826537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin goto err_res; 827537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 828537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->phys_base = res->start; 829537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 830537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* Get the DMA */ 831537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin res = platform_get_resource(pdev, IORESOURCE_DMA, 0); 832537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!res) 833537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_info(dev, "no DMA info\n"); 834537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin else 835537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->dma_out = res->start; 836537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 837537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* Get the DMA */ 838537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin res = platform_get_resource(pdev, IORESOURCE_DMA, 1); 839537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!res) 840537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_info(dev, "no DMA info\n"); 841537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin else 842537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->dma_in = res->start; 843537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 844537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin /* Initializing the clock */ 845537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->iclk = clk_get(dev, "ick"); 8463e50191d981082345572f1e80b463eb9c05989a0Jamie Iles if (IS_ERR(dd->iclk)) { 847537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dev, "clock intialization failed.\n"); 8483e50191d981082345572f1e80b463eb9c05989a0Jamie Iles err = PTR_ERR(dd->iclk); 849537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin goto err_res; 850537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 851537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 852537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd->io_base = ioremap(dd->phys_base, SZ_4K); 853537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!dd->io_base) { 854537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dev, "can't ioremap\n"); 855537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin err = -ENOMEM; 856537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin goto err_io; 857537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 858537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 859537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin clk_enable(dd->iclk); 860537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin reg = omap_aes_read(dd, AES_REG_REV); 861537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_info(dev, "OMAP AES hw accel rev: %u.%u\n", 862537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin (reg & AES_REG_REV_MAJOR) >> 4, reg & AES_REG_REV_MINOR); 863537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin clk_disable(dd->iclk); 864537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 86521fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd); 86621fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin tasklet_init(&dd->queue_task, omap_aes_queue_task, (unsigned long)dd); 867537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 868537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin err = omap_aes_dma_init(dd); 869537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (err) 870537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin goto err_dma; 871537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 872537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin INIT_LIST_HEAD(&dd->list); 873537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin spin_lock(&list_lock); 874537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin list_add_tail(&dd->list, &dev_list); 875537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin spin_unlock(&list_lock); 876537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 877537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin for (i = 0; i < ARRAY_SIZE(algs); i++) { 878537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_debug("i: %d\n", i); 879537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin INIT_LIST_HEAD(&algs[i].cra_list); 880537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin err = crypto_register_alg(&algs[i]); 881537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (err) 882537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin goto err_algs; 883537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 884537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 885537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_info("probe() done\n"); 886537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 887537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return 0; 888537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_algs: 889537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin for (j = 0; j < i; j++) 890537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin crypto_unregister_alg(&algs[j]); 891537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_aes_dma_cleanup(dd); 892537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_dma: 89321fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin tasklet_kill(&dd->done_task); 89421fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin tasklet_kill(&dd->queue_task); 895537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin iounmap(dd->io_base); 896537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_io: 897537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin clk_put(dd->iclk); 898537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_res: 899537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin kfree(dd); 900537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd = NULL; 901537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_data: 902537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dev_err(dev, "initialization failed.\n"); 903537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return err; 904537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 905537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 906537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_remove(struct platform_device *pdev) 907537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 908537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin struct omap_aes_dev *dd = platform_get_drvdata(pdev); 909537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin int i; 910537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 911537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!dd) 912537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return -ENODEV; 913537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 914537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin spin_lock(&list_lock); 915537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin list_del(&dd->list); 916537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin spin_unlock(&list_lock); 917537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 918537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin for (i = 0; i < ARRAY_SIZE(algs); i++) 919537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin crypto_unregister_alg(&algs[i]); 920537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 92121fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin tasklet_kill(&dd->done_task); 92221fe9767f3bd56fd9a271dc43b93cd4608d47f4aDmitry Kasatkin tasklet_kill(&dd->queue_task); 923537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin omap_aes_dma_cleanup(dd); 924537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin iounmap(dd->io_base); 925537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin clk_put(dd->iclk); 926537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin kfree(dd); 927537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin dd = NULL; 928537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 929537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return 0; 930537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 931537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 932537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic struct platform_driver omap_aes_driver = { 933537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .probe = omap_aes_probe, 934537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .remove = omap_aes_remove, 935537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .driver = { 936537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .name = "omap-aes", 937537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin .owner = THIS_MODULE, 938537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin }, 939537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}; 940537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 941537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int __init omap_aes_mod_init(void) 942537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 943537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_info("loading %s driver\n", "omap-aes"); 944537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 945537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin if (!cpu_class_is_omap2() || omap_type() != OMAP2_DEVICE_TYPE_SEC) { 946537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin pr_err("Unsupported cpu\n"); 947537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return -ENODEV; 948537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin } 949537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 950537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin return platform_driver_register(&omap_aes_driver); 951537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 952537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 953537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void __exit omap_aes_mod_exit(void) 954537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{ 955537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin platform_driver_unregister(&omap_aes_driver); 956537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin} 957537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 958537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinmodule_init(omap_aes_mod_init); 959537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinmodule_exit(omap_aes_mod_exit); 960537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 961537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry KasatkinMODULE_DESCRIPTION("OMAP AES hw acceleration support."); 962537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry KasatkinMODULE_LICENSE("GPL v2"); 963537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry KasatkinMODULE_AUTHOR("Dmitry Kasatkin"); 964537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin 965