diff options
author | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-03 22:27:08 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 13:45:21 -0700 |
commit | c9ba669f458f36fb60329db8bf17a79559a2abbb (patch) | |
tree | 9df0bc37b03c697d8407f752e07b4420c0db10ea /drivers/crypto | |
parent | e8dab51df788690cce57c8600f2e3de1b26f23d4 (diff) |
crypto: tegra-aes: Revert to v3.10.10 version
This isn't being built on supported products, so use the upstream
version.
Signed-off-by: Dan Willemsen <dwillemsen@nvidia.com>
Change-Id: If2abf074dcf702062eb8c2bcf7c3cb79bb5ae354
Reviewed-on: http://git-master/r/270000
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/tegra-aes.c | 1103 |
1 files changed, 352 insertions, 751 deletions
diff --git a/drivers/crypto/tegra-aes.c b/drivers/crypto/tegra-aes.c index b6e91988d2bd..85ea7525fa36 100644 --- a/drivers/crypto/tegra-aes.c +++ b/drivers/crypto/tegra-aes.c @@ -1,16 +1,14 @@ /* * drivers/crypto/tegra-aes.c * - * Driver for NVIDIA Tegra AES hardware engines residing inside the - * Bit Stream Engine for Video (BSEV) and Bit Stream Engine for Audio - * (BSEA) hardware blocks. + * Driver for NVIDIA Tegra AES hardware engine residing inside the + * Bit Stream Engine for Video (BSEV) hardware block. * - * The programming sequence for these engines is with the help + * 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/A block. The BSEV engine has an internal RAM (VRAM) + * 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. The BSEA engine operates - * with the help of IRAM. + * before starting the encrypt/decrypt operation. * * Copyright (c) 2010, NVIDIA Corporation. * @@ -42,10 +40,6 @@ #include <linux/interrupt.h> #include <linux/completion.h> #include <linux/workqueue.h> -#include <linux/delay.h> -#include <linux/nvmap.h> - -#include <mach/arb_sema.h> #include <crypto/scatterwalk.h> #include <crypto/aes.h> @@ -59,8 +53,11 @@ #define FLAGS_GIV BIT(2) #define FLAGS_RNG BIT(3) #define FLAGS_OFB BIT(4) -#define FLAGS_INIT BIT(5) -#define FLAGS_BUSY 1 +#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. @@ -69,18 +66,14 @@ * 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 +#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 - -#define AES_HW_IV_SIZE 16 -#define AES_HW_KEYSCHEDULE_LEN 256 -#define ARB_SEMA_TIMEOUT 500 +#define AES_HW_KEY_TABLE_LENGTH_BYTES 64 /* * The memory being used is divides as follows: @@ -91,14 +84,25 @@ * * 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 DEFAULT_RNG_BLK_SZ 16 - -/* As of now only 4 commands are USED for AES encryption/Decryption */ -#define AES_HW_MAX_ICQ_LENGTH 4 +/* Define commands required for AES operation */ +enum { + CMD_BLKSTARTENGINE = 0x0E, + CMD_DMASETUP = 0x10, + CMD_DMACOMPLETE = 0x11, + CMD_SETTABLE = 0x15, + CMD_MEMDMAVD = 0x22, +}; -#define ICQBITSHIFT_BLKCNT 0 +/* 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 */ @@ -115,263 +119,128 @@ enum { CMDQ_OPCODE_SHIFT = 26, }; -/* 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, -}; +/* + * 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 UCQCMD_KEYTABLEADDRMASK 0x1FFFF +#define AES_NR_KEYSLOTS 8 +#define TEGRA_AES_QUEUE_LENGTH 50 +#define DEFAULT_RNG_BLK_SZ 16 -#define AES_NR_KEYSLOTS 8 -#define SSK_SLOT_NUM 4 +/* The command queue depth */ +#define AES_HW_MAX_ICQ_LENGTH 5 struct tegra_aes_slot { struct list_head node; int slot_num; - bool available; +}; + +static struct tegra_aes_slot ssk = { + .slot_num = SSK_SLOT_NUM, }; struct tegra_aes_reqctx { unsigned long mode; }; -#define TEGRA_AES_QUEUE_LENGTH 500 - -struct tegra_aes_engine { - struct tegra_aes_dev *dd; - struct tegra_aes_ctx *ctx; - struct clk *iclk; - struct clk *pclk; - struct ablkcipher_request *req; - struct scatterlist *in_sg; - struct completion op_complete; - struct scatterlist *out_sg; +struct tegra_aes_dev { + struct device *dev; void __iomem *io_base; - void __iomem *ivkey_base; - unsigned long phys_base; - unsigned long iram_phys; - void *iram_virt; 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; - u32 engine_offset; - u32 *buf_in; - u32 *buf_out; - int res_id; - unsigned long busy; - u8 irq; - u32 status; -}; - -struct tegra_aes_dev { - struct device *dev; - struct tegra_aes_slot *slots; - struct tegra_aes_engine bsev; - struct tegra_aes_engine bsea; - struct nvmap_client *client; - struct nvmap_handle_ref *h_ref; - struct crypto_queue queue; - spinlock_t lock; - u64 ctr; - unsigned long flags; - u8 dt[DEFAULT_RNG_BLK_SZ]; }; static struct tegra_aes_dev *aes_dev; struct tegra_aes_ctx { struct tegra_aes_dev *dd; - struct tegra_aes_engine *eng; + unsigned long flags; struct tegra_aes_slot *slot; - int key[AES_MAX_KEY_SIZE]; - int keylen; - bool use_ssk; - u8 dt[DEFAULT_RNG_BLK_SZ]; + u8 key[AES_MAX_KEY_SIZE]; + size_t keylen; }; -static struct tegra_aes_ctx rng_ctx; +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); -/* Engine specific work queues */ -static void bsev_workqueue_handler(struct work_struct *work); -static void bsea_workqueue_handler(struct work_struct *work); - -static DECLARE_WORK(bsev_work, bsev_workqueue_handler); -static DECLARE_WORK(bsea_work, bsea_workqueue_handler); - -static struct workqueue_struct *bsev_wq; -static struct workqueue_struct *bsea_wq; +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 tegra_chip_uid(void); -static inline u32 aes_readl(struct tegra_aes_engine *engine, u32 offset) -{ - return readl(engine->io_base + offset); -} - -static inline void aes_writel(struct tegra_aes_engine *engine, - u32 val, u32 offset) -{ - writel(val, engine->io_base + offset); -} - -static int alloc_iram(struct tegra_aes_dev *dd) -{ - size_t size; - int err; - - dd->h_ref = NULL; - - /* [key+iv+u-iv=64B] * 8 = 512Bytes */ - size = AES_MAX_KEY_SIZE; - dd->client = nvmap_create_client(nvmap_dev, "aes_bsea"); - if (IS_ERR(dd->client)) { - dev_err(dd->dev, "nvmap_create_client failed\n"); - goto out; - } - - dd->h_ref = nvmap_create_handle(dd->client, size); - if (IS_ERR(dd->h_ref)) { - dev_err(dd->dev, "nvmap_create_handle failed\n"); - goto out; - } - - /* Allocate memory in the iram */ - err = nvmap_alloc_handle_id(dd->client, nvmap_ref_to_id(dd->h_ref), - NVMAP_HEAP_CARVEOUT_IRAM, size, 0); - if (err) { - dev_err(dd->dev, "nvmap_alloc_handle_id failed\n"); - nvmap_free_handle_id(dd->client, nvmap_ref_to_id(dd->h_ref)); - goto out; - } - dd->bsea.iram_phys = nvmap_handle_address(dd->client, - nvmap_ref_to_id(dd->h_ref)); - - dd->bsea.iram_virt = nvmap_mmap(dd->h_ref); /* get virtual address */ - if (!dd->bsea.iram_virt) { - dev_err(dd->dev, "%s: no mem, BSEA IRAM alloc failure\n", - __func__); - goto out; - } - - memset(dd->bsea.iram_virt, 0, size); - return 0; - -out: - if (dd->bsea.iram_virt) - nvmap_munmap(dd->h_ref, dd->bsea.iram_virt); - - if (dd->client) { - nvmap_free_handle_id(dd->client, nvmap_ref_to_id(dd->h_ref)); - nvmap_client_put(dd->client); - } - - return -ENOMEM; -} - -static void free_iram(struct tegra_aes_dev *dd) -{ - if (dd->bsea.iram_virt) - nvmap_munmap(dd->h_ref, dd->bsea.iram_virt); - - if (dd->client) { - nvmap_free_handle_id(dd->client, nvmap_ref_to_id(dd->h_ref)); - nvmap_client_put(dd->client); - } -} - -static int aes_hw_init(struct tegra_aes_engine *engine) +static inline u32 aes_readl(struct tegra_aes_dev *dd, u32 offset) { - struct tegra_aes_dev *dd = aes_dev; - int ret = 0; - - if (engine->pclk) { - ret = clk_prepare_enable(engine->pclk); - if (ret < 0) { - dev_err(dd->dev, "%s: pclock enable fail(%d)\n", - __func__, ret); - return ret; - } - } - - if (engine->iclk) { - ret = clk_prepare_enable(engine->iclk); - if (ret < 0) { - dev_err(dd->dev, "%s: iclock enable fail(%d)\n", - __func__, ret); - if (engine->pclk) - clk_disable_unprepare(engine->pclk); - return ret; - } - } - - return ret; + return readl(dd->io_base + offset); } -static void aes_hw_deinit(struct tegra_aes_engine *engine) +static inline void aes_writel(struct tegra_aes_dev *dd, u32 val, u32 offset) { - if (engine->pclk) - clk_disable_unprepare(engine->pclk); - - if (engine->iclk) - clk_disable_unprepare(engine->iclk); + writel(val, dd->io_base + offset); } -#define MIN_RETRIES 3 -static int aes_start_crypt(struct tegra_aes_engine *eng, u32 in_addr, - u32 out_addr, int nblocks, int mode, bool upd_iv) +static int aes_start_crypt(struct tegra_aes_dev *dd, u32 in_addr, u32 out_addr, + int nblocks, int mode, bool upd_iv) { u32 cmdq[AES_HW_MAX_ICQ_LENGTH]; - int qlen = 0, i, eng_busy, icq_empty, ret; + int i, eng_busy, icq_empty, ret; u32 value; - int retries = MIN_RETRIES; -start: - do { - value = aes_readl(eng, TEGRA_AES_INTR_STATUS); - eng_busy = value & BIT(0); - icq_empty = value & BIT(3); - } while (eng_busy || (!icq_empty)); - - aes_writel(eng, 0xFFFFFFFF, TEGRA_AES_INTR_STATUS); + /* reset all the interrupt bits */ + aes_writel(dd, 0xFFFFFFFF, TEGRA_AES_INTR_STATUS); /* enable error, dma xfer complete interrupts */ - aes_writel(eng, 0x33, TEGRA_AES_INT_ENB); + aes_writel(dd, 0x33, TEGRA_AES_INT_ENB); cmdq[0] = CMD_DMASETUP << CMDQ_OPCODE_SHIFT; cmdq[1] = in_addr; cmdq[2] = CMD_BLKSTARTENGINE << CMDQ_OPCODE_SHIFT | (nblocks-1); cmdq[3] = CMD_DMACOMPLETE << CMDQ_OPCODE_SHIFT; - value = aes_readl(eng, TEGRA_AES_CMDQUE_CONTROL); + value = aes_readl(dd, TEGRA_AES_CMDQUE_CONTROL); /* access SDRAM through AHB */ value &= ~TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD; value &= ~TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD; value |= TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD | TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD | TEGRA_AES_CMDQ_CTRL_ICMDQEN_FIELD; - aes_writel(eng, value, TEGRA_AES_CMDQUE_CONTROL); - dev_dbg(aes_dev->dev, "cmd_q_ctrl=0x%x", value); + aes_writel(dd, value, TEGRA_AES_CMDQUE_CONTROL); + dev_dbg(dd->dev, "cmd_q_ctrl=0x%x", value); value = (0x1 << TEGRA_AES_SECURE_INPUT_ALG_SEL_SHIFT) | - ((eng->ctx->keylen * 8) << + ((dd->ctx->keylen * 8) << TEGRA_AES_SECURE_INPUT_KEY_LEN_SHIFT) | ((u32)upd_iv << TEGRA_AES_SECURE_IV_SELECT_SHIFT); @@ -395,36 +264,30 @@ start: << TEGRA_AES_SECURE_CORE_SEL_SHIFT); } - dev_dbg(aes_dev->dev, "secure_in_sel=0x%x", value); - aes_writel(eng, value, TEGRA_AES_SECURE_INPUT_SELECT); + dev_dbg(dd->dev, "secure_in_sel=0x%x", value); + aes_writel(dd, value, TEGRA_AES_SECURE_INPUT_SELECT); - aes_writel(eng, out_addr, TEGRA_AES_SECURE_DEST_ADDR); - INIT_COMPLETION(eng->op_complete); + aes_writel(dd, out_addr, TEGRA_AES_SECURE_DEST_ADDR); + INIT_COMPLETION(dd->op_complete); - for (i = 0; i < 3; i++) { + for (i = 0; i < AES_HW_MAX_ICQ_LENGTH - 1; i++) { do { - value = aes_readl(eng, TEGRA_AES_INTR_STATUS); + value = aes_readl(dd, TEGRA_AES_INTR_STATUS); eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD; icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD; - } while (eng_busy || (!icq_empty)); - aes_writel(eng, cmdq[i], TEGRA_AES_ICMDQUE_WR); + } while (eng_busy & (!icq_empty)); + aes_writel(dd, cmdq[i], TEGRA_AES_ICMDQUE_WR); } - ret = wait_for_completion_timeout(&eng->op_complete, - msecs_to_jiffies(150)); + ret = wait_for_completion_timeout(&dd->op_complete, + msecs_to_jiffies(150)); if (ret == 0) { - dev_err(aes_dev->dev, "engine%d timed out (0x%x)\n", - eng->res_id, aes_readl(eng, TEGRA_AES_INTR_STATUS)); + dev_err(dd->dev, "timed out (0x%x)\n", + aes_readl(dd, TEGRA_AES_INTR_STATUS)); return -ETIMEDOUT; } - aes_writel(eng, cmdq[3], TEGRA_AES_ICMDQUE_WR); - - if ((eng->status != 0) && (retries-- > 0)) { - qlen = 0; - goto start; - } - + aes_writel(dd, cmdq[AES_HW_MAX_ICQ_LENGTH - 1], TEGRA_AES_ICMDQUE_WR); return 0; } @@ -434,133 +297,116 @@ static void aes_release_key_slot(struct tegra_aes_slot *slot) return; spin_lock(&list_lock); - slot->available = true; + list_add_tail(&slot->node, &dev_list); slot = NULL; spin_unlock(&list_lock); } static struct tegra_aes_slot *aes_find_key_slot(void) { - struct tegra_aes_slot *slot; - int found = 0; + struct tegra_aes_slot *slot = NULL; + struct list_head *new_head; + int empty; spin_lock(&list_lock); - list_for_each_entry(slot, &dev_list, node) { - if (slot->available) { - slot->available = false; - found = 1; - break; - } + empty = list_empty(&dev_list); + if (!empty) { + slot = list_entry(&dev_list, struct tegra_aes_slot, node); + new_head = dev_list.next; + list_del(&dev_list); + dev_list.next = new_head->next; + dev_list.prev = NULL; } spin_unlock(&list_lock); - return found ? slot : NULL; + return slot; } -static int aes_set_key(struct tegra_aes_engine *eng, int slot_num) +static int aes_set_key(struct tegra_aes_dev *dd) { - struct tegra_aes_dev *dd = aes_dev; u32 value, cmdq[2]; + struct tegra_aes_ctx *ctx = dd->ctx; int eng_busy, icq_empty, dma_busy; + bool use_ssk = false; - if (!eng) { - dev_err(dd->dev, "%s: context invalid\n", __func__); - return -EINVAL; + /* use ssk? */ + if (!dd->ctx->slot) { + dev_dbg(dd->dev, "using ssk"); + dd->ctx->slot = &ssk; + use_ssk = true; } /* enable key schedule generation in hardware */ - value = aes_readl(eng, TEGRA_AES_SECURE_CONFIG_EXT); + value = aes_readl(dd, TEGRA_AES_SECURE_CONFIG_EXT); value &= ~TEGRA_AES_SECURE_KEY_SCH_DIS_FIELD; - aes_writel(eng, value, TEGRA_AES_SECURE_CONFIG_EXT); + aes_writel(dd, value, TEGRA_AES_SECURE_CONFIG_EXT); /* select the key slot */ - value = aes_readl(eng, TEGRA_AES_SECURE_CONFIG); + value = aes_readl(dd, TEGRA_AES_SECURE_CONFIG); value &= ~TEGRA_AES_SECURE_KEY_INDEX_FIELD; - value |= (slot_num << TEGRA_AES_SECURE_KEY_INDEX_SHIFT); - aes_writel(eng, value, TEGRA_AES_SECURE_CONFIG); + value |= (ctx->slot->slot_num << TEGRA_AES_SECURE_KEY_INDEX_SHIFT); + aes_writel(dd, value, TEGRA_AES_SECURE_CONFIG); - if (slot_num == SSK_SLOT_NUM) - goto out; + if (use_ssk) + return 0; - if (eng->res_id == TEGRA_ARB_BSEV) { - memset(dd->bsev.ivkey_base, 0, AES_HW_KEY_TABLE_LENGTH_BYTES); - memcpy(dd->bsev.ivkey_base, eng->ctx->key, eng->ctx->keylen); + /* copy the key table from sdram to vram */ + cmdq[0] = CMD_MEMDMAVD << CMDQ_OPCODE_SHIFT | + MEMDMA_DIR_DTOVRAM << MEMDMA_DIR_SHIFT | + AES_HW_KEY_TABLE_LENGTH_BYTES / sizeof(u32) << + MEMDMA_NUM_WORDS_SHIFT; + cmdq[1] = (u32)dd->ivkey_phys_base; - /* sync the buffer for device */ - dma_sync_single_for_device(dd->dev, dd->bsev.ivkey_phys_base, - eng->ctx->keylen, DMA_TO_DEVICE); + aes_writel(dd, cmdq[0], TEGRA_AES_ICMDQUE_WR); + aes_writel(dd, cmdq[1], TEGRA_AES_ICMDQUE_WR); - /* copy the key table from sdram to vram */ - cmdq[0] = CMD_MEMDMAVD << CMDQ_OPCODE_SHIFT | - MEMDMA_DIR_DTOVRAM << MEMDMA_DIR_SHIFT | - AES_HW_KEY_TABLE_LENGTH_BYTES / sizeof(u32) << - MEMDMA_NUM_WORDS_SHIFT; - cmdq[1] = (u32)eng->ivkey_phys_base; - - aes_writel(eng, cmdq[0], TEGRA_AES_ICMDQUE_WR); - aes_writel(eng, cmdq[1], TEGRA_AES_ICMDQUE_WR); + do { + value = aes_readl(dd, TEGRA_AES_INTR_STATUS); + eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD; + icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD; + dma_busy = value & TEGRA_AES_DMA_BUSY_FIELD; + } while (eng_busy & (!icq_empty) & dma_busy); - do { - value = aes_readl(eng, TEGRA_AES_INTR_STATUS); - eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD; - icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD; - dma_busy = value & TEGRA_AES_DMA_BUSY_FIELD; - } while (eng_busy & (!icq_empty) & dma_busy); - - /* settable command to get key into internal registers */ - value = CMD_SETTABLE << CMDQ_OPCODE_SHIFT | - SUBCMD_CRYPTO_TABLE_SEL << CMDQ_TABLESEL_SHIFT | - SUBCMD_VRAM_SEL << CMDQ_VRAMSEL_SHIFT | - (SUBCMD_KEY_TABLE_SEL | slot_num) - << CMDQ_KEYTABLEID_SHIFT; - } else { - memset(dd->bsea.iram_virt, 0, AES_HW_KEY_TABLE_LENGTH_BYTES); - memcpy(dd->bsea.iram_virt, eng->ctx->key, eng->ctx->keylen); - - /* set iram access cfg bit 0 if address >128K */ - if (dd->bsea.iram_phys > 0x00020000) - aes_writel(eng, BIT(0), TEGRA_AES_IRAM_ACCESS_CFG); - else - aes_writel(eng, 0, TEGRA_AES_IRAM_ACCESS_CFG); - - /* settable command to get key into internal registers */ - value = CMD_SETTABLE << CMDQ_OPCODE_SHIFT | - SUBCMD_CRYPTO_TABLE_SEL << CMDQ_TABLESEL_SHIFT | - (SUBCMD_KEY_TABLE_SEL | slot_num) - << CMDQ_KEYTABLEID_SHIFT | - dd->bsea.iram_phys >> 2; - } + /* settable command to get key into internal registers */ + value = CMD_SETTABLE << CMDQ_OPCODE_SHIFT | + SUBCMD_CRYPTO_TABLE_SEL << CMDQ_TABLESEL_SHIFT | + SUBCMD_VRAM_SEL << CMDQ_VRAMSEL_SHIFT | + (SUBCMD_KEY_TABLE_SEL | ctx->slot->slot_num) << + CMDQ_KEYTABLEID_SHIFT; + aes_writel(dd, value, TEGRA_AES_ICMDQUE_WR); - aes_writel(eng, value, TEGRA_AES_ICMDQUE_WR); do { - value = aes_readl(eng, TEGRA_AES_INTR_STATUS); + value = aes_readl(dd, TEGRA_AES_INTR_STATUS); eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD; icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD; } while (eng_busy & (!icq_empty)); -out: return 0; } -static int tegra_aes_handle_req(struct tegra_aes_engine *eng) +static int tegra_aes_handle_req(struct tegra_aes_dev *dd) { - struct tegra_aes_dev *dd = aes_dev; - struct tegra_aes_ctx *ctx; struct crypto_async_request *async_req, *backlog; + struct crypto_ablkcipher *tfm; + struct tegra_aes_ctx *ctx; struct tegra_aes_reqctx *rctx; struct ablkcipher_request *req; - unsigned long irq_flags; + unsigned long flags; int dma_max = AES_HW_DMA_BUFFER_SIZE_BYTES; - int nblocks, total, ret = 0, count = 0; + int ret = 0, nblocks, total; + int count = 0; dma_addr_t addr_in, addr_out; struct scatterlist *in_sg, *out_sg; - spin_lock_irqsave(&dd->lock, irq_flags); + if (!dd) + return -EINVAL; + + spin_lock_irqsave(&dd->lock, flags); backlog = crypto_get_backlog(&dd->queue); async_req = crypto_dequeue_request(&dd->queue); if (!async_req) - clear_bit(FLAGS_BUSY, &eng->busy); - spin_unlock_irqrestore(&dd->lock, irq_flags); + clear_bit(FLAGS_BUSY, &dd->flags); + spin_unlock_irqrestore(&dd->lock, flags); if (!async_req) return -ENODATA; @@ -569,58 +415,62 @@ static int tegra_aes_handle_req(struct tegra_aes_engine *eng) backlog->complete(backlog, -EINPROGRESS); req = ablkcipher_request_cast(async_req); - dev_dbg(dd->dev, "%s: get new req (engine #%d)\n", __func__, - eng->res_id); + + dev_dbg(dd->dev, "%s: get new req\n", __func__); if (!req->src || !req->dst) return -EINVAL; - /* take the hardware semaphore */ - if (tegra_arb_mutex_lock_timeout(eng->res_id, ARB_SEMA_TIMEOUT) < 0) { - dev_err(dd->dev, "aes hardware (%d) not available\n", - eng->res_id); - return -EBUSY; - } + /* take mutex to access the aes hw */ + mutex_lock(&aes_lock); /* assign new request to device */ - eng->req = req; - eng->total = req->nbytes; - eng->in_offset = 0; - eng->in_sg = req->src; - eng->out_offset = 0; - eng->out_sg = req->dst; + dd->req = req; + dd->total = req->nbytes; + dd->in_offset = 0; + dd->in_sg = req->src; + dd->out_offset = 0; + dd->out_sg = req->dst; + + in_sg = dd->in_sg; + out_sg = dd->out_sg; - in_sg = eng->in_sg; - out_sg = eng->out_sg; - total = eng->total; + total = dd->total; + tfm = crypto_ablkcipher_reqtfm(req); rctx = ablkcipher_request_ctx(req); - ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req)); + ctx = crypto_ablkcipher_ctx(tfm); rctx->mode &= FLAGS_MODE_MASK; dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode; - eng->ctx = ctx; - if (((dd->flags & FLAGS_CBC) || (dd->flags & FLAGS_OFB)) && req->info) { + dd->iv = (u8 *)req->info; + dd->ivlen = crypto_ablkcipher_ivsize(tfm); + + /* assign new context to device */ + ctx->dd = dd; + dd->ctx = ctx; + + if (ctx->flags & FLAGS_NEW_KEY) { + /* copy the key */ + memcpy(dd->ivkey_base, ctx->key, ctx->keylen); + memset(dd->ivkey_base + ctx->keylen, 0, AES_HW_KEY_TABLE_LENGTH_BYTES - ctx->keylen); + aes_set_key(dd); + ctx->flags &= ~FLAGS_NEW_KEY; + } + + if (((dd->flags & FLAGS_CBC) || (dd->flags & FLAGS_OFB)) && dd->iv) { /* set iv to the aes hw slot * Hw generates updated iv only after iv is set in slot. * So key and iv is passed asynchronously. - */ - memcpy(eng->buf_in, (u8 *)req->info, AES_BLOCK_SIZE); + */ + memcpy(dd->buf_in, dd->iv, dd->ivlen); - /* sync the buffer for device */ - dma_sync_single_for_device(dd->dev, eng->dma_buf_in, - AES_HW_DMA_BUFFER_SIZE_BYTES, DMA_TO_DEVICE); - - ret = aes_start_crypt(eng, (u32)eng->dma_buf_in, - (u32)eng->dma_buf_out, 1, FLAGS_CBC, false); + ret = aes_start_crypt(dd, (u32)dd->dma_buf_in, + dd->dma_buf_out, 1, FLAGS_CBC, false); if (ret < 0) { dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret); goto out; } - - /* sync the buffer for cpu */ - dma_sync_single_for_cpu(dd->dev, eng->dma_buf_out, - AES_HW_DMA_BUFFER_SIZE_BYTES, DMA_FROM_DEVICE); } while (total) { @@ -634,18 +484,19 @@ static int tegra_aes_handle_req(struct tegra_aes_engine *eng) ret = dma_map_sg(dd->dev, out_sg, 1, DMA_FROM_DEVICE); if (!ret) { dev_err(dd->dev, "dma_map_sg() error\n"); - dma_unmap_sg(dd->dev, eng->in_sg, + dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); goto out; } addr_in = sg_dma_address(in_sg); addr_out = sg_dma_address(out_sg); + dd->flags |= FLAGS_FAST; count = min_t(int, sg_dma_len(in_sg), dma_max); WARN_ON(sg_dma_len(in_sg) != sg_dma_len(out_sg)); nblocks = DIV_ROUND_UP(count, AES_BLOCK_SIZE); - ret = aes_start_crypt(eng, addr_in, addr_out, nblocks, + ret = aes_start_crypt(dd, addr_in, addr_out, nblocks, dd->flags, true); dma_unmap_sg(dd->dev, out_sg, 1, DMA_FROM_DEVICE); @@ -655,6 +506,7 @@ static int tegra_aes_handle_req(struct tegra_aes_engine *eng) dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret); goto out; } + dd->flags &= ~FLAGS_FAST; dev_dbg(dd->dev, "out: copied %d\n", count); total -= count; @@ -664,68 +516,14 @@ static int tegra_aes_handle_req(struct tegra_aes_engine *eng) } out: - /* release the hardware semaphore */ - tegra_arb_mutex_unlock(eng->res_id); - eng->total = total; - - if (eng->req->base.complete) - eng->req->base.complete(&eng->req->base, ret); - - dev_dbg(dd->dev, "%s: exit\n", __func__); - return ret; -} - -static int tegra_aes_key_save(struct tegra_aes_ctx *ctx) -{ - struct tegra_aes_dev *dd = aes_dev; - int retry_count, eng_busy, ret, eng_no; - struct tegra_aes_engine *eng[2] = {&dd->bsev, &dd->bsea}; - unsigned long flags; - - /* check for engine free state */ - for (eng_no = 0; eng_no < ARRAY_SIZE(eng); eng_no++) { - for (retry_count = 0; retry_count <= 10; retry_count++) { - spin_lock_irqsave(&dd->lock, flags); - eng_busy = test_and_set_bit(FLAGS_BUSY, - &eng[eng_no]->busy); - spin_unlock_irqrestore(&dd->lock, flags); - - if (!eng_busy) - break; - - if (retry_count == 10) { - dev_err(dd->dev, - "%s: eng=%d busy, wait timeout\n", - __func__, eng[eng_no]->res_id); - ret = -EBUSY; - goto out; - } - mdelay(5); - } - } + mutex_unlock(&aes_lock); - /* save key in the engine */ - for (eng_no = 0; eng_no < ARRAY_SIZE(eng); eng_no++) { - ret = aes_hw_init(eng[eng_no]); - if (ret < 0) { - dev_err(dd->dev, "%s: eng=%d hw init fail(%d)\n", - __func__, eng[eng_no]->res_id, ret); - goto out; - } - eng[eng_no]->ctx = ctx; - if (ctx->use_ssk) - aes_set_key(eng[eng_no], SSK_SLOT_NUM); - else - aes_set_key(eng[eng_no], ctx->slot->slot_num); + dd->total = total; - aes_hw_deinit(eng[eng_no]); - } -out: - spin_lock_irqsave(&dd->lock, flags); - while (--eng_no >= 0) - clear_bit(FLAGS_BUSY, &eng[eng_no]->busy); - spin_unlock_irqrestore(&dd->lock, flags); + if (dd->req->base.complete) + dd->req->base.complete(&dd->req->base, ret); + dev_dbg(dd->dev, "%s: exit\n", __func__); return ret; } @@ -735,13 +533,6 @@ static int tegra_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, struct tegra_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); struct tegra_aes_dev *dd = aes_dev; struct tegra_aes_slot *key_slot; - int ret = 0; - - if (!ctx || !dd) { - pr_err("ctx=0x%x, dd=0x%x\n", - (unsigned int)ctx, (unsigned int)dd); - return -EINVAL; - } if ((keylen != AES_KEYSIZE_128) && (keylen != AES_KEYSIZE_192) && (keylen != AES_KEYSIZE_256)) { @@ -750,19 +541,8 @@ static int tegra_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, return -EINVAL; } - /* take the hardware semaphore */ - if (tegra_arb_mutex_lock_timeout(dd->bsev.res_id, ARB_SEMA_TIMEOUT) < 0) { - dev_err(dd->dev, "aes hardware (%d) not available\n", dd->bsev.res_id); - return -EBUSY; - } - - if (tegra_arb_mutex_lock_timeout(dd->bsea.res_id, ARB_SEMA_TIMEOUT) < 0) { - dev_err(dd->dev, "aes hardware (%d) not available\n", dd->bsea.res_id); - tegra_arb_mutex_unlock(dd->bsev.res_id); - return -EBUSY; - } - dev_dbg(dd->dev, "keylen: %d\n", keylen); + ctx->dd = dd; if (key) { @@ -770,99 +550,57 @@ static int tegra_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, key_slot = aes_find_key_slot(); if (!key_slot) { dev_err(dd->dev, "no empty slot\n"); - ret = -EBUSY; - goto out; + return -ENOMEM; } + ctx->slot = key_slot; } - /* copy the key to the proper slot */ - memset(ctx->key, 0, AES_MAX_KEY_SIZE); memcpy(ctx->key, key, keylen); ctx->keylen = keylen; - ctx->use_ssk = false; - } else { - ctx->use_ssk = true; - ctx->keylen = AES_KEYSIZE_128; } - ret = tegra_aes_key_save(ctx); - if (ret != 0) - dev_err(dd->dev, "%s failed\n", __func__); -out: - tegra_arb_mutex_unlock(dd->bsev.res_id); - tegra_arb_mutex_unlock(dd->bsea.res_id); + ctx->flags |= FLAGS_NEW_KEY; dev_dbg(dd->dev, "done\n"); - return ret; -} - -static void bsev_workqueue_handler(struct work_struct *work) -{ - struct tegra_aes_dev *dd = aes_dev; - struct tegra_aes_engine *engine = &dd->bsev; - int ret; - - aes_hw_init(engine); - - /* empty the crypto queue and then return */ - do { - ret = tegra_aes_handle_req(engine); - } while (!ret); - - aes_hw_deinit(engine); + return 0; } -static void bsea_workqueue_handler(struct work_struct *work) +static void aes_workqueue_handler(struct work_struct *work) { struct tegra_aes_dev *dd = aes_dev; - struct tegra_aes_engine *engine = &dd->bsea; int ret; - aes_hw_init(engine); + ret = clk_prepare_enable(dd->aes_clk); + if (ret) + BUG_ON("clock enable failed"); /* empty the crypto queue and then return */ do { - ret = tegra_aes_handle_req(engine); + ret = tegra_aes_handle_req(dd); } while (!ret); - aes_hw_deinit(engine); + clk_disable_unprepare(dd->aes_clk); } -#define INT_ERROR_MASK 0xFFF000 -static irqreturn_t aes_bsev_irq(int irq, void *dev_id) +static irqreturn_t aes_irq(int irq, void *dev_id) { struct tegra_aes_dev *dd = (struct tegra_aes_dev *)dev_id; - u32 value = aes_readl(&dd->bsev, TEGRA_AES_INTR_STATUS); + u32 value = aes_readl(dd, TEGRA_AES_INTR_STATUS); + int busy = test_bit(FLAGS_BUSY, &dd->flags); - dev_dbg(dd->dev, "bsev irq_stat: 0x%x", value); - dd->bsev.status = 0; - if (value & TEGRA_AES_INT_ERROR_MASK) { - aes_writel(&dd->bsev, TEGRA_AES_INT_ERROR_MASK, TEGRA_AES_INTR_STATUS); - dd->bsev.status = value & TEGRA_AES_INT_ERROR_MASK; + if (!busy) { + dev_dbg(dd->dev, "spurious interrupt\n"); + return IRQ_NONE; } - value = aes_readl(&dd->bsev, TEGRA_AES_INTR_STATUS); - if (!(value & TEGRA_AES_ENGINE_BUSY_FIELD)) - complete(&dd->bsev.op_complete); - - return IRQ_HANDLED; -} - -static irqreturn_t aes_bsea_irq(int irq, void *dev_id) -{ - struct tegra_aes_dev *dd = (struct tegra_aes_dev *)dev_id; - u32 value = aes_readl(&dd->bsea, TEGRA_AES_INTR_STATUS); + dev_dbg(dd->dev, "irq_stat: 0x%x\n", value); + if (value & TEGRA_AES_INT_ERROR_MASK) + aes_writel(dd, TEGRA_AES_INT_ERROR_MASK, TEGRA_AES_INTR_STATUS); - dev_dbg(dd->dev, "bsea irq_stat: 0x%x", value); - dd->bsea.status = 0; - if (value & TEGRA_AES_INT_ERROR_MASK) { - aes_writel(&dd->bsea, TEGRA_AES_INT_ERROR_MASK, TEGRA_AES_INTR_STATUS); - dd->bsea.status = value & TEGRA_AES_INT_ERROR_MASK; - } - - value = aes_readl(&dd->bsea, TEGRA_AES_INTR_STATUS); if (!(value & TEGRA_AES_ENGINE_BUSY_FIELD)) - complete(&dd->bsea.op_complete); + complete(&dd->op_complete); + else + return IRQ_NONE; return IRQ_HANDLED; } @@ -873,29 +611,22 @@ static int tegra_aes_crypt(struct ablkcipher_request *req, unsigned long mode) struct tegra_aes_dev *dd = aes_dev; unsigned long flags; int err = 0; - int bsev_busy; - int bsea_busy; + int busy; dev_dbg(dd->dev, "nbytes: %d, enc: %d, cbc: %d, ofb: %d\n", - req->nbytes, !!(mode & FLAGS_ENCRYPT), !!(mode & FLAGS_CBC), - !!(mode & FLAGS_OFB)); + req->nbytes, !!(mode & FLAGS_ENCRYPT), + !!(mode & FLAGS_CBC), !!(mode & FLAGS_OFB)); rctx->mode = mode; spin_lock_irqsave(&dd->lock, flags); err = ablkcipher_enqueue_request(&dd->queue, req); + busy = test_and_set_bit(FLAGS_BUSY, &dd->flags); spin_unlock_irqrestore(&dd->lock, flags); - bsev_busy = test_and_set_bit(FLAGS_BUSY, &dd->bsev.busy); - if (!bsev_busy) { - queue_work(bsev_wq, &bsev_work); - goto finish; - } - bsea_busy = test_and_set_bit(FLAGS_BUSY, &dd->bsea.busy); - if (!bsea_busy) - queue_work(bsea_wq, &bsea_work); + if (!busy) + queue_work(aes_wq, &aes_work); -finish: return err; } @@ -930,47 +661,36 @@ static int tegra_aes_ofb_decrypt(struct ablkcipher_request *req) } static int tegra_aes_get_random(struct crypto_rng *tfm, u8 *rdata, - unsigned int dlen) + unsigned int dlen) { struct tegra_aes_dev *dd = aes_dev; - struct tegra_aes_engine *eng = rng_ctx.eng; - unsigned long flags; + struct tegra_aes_ctx *ctx = &rng_ctx; int ret, i; - u8 *dest = rdata, *dt = rng_ctx.dt; + u8 *dest = rdata, *dt = dd->dt; - /* take the hardware semaphore */ - if (tegra_arb_mutex_lock_timeout(eng->res_id, ARB_SEMA_TIMEOUT) < 0) { - dev_err(dd->dev, "aes hardware (%d) not available\n", - eng->res_id); - return -EBUSY; - } + /* take mutex to access the aes hw */ + mutex_lock(&aes_lock); - ret = aes_hw_init(eng); - if (ret < 0) { - dev_err(dd->dev, "%s: hw init fail(%d)\n", __func__, ret); - dlen = ret; - goto fail; + ret = clk_prepare_enable(dd->aes_clk); + if (ret) { + mutex_unlock(&aes_lock); + return ret; } - memset(eng->buf_in, 0, AES_BLOCK_SIZE); - memcpy(eng->buf_in, dt, DEFAULT_RNG_BLK_SZ); + ctx->dd = dd; + dd->ctx = ctx; + dd->flags = FLAGS_ENCRYPT | FLAGS_RNG; - /* sync the buffer for device */ - dma_sync_single_for_device(dd->dev, eng->dma_buf_in, - AES_HW_DMA_BUFFER_SIZE_BYTES, DMA_TO_DEVICE); + memcpy(dd->buf_in, dt, DEFAULT_RNG_BLK_SZ); - ret = aes_start_crypt(eng, (u32)eng->dma_buf_in, (u32)eng->dma_buf_out, - 1, FLAGS_ENCRYPT | FLAGS_RNG, true); + ret = aes_start_crypt(dd, (u32)dd->dma_buf_in, + (u32)dd->dma_buf_out, 1, dd->flags, true); if (ret < 0) { dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret); dlen = ret; goto out; } - /* sync the buffer for cpu */ - dma_sync_single_for_cpu(dd->dev, eng->dma_buf_out, - AES_HW_DMA_BUFFER_SIZE_BYTES, DMA_FROM_DEVICE); - - memcpy(dest, eng->buf_out, dlen); + memcpy(dest, dd->buf_out, dlen); /* update the DT */ for (i = DEFAULT_RNG_BLK_SZ - 1; i >= 0; i--) { @@ -980,100 +700,83 @@ static int tegra_aes_get_random(struct crypto_rng *tfm, u8 *rdata, } out: - aes_hw_deinit(eng); - - spin_lock_irqsave(&dd->lock, flags); - clear_bit(FLAGS_BUSY, &eng->busy); - spin_unlock_irqrestore(&dd->lock, flags); + clk_disable_unprepare(dd->aes_clk); + mutex_unlock(&aes_lock); -fail: - /* release the hardware semaphore */ - tegra_arb_mutex_unlock(eng->res_id); dev_dbg(dd->dev, "%s: done\n", __func__); return dlen; } static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed, - unsigned int slen) + unsigned int slen) { struct tegra_aes_dev *dd = aes_dev; struct tegra_aes_ctx *ctx = &rng_ctx; - struct tegra_aes_engine *eng = NULL; struct tegra_aes_slot *key_slot; - int bsea_busy = false; - unsigned long flags; struct timespec ts; - u64 nsec, tmp[2]; int ret = 0; + u64 nsec, tmp[2]; u8 *dt; - if (!dd) + if (!ctx || !dd) { + dev_err(dd->dev, "ctx=0x%x, dd=0x%x\n", + (unsigned int)ctx, (unsigned int)dd); return -EINVAL; + } if (slen < (DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128)) { + dev_err(dd->dev, "seed size invalid"); return -ENOMEM; } - spin_lock_irqsave(&dd->lock, flags); - bsea_busy = test_and_set_bit(FLAGS_BUSY, &dd->bsea.busy); - spin_unlock_irqrestore(&dd->lock, flags); - - if (!bsea_busy) - eng = &dd->bsea; - else - return -EBUSY; - - ctx->eng = eng; - dd->flags = FLAGS_ENCRYPT | FLAGS_RNG; + /* take mutex to access the aes hw */ + mutex_lock(&aes_lock); if (!ctx->slot) { key_slot = aes_find_key_slot(); if (!key_slot) { dev_err(dd->dev, "no empty slot\n"); + mutex_unlock(&aes_lock); return -ENOMEM; } ctx->slot = key_slot; } - /* take the hardware semaphore */ - if (tegra_arb_mutex_lock_timeout(eng->res_id, ARB_SEMA_TIMEOUT) < 0) { - dev_err(dd->dev, "aes hardware (%d) not available\n", - eng->res_id); - return -EBUSY; - } + ctx->dd = dd; + dd->ctx = ctx; + dd->ctr = 0; - ret = aes_hw_init(eng); - if (ret < 0) { - dev_err(dd->dev, "%s: hw init fail(%d)\n", __func__, ret); - goto fail; - } + ctx->keylen = AES_KEYSIZE_128; + ctx->flags |= FLAGS_NEW_KEY; - memcpy(ctx->key, seed + DEFAULT_RNG_BLK_SZ, AES_KEYSIZE_128); + /* copy the key to the key slot */ + memcpy(dd->ivkey_base, seed + DEFAULT_RNG_BLK_SZ, AES_KEYSIZE_128); + memset(dd->ivkey_base + AES_KEYSIZE_128, 0, AES_HW_KEY_TABLE_LENGTH_BYTES - AES_KEYSIZE_128); - eng->ctx = ctx; - eng->ctx->keylen = AES_KEYSIZE_128; - aes_set_key(eng, ctx->slot->slot_num); + dd->iv = seed; + dd->ivlen = slen; - /* set seed to the aes hw slot */ - memset(eng->buf_in, 0, AES_BLOCK_SIZE); - memcpy(eng->buf_in, seed, DEFAULT_RNG_BLK_SZ); + dd->flags = FLAGS_ENCRYPT | FLAGS_RNG; + + ret = clk_prepare_enable(dd->aes_clk); + if (ret) { + mutex_unlock(&aes_lock); + return ret; + } - /* sync the buffer for device */ - dma_sync_single_for_device(dd->dev, eng->dma_buf_in, - AES_HW_DMA_BUFFER_SIZE_BYTES, DMA_TO_DEVICE); + aes_set_key(dd); - ret = aes_start_crypt(eng, (u32)eng->dma_buf_in, - (u32)eng->dma_buf_out, 1, FLAGS_CBC, false); + /* set seed to the aes hw slot */ + memcpy(dd->buf_in, dd->iv, DEFAULT_RNG_BLK_SZ); + ret = aes_start_crypt(dd, (u32)dd->dma_buf_in, + dd->dma_buf_out, 1, FLAGS_CBC, false); if (ret < 0) { dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret); goto out; } - /* sync the buffer for cpu */ - dma_sync_single_for_cpu(dd->dev, eng->dma_buf_out, - AES_HW_DMA_BUFFER_SIZE_BYTES, DMA_FROM_DEVICE); - if (slen >= (2 * DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128)) { - dt = seed + DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128; + if (dd->ivlen >= (2 * DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128)) { + dt = dd->iv + DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128; } else { getnstimeofday(&ts); nsec = timespec_to_ns(&ts); @@ -1084,15 +787,11 @@ static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed, tmp[1] = tegra_chip_uid(); dt = (u8 *)tmp; } - - memcpy(ctx->dt, dt, DEFAULT_RNG_BLK_SZ); + memcpy(dd->dt, dt, DEFAULT_RNG_BLK_SZ); out: - aes_hw_deinit(eng); - -fail: - /* release the hardware semaphore */ - tegra_arb_mutex_unlock(eng->res_id); + clk_disable_unprepare(dd->aes_clk); + mutex_unlock(&aes_lock); dev_dbg(dd->dev, "%s: done\n", __func__); return ret; @@ -1101,6 +800,7 @@ fail: static int tegra_aes_cra_init(struct crypto_tfm *tfm) { tfm->crt_ablkcipher.reqsize = sizeof(struct tegra_aes_reqctx); + return 0; } @@ -1115,8 +815,9 @@ void tegra_aes_cra_exit(struct crypto_tfm *tfm) static struct crypto_alg algs[] = { { - .cra_name = "disabled_ecb(aes)", + .cra_name = "ecb(aes)", .cra_driver_name = "ecb-aes-tegra", + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, .cra_alignmask = 3, @@ -1129,8 +830,9 @@ static struct crypto_alg algs[] = { .decrypt = tegra_aes_ecb_decrypt, }, }, { - .cra_name = "disabled_cbc(aes)", + .cra_name = "cbc(aes)", .cra_driver_name = "cbc-aes-tegra", + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, .cra_alignmask = 3, @@ -1144,8 +846,9 @@ static struct crypto_alg algs[] = { .decrypt = tegra_aes_cbc_decrypt, } }, { - .cra_name = "disabled_ofb(aes)", + .cra_name = "ofb(aes)", .cra_driver_name = "ofb-aes-tegra", + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, .cra_alignmask = 3, @@ -1159,7 +862,7 @@ static struct crypto_alg algs[] = { .decrypt = tegra_aes_ofb_decrypt, } }, { - .cra_name = "disabled_ansi_cprng", + .cra_name = "ansi_cprng", .cra_driver_name = "rng-aes-tegra", .cra_flags = CRYPTO_ALG_TYPE_RNG, .cra_ctxsize = sizeof(struct tegra_aes_ctx), @@ -1198,22 +901,14 @@ static int tegra_aes_probe(struct platform_device *pdev) spin_lock_init(&dd->lock); crypto_init_queue(&dd->queue, TEGRA_AES_QUEUE_LENGTH); + /* Get the module base address */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), - dev_name(&pdev->dev))) { - dev_err(&pdev->dev, "Couldn't request MEM resource\n"); - return -ENODEV; - } - - dd->bsev.io_base = devm_ioremap(dev, res->start, resource_size(res)); - if (!dd->bsev.io_base) { - dev_err(dev, "can't ioremap bsev register space\n"); - err = -ENOMEM; + if (!res) { + dev_err(dev, "invalid resource type: base\n"); + err = -ENODEV; goto out; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), dev_name(&pdev->dev))) { @@ -1221,59 +916,24 @@ static int tegra_aes_probe(struct platform_device *pdev) return -ENODEV; } - dd->bsea.io_base = devm_ioremap(dev, res->start, resource_size(res)); - if (!dd->bsea.io_base) { - dev_err(dev, "can't ioremap bsea register space\n"); + dd->io_base = devm_ioremap(dev, res->start, resource_size(res)); + if (!dd->io_base) { + dev_err(dev, "can't ioremap register space\n"); err = -ENOMEM; goto out; } - err = alloc_iram(dd); - if (err < 0) { - dev_err(dev, "Failed to allocate IRAM for BSEA\n"); - goto out; - } - - dd->bsev.res_id = TEGRA_ARB_BSEV; - dd->bsea.res_id = TEGRA_ARB_BSEA; - - dd->bsev.pclk = clk_get(dev, "bsev"); - if (IS_ERR(dd->bsev.pclk)) { - dev_err(dev, "v: pclock intialization failed.\n"); - err = -ENODEV; - goto out; - } - - dd->bsev.iclk = clk_get(dev, "vde"); - if (IS_ERR(dd->bsev.iclk)) { - dev_err(dev, "v: iclock intialization failed.\n"); + /* Initialize the vde clock */ + dd->aes_clk = clk_get(dev, "vde"); + if (IS_ERR(dd->aes_clk)) { + dev_err(dev, "iclock intialization failed.\n"); err = -ENODEV; goto out; } - dd->bsea.pclk = clk_get(dev, "bsea"); - if (IS_ERR(dd->bsea.pclk)) { - dev_err(dev, "a: pclock intialization failed.\n"); - err = -ENODEV; - goto out; - } - - dd->bsea.iclk = clk_get(dev, "sclk"); - if (IS_ERR(dd->bsea.iclk)) { - dev_err(dev, "a: iclock intialization failed.\n"); - err = -ENODEV; - goto out; - } - - err = clk_set_rate(dd->bsev.iclk, ULONG_MAX); - if (err) { - dev_err(dd->dev, "bsev iclk set_rate fail(%d)\n", err); - goto out; - } - - err = clk_set_rate(dd->bsea.iclk, ULONG_MAX); + err = clk_set_rate(dd->aes_clk, ULONG_MAX); if (err) { - dev_err(dd->dev, "bsea iclk set_rate fail(%d)\n", err); + dev_err(dd->dev, "iclk set_rate fail(%d)\n", err); goto out; } @@ -1282,42 +942,34 @@ static int tegra_aes_probe(struct platform_device *pdev) * - hardware key table * - key schedule */ - dd->bsea.ivkey_base = NULL; - dd->bsev.ivkey_base = dma_alloc_coherent(dev, SZ_512, - &dd->bsev.ivkey_phys_base, GFP_KERNEL); - if (!dd->bsev.ivkey_base) { - dev_err(dev, "can not allocate iv/key buffer for BSEV\n"); + dd->ivkey_base = dma_alloc_coherent(dev, AES_HW_KEY_TABLE_LENGTH_BYTES, + &dd->ivkey_phys_base, + GFP_KERNEL); + if (!dd->ivkey_base) { + dev_err(dev, "can not allocate iv/key buffer\n"); err = -ENOMEM; goto out; } - memset(dd->bsev.ivkey_base, 0, SZ_512); - dd->bsev.buf_in = dma_alloc_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, - &dd->bsev.dma_buf_in, GFP_KERNEL); - dd->bsea.buf_in = dma_alloc_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, - &dd->bsea.dma_buf_in, GFP_KERNEL); - if (!dd->bsev.buf_in || !dd->bsea.buf_in) { + dd->buf_in = dma_alloc_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, + &dd->dma_buf_in, GFP_KERNEL); + if (!dd->buf_in) { dev_err(dev, "can not allocate dma-in buffer\n"); err = -ENOMEM; goto out; } - dd->bsev.buf_out = dma_alloc_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, - &dd->bsev.dma_buf_out, GFP_KERNEL); - dd->bsea.buf_out = dma_alloc_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, - &dd->bsea.dma_buf_out, GFP_KERNEL); - if (!dd->bsev.buf_out || !dd->bsea.buf_out) { + dd->buf_out = dma_alloc_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, + &dd->dma_buf_out, GFP_KERNEL); + if (!dd->buf_out) { dev_err(dev, "can not allocate dma-out buffer\n"); err = -ENOMEM; goto out; } - init_completion(&dd->bsev.op_complete); - init_completion(&dd->bsea.op_complete); - - bsev_wq = alloc_workqueue("bsev_wq", WQ_HIGHPRI | WQ_UNBOUND, 1); - bsea_wq = alloc_workqueue("bsea_wq", WQ_HIGHPRI | WQ_UNBOUND, 1); - if (!bsev_wq || !bsea_wq) { + init_completion(&dd->op_complete); + aes_wq = alloc_workqueue("tegra_aes_wq", WQ_HIGHPRI | WQ_UNBOUND, 1); + if (!aes_wq) { dev_err(dev, "alloc_workqueue failed\n"); err = -ENOMEM; goto out; @@ -1326,34 +978,20 @@ static int tegra_aes_probe(struct platform_device *pdev) /* get the irq */ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { - dev_err(dev, "invalid resource type: IRQ\n"); + dev_err(dev, "invalid resource type: base\n"); err = -ENODEV; goto out; } - dd->bsev.irq = res->start; + dd->irq = res->start; - err = devm_request_irq(dev, dd->bsev.irq, aes_bsev_irq, - IRQF_TRIGGER_HIGH | IRQF_SHARED, "tegra-aes", dd); + err = devm_request_irq(dev, dd->irq, aes_irq, IRQF_TRIGGER_HIGH | + IRQF_SHARED, "tegra-aes", dd); if (err) { - dev_err(dev, "request_irq failed fir BSEV Engine\n"); - goto out; - } - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); - if (!res) { - dev_err(dev, "invalid resource type: IRQ\n"); - err = -ENODEV; - goto out; - } - dd->bsea.irq = res->start; - - err = devm_request_irq(dev, dd->bsea.irq, aes_bsea_irq, - IRQF_TRIGGER_HIGH | IRQF_SHARED, "tegra-aes", dd); - if (err) { - dev_err(dev, "request_irq failed for BSEA Engine\n"); + dev_err(dev, "request_irq failed\n"); goto out; } + mutex_init(&aes_lock); INIT_LIST_HEAD(&dev_list); spin_lock_init(&list_lock); @@ -1362,7 +1000,6 @@ static int tegra_aes_probe(struct platform_device *pdev) if (i == SSK_SLOT_NUM) continue; dd->slots[i].slot_num = i; - dd->slots[i].available = true; INIT_LIST_HEAD(&dd->slots[i].node); list_add_tail(&dd->slots[i].node, &dev_list); } @@ -1387,46 +1024,23 @@ static int tegra_aes_probe(struct platform_device *pdev) out: for (j = 0; j < i; j++) crypto_unregister_alg(&algs[j]); - - free_iram(dd); - - if (dd->bsev.ivkey_base) { + if (dd->ivkey_base) dma_free_coherent(dev, AES_HW_KEY_TABLE_LENGTH_BYTES, - dd->bsev.ivkey_base, dd->bsev.ivkey_phys_base); - } - - if (dd->bsev.buf_in && dd->bsea.buf_in) { - dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, - dd->bsev.buf_in, dd->bsev.dma_buf_in); - dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, - dd->bsea.buf_in, dd->bsea.dma_buf_in); - } - - if (dd->bsev.buf_out && dd->bsea.buf_out) { + dd->ivkey_base, dd->ivkey_phys_base); + if (dd->buf_in) dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, - dd->bsev.buf_out, dd->bsev.dma_buf_out); + dd->buf_in, dd->dma_buf_in); + if (dd->buf_out) dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, - dd->bsea.buf_out, dd->bsea.dma_buf_out); - } - - if (dd->bsev.pclk) - clk_put(dd->bsev.pclk); - - if (dd->bsev.iclk) - clk_put(dd->bsev.iclk); - - if (dd->bsea.pclk) - clk_put(dd->bsea.pclk); - - if (bsev_wq) - destroy_workqueue(bsev_wq); - - if (bsea_wq) - destroy_workqueue(bsea_wq); - + dd->buf_out, dd->dma_buf_out); + if (!IS_ERR(dd->aes_clk)) + clk_put(dd->aes_clk); + if (aes_wq) + destroy_workqueue(aes_wq); spin_lock(&list_lock); list_del(&dev_list); spin_unlock(&list_lock); + aes_dev = NULL; dev_err(dev, "%s: initialization failed.\n", __func__); @@ -1442,32 +1056,19 @@ static int tegra_aes_remove(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(algs); i++) crypto_unregister_alg(&algs[i]); - cancel_work_sync(&bsev_work); - cancel_work_sync(&bsea_work); - destroy_workqueue(bsev_wq); - destroy_workqueue(bsea_wq); - free_irq(dd->bsev.irq, dd); - free_irq(dd->bsea.irq, dd); + cancel_work_sync(&aes_work); + destroy_workqueue(aes_wq); spin_lock(&list_lock); list_del(&dev_list); spin_unlock(&list_lock); - free_iram(dd); - dma_free_coherent(dev, SZ_512, dd->bsev.ivkey_base, - dd->bsev.ivkey_phys_base); - dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, dd->bsev.buf_in, - dd->bsev.dma_buf_in); - dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, dd->bsea.buf_in, - dd->bsea.dma_buf_in); - dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, dd->bsev.buf_out, - dd->bsev.dma_buf_out); - dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, dd->bsea.buf_out, - dd->bsea.dma_buf_out); - - clk_put(dd->bsev.iclk); - clk_put(dd->bsev.pclk); - clk_put(dd->bsea.pclk); - + dma_free_coherent(dev, AES_HW_KEY_TABLE_LENGTH_BYTES, + dd->ivkey_base, dd->ivkey_phys_base); + dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, + dd->buf_in, dd->dma_buf_in); + dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, + dd->buf_out, dd->dma_buf_out); + clk_put(dd->aes_clk); aes_dev = NULL; return 0; |