/*
* drivers/crypto/tegra-aes.c
*
* Driver for NVIDIA Tegra AES hardware engine residing inside the
* Bit Stream Engine for Video (BSEV) hardware block.
*
* The programming sequence for this engine is with the help
* of commands which travel via a command queue residing between the
* CPU and the BSEV block. The BSEV engine has an internal RAM (VRAM)
* where the final input plaintext, keys and the IV have to be copied
* before starting the encrypt/decrypt operation.
*
* Copyright (c) 2010, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
#include <mach/clk.h>
#include <crypto/scatterwalk.h>
#include <crypto/aes.h>
#include <crypto/internal/rng.h>
#include "tegra-aes.h"
#define FLAGS_MODE_MASK 0x00FF
#define FLAGS_ENCRYPT BIT(0)
#define FLAGS_CBC BIT(1)
#define FLAGS_GIV BIT(2)
#define FLAGS_RNG BIT(3)
#define FLAGS_OFB BIT(4)
#define FLAGS_NEW_KEY BIT(5)
#define FLAGS_NEW_IV BIT(6)
#define FLAGS_INIT BIT(7)
#define FLAGS_FAST BIT(8)
#define FLAGS_BUSY 9
/*
* Defines AES engine Max process bytes size in one go, which takes 1 msec.
* AES engine spends about 176 cycles/16-bytes or 11 cycles/byte
* The duration CPU can use the BSE to 1 msec, then the number of available
* cycles of AVP/BSE is 216K. In this duration, AES can process 216/11 ~= 19KB
* Based on this AES_HW_DMA_BUFFER_SIZE_BYTES is configured to 16KB.
*/
#define AES_HW_DMA_BUFFER_SIZE_BYTES 0x4000
/*
* The key table length is 64 bytes
* (This includes first upto 32 bytes key + 16 bytes original initial vector
* and 16 bytes updated initial vector)
*/
#define AES_HW_KEY_TABLE_LENGTH_BYTES 64
/*
* The memory being used is divides as follows:
* 1. Key - 32 bytes
* 2. Original IV - 16 bytes
* 3. Updated IV - 16 bytes
* 4. Key schedule - 256 bytes
*
* 1+2+3 constitute the hw key table.
*/
#define AES_HW_IV_SIZE 16
#define AES_HW_KEYSCHEDULE_LEN 256
#define AES_IVKEY_SIZE (AES_HW_KEY_TABLE_LENGTH_BYTES + AES_HW_KEYSCHEDULE_LEN)
/* Define commands required for AES operation */
enum {
CMD_BLKSTARTENGINE = 0x0E,
CMD_DMASETUP = 0x10,
CMD_DMACOMPLETE = 0x11,
CMD_SETTABLE = 0x15,
CMD_MEMDMAVD = 0x22,
};
/* Define sub-commands */
enum {
SUBCMD_VRAM_SEL = 0x1,
SUBCMD_CRYPTO_TABLE_SEL = 0x3,
SUBCMD_KEY_TABLE_SEL = 0x8,
};
/* memdma_vd command */
#define MEMDMA_DIR_DTOVRAM 0 /* sdram -> vram */
#define MEMDMA_DIR_VTODRAM 1 /* vram -> sdram */
#define MEMDMA_DIR_SHIFT 25
#define MEMDMA_NUM_WORDS_SHIFT 12
/* command queue bit shifts */
enum {
CMDQ_KEYTABLEADDR_SHIFT = 0,
CMDQ_KEYTABLEID_SHIFT = 17,
CMDQ_VRAMSEL_SHIFT = 23,
CMDQ_TABLESEL_SHIFT = 24,
CMDQ_OPCODE_SHIFT = 26,
};
/*
* The secure key slot contains a unique secure key generated
* and loaded by the bootloader. This slot is marked as non-accessible
* to the kernel.
*/
#define SSK_SLOT_NUM 4
#define AES_NR_KEYSLOTS 8
#define TEGRA_AES_QUEUE_LENGTH 50
#define DEFAULT_RNG_BLK_SZ 16
/* The command queue depth */
#define AES_HW_MAX_ICQ_LENGTH 5
struct tegra_aes_slot {
struct list_head node;
int slot_num;
};
static struct tegra_aes_slot ssk = {
.slot_num = SSK_SLOT_NUM,
};
struct tegra_aes_reqctx {
unsigned long mode;
};
struct tegra_aes_dev {
struct device *dev;
void __iomem *io_base;
dma_addr_t ivkey_phys_base;
void __iomem *ivkey_base;
struct clk *aes_clk;
struct tegra_aes_ctx *ctx;
int irq;
unsigned long flags;
struct completion op_complete;
u32 *buf_in;
dma_addr_t dma_buf_in;
u32 *buf_out;
dma_addr_t dma_buf_out;
u8 *iv;
u8 dt[DEFAULT_RNG_BLK_SZ];
int ivlen;
u64 ctr;
spinlock_t lock;
struct crypto_queue queue;
struct tegra_aes_slot *slots;
struct ablkcipher_request *req;
size_t total;
struct scatterlist *in_sg;
size_t in_offset;
struct scatterlist *out_sg;
size_t out_offset;
};
static struct tegra_aes_dev *aes_dev;
struct tegra_aes_ctx {
struct tegra_aes_dev *dd;
unsigned long flags;
struct tegra_aes_slot *slot;
u8 key[AES_MAX_KEY_SIZE];
size_t keylen;
};
static struct tegra_aes_ctx rng_ctx = {
.flags = FLAGS_NEW_KEY,
.keylen = AES_KEYSIZE_128,
};
/* keep registered devices data here */
static struct list_head dev_list;
static DEFINE_SPINLOCK(list_lock);
static DEFINE_MUTEX(aes_lock);
static void aes_workqueue_handler(struct work_struct *work);
static DECLARE_WORK(aes_work, aes_workqueue_handler);
static struct workqueue_struct *aes_wq;
extern unsigned long long