diff options
author | Varun Wadekar <vwadekar@nvidia.com> | 2011-06-08 12:36:12 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:41:48 -0800 |
commit | 81c9b782765072edd856eb3463a0b8a9f34518bd (patch) | |
tree | 6547316a7b476755a16041d4dc91987b28319f10 /drivers/crypto | |
parent | 0a1fca0bdfebf699cc56a3a2db8bdd403ff21eff (diff) |
crypto: tegra-se: code refactor and fix clock disable
- get some basic struct definitions from the header to
the .c file
- read SE config register before disabling the clock.
there are scenarios seen where some write transactions
are not posted before we disable clock. a dummy SE
register read fixes that issue.
Bug 835859
Original-Change-Id: I5e09c13262dbc392cac233a1fb6d69240b3460f2
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-on: http://git-master/r/35636
Reviewed-by: Mallikarjun Kasoju <mkasoju@nvidia.com>
Tested-by: Mallikarjun Kasoju <mkasoju@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Rebase-Id: R8a7380e843db8dd8fda379b9d0a2c4270d1bd40b
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/tegra-se.c | 178 | ||||
-rw-r--r-- | drivers/crypto/tegra-se.h | 99 |
2 files changed, 139 insertions, 138 deletions
diff --git a/drivers/crypto/tegra-se.c b/drivers/crypto/tegra-se.c index 261fc7eb099e..54be8f93dc9c 100644 --- a/drivers/crypto/tegra-se.c +++ b/drivers/crypto/tegra-se.c @@ -21,7 +21,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - #include <linux/module.h> #include <linux/init.h> #include <linux/errno.h> @@ -41,23 +40,119 @@ #include <crypto/internal/rng.h> #include <crypto/internal/hash.h> #include <crypto/sha.h> + #include "tegra-se.h" -static const char sg_driver_name[] = "tegra-se"; +#define DRIVER_NAME "tegra-se" + +/* Security Engine operation modes */ +enum tegra_se_aes_op_mode { + SE_AES_OP_MODE_CBC, /* Cipher Block Chaining (CBC) mode */ + SE_AES_OP_MODE_ECB, /* Electronic Codebook (ECB) mode */ + SE_AES_OP_MODE_CTR, /* Counter (CTR) mode */ + SE_AES_OP_MODE_OFB, /* Output feedback (CFB) mode */ + SE_AES_OP_MODE_RNG_X931, /* Random number generator (RNG) mode */ + SE_AES_OP_MODE_CMAC, /* Cipher-based MAC (CMAC) mode */ + SE_AES_OP_MODE_SHA1, /* Secure Hash Algorithm-1 (SHA1) mode */ + SE_AES_OP_MODE_SHA224, /* Secure Hash Algorithm-224 (SHA224) mode */ + SE_AES_OP_MODE_SHA256, /* Secure Hash Algorithm-256 (SHA256) mode */ + SE_AES_OP_MODE_SHA384, /* Secure Hash Algorithm-384 (SHA384) mode */ + SE_AES_OP_MODE_SHA512 /* Secure Hash Algorithm-512 (SHA512) mode */ +}; + +/* Security Engine key table type */ +enum tegra_se_key_table_type { + SE_KEY_TABLE_TYPE_KEY, /* Key */ + SE_KEY_TABLE_TYPE_ORGIV, /* Original IV */ + SE_KEY_TABLE_TYPE_UPDTDIV /* Updated IV */ +}; + +/* Security Engine request context */ +struct tegra_se_req_context { + enum tegra_se_aes_op_mode op_mode; /* Security Engine operation mode */ + bool encrypt; /* Operation type */ +}; + +struct tegra_se_dev { + struct device *dev; + void __iomem *io_reg; /* device memory/io */ + int irq; /* irq allocated */ + spinlock_t lock; /* spin lock */ + struct clk *pclk; /* Security Engine clock */ + struct crypto_queue queue; /* Security Engine crypto queue */ + struct tegra_se_slot *slot_list; /* pointer to key slots */ + u32 *src_ll_buf; /* pointer to source linked list buffer */ + dma_addr_t src_ll_buf_adr; /* Source linked list buffer dma address */ + u32 src_ll_size; /* Size of source linked list buffer */ + u32 *dst_ll_buf; /* pointer to destination linked list buffer */ + dma_addr_t dst_ll_buf_adr; /* Destination linked list dma address */ + u32 dst_ll_size; /* Size of destination linked list buffer */ + struct completion complete; /* Tells the task completion */ + bool work_q_busy; /* Work queue busy status */ +}; static struct tegra_se_dev *sg_tegra_se_dev; +/* Security Engine AES context */ +struct tegra_se_aes_context { + struct tegra_se_dev *se_dev; /* Security Engine device */ + struct tegra_se_slot *slot; /* Security Engine key slot */ + u32 keylen; /* key length in bits */ + u32 op_mode; /* AES operation mode */ +}; + +/* Security Engine randon number generator context */ +struct tegra_se_rng_context { + struct tegra_se_dev *se_dev; /* Security Engine device */ + struct tegra_se_slot *slot; /* Security Engine key slot */ + u32 *dt_buf; /* Destination buffer pointer */ + dma_addr_t dt_buf_adr; /* Destination buffer dma address */ + u32 *rng_buf; /* RNG buffer pointer */ + dma_addr_t rng_buf_adr; /* RNG buffer dma address */ + bool use_org_iv; /* Tells whether original IV is be used + or not. If it is false updated IV is used*/ +}; + +/* Security Engine SHA context */ +struct tegra_se_sha_context { + struct tegra_se_dev *se_dev; /* Security Engine device */ + u32 op_mode; /* SHA operation mode */ +}; + +/* Security Engine AES CMAC context */ +struct tegra_se_aes_cmac_context { + struct tegra_se_dev *se_dev; /* Security Engine device */ + struct tegra_se_slot *slot; /* Security Engine key slot */ + u32 keylen; /* key length in bits */ + u8 K1[TEGRA_SE_KEY_128_SIZE]; /* Key1 */ + u8 K2[TEGRA_SE_KEY_128_SIZE]; /* Key2 */ + dma_addr_t dma_addr; /* DMA address of local buffer */ + u32 buflen; /* local buffer length */ + u8 *buffer; /* local buffer pointer */ +}; + +/* Security Engine key slot */ +struct tegra_se_slot { + struct list_head node; + u8 slot_num; /* Key slot number */ + bool available; /* Tells whether key slot is free to use */ +}; + +/* Security Engine Linked List */ +struct tegra_se_ll { + dma_addr_t addr; /* DMA buffer address */ + u32 data_len; /* Data length in DMA buffer */ +}; + static LIST_HEAD(key_slot); static DEFINE_SPINLOCK(key_slot_lock); static DEFINE_MUTEX(se_hw_lock); /* create a work for handling the async transfers */ static void tegra_se_work_handler(struct work_struct *work); - static DECLARE_WORK(se_work, tegra_se_work_handler); static struct workqueue_struct *se_work_q; - #define GET_MSB(x) ((x) >> (8*sizeof(x)-1)) static void tegra_se_leftshift_onebit(u8 *in_buf, u32 size, u8 *org_msb) { @@ -98,6 +193,21 @@ static void tegra_se_free_key_slot(struct tegra_se_slot *slot) spin_unlock(&key_slot_lock); } +void tegra_se_clk_enable(struct clk *c) +{ + clk_enable(c); +} + +void tegra_se_clk_disable(struct clk *c) +{ + /* + * do a dummy read, to avoid scenarios where you have unposted writes + * still on the bus, before disabling clocks + */ + se_readl(sg_tegra_se_dev, SE_CONFIG_REG_OFFSET); + clk_disable(c); +} + static struct tegra_se_slot *tegra_se_alloc_key_slot(void) { struct tegra_se_slot *slot = NULL; @@ -441,7 +551,6 @@ static int tegra_se_start_operation(struct tegra_se_dev *se_dev, u32 nbytes) return 0; } - static void tegra_se_read_hash_result(struct tegra_se_dev *se_dev, u8 *pdata, u32 nbytes, bool swap32) { @@ -661,7 +770,7 @@ static void tegra_se_work_handler(struct work_struct *work) struct crypto_async_request *async_req = NULL; struct crypto_async_request *backlog = NULL; - clk_enable(se_dev->pclk); + tegra_se_clk_enable(se_dev->pclk); do { spin_lock_irq(&se_dev->lock); @@ -682,7 +791,7 @@ static void tegra_se_work_handler(struct work_struct *work) async_req = NULL; } } while (se_dev->work_q_busy); - clk_disable(se_dev->pclk); + tegra_se_clk_disable(se_dev->pclk); } static int tegra_se_aes_queue_req(struct ablkcipher_request *req) @@ -788,7 +897,6 @@ static int tegra_se_aes_ofb_decrypt(struct ablkcipher_request *req) return tegra_se_aes_queue_req(req); } - static int tegra_se_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, u32 keylen) { @@ -810,19 +918,18 @@ static int tegra_se_aes_setkey(struct crypto_ablkcipher *tfm, /* take access to the hw */ mutex_lock(&se_hw_lock); - clk_enable(se_dev->pclk); + tegra_se_clk_enable(se_dev->pclk); /* load the key */ tegra_se_write_key_table(pdata, keylen, ctx->slot->slot_num, SE_KEY_TABLE_TYPE_KEY); - clk_disable(se_dev->pclk); + tegra_se_clk_disable(se_dev->pclk); mutex_unlock(&se_hw_lock); return 0; } - static int tegra_se_aes_cra_init(struct crypto_tfm *tfm) { struct tegra_se_dev *se_dev = sg_tegra_se_dev; @@ -843,6 +950,7 @@ static int tegra_se_aes_cra_init(struct crypto_tfm *tfm) return 0; } + static void tegra_se_aes_cra_exit(struct crypto_tfm *tfm) { struct tegra_se_aes_context *ctx = crypto_tfm_ctx(tfm); @@ -851,7 +959,6 @@ static void tegra_se_aes_cra_exit(struct crypto_tfm *tfm) ctx->slot = NULL; } - static int tegra_se_rng_init(struct crypto_tfm *tfm) { struct tegra_se_rng_context *rng_ctx = crypto_tfm_ctx(tfm); @@ -920,7 +1027,7 @@ static int tegra_se_rng_get_random(struct crypto_rng *tfm, u8 *rdata, u32 dlen) /* take access to the hw */ mutex_lock(&se_hw_lock); - clk_enable(se_dev->pclk); + tegra_se_clk_enable(se_dev->pclk); *se_dev->src_ll_buf = 0; *se_dev->dst_ll_buf = 0; @@ -950,7 +1057,7 @@ static int tegra_se_rng_get_random(struct crypto_rng *tfm, u8 *rdata, u32 dlen) } rng_ctx->use_org_iv = false; - clk_disable(se_dev->pclk); + tegra_se_clk_disable(se_dev->pclk); mutex_unlock(&se_hw_lock); return dlen; @@ -971,7 +1078,7 @@ static int tegra_se_rng_reset(struct crypto_rng *tfm, u8 *seed, u32 slen) /* take access to the hw */ mutex_lock(&se_hw_lock); - clk_enable(se_dev->pclk); + tegra_se_clk_enable(se_dev->pclk); tegra_se_write_key_table(key, TEGRA_SE_RNG_KEY_SIZE, rng_ctx->slot->slot_num, SE_KEY_TABLE_TYPE_KEY); @@ -979,7 +1086,7 @@ static int tegra_se_rng_reset(struct crypto_rng *tfm, u8 *seed, u32 slen) tegra_se_write_key_table(iv, TEGRA_SE_RNG_IV_SIZE, rng_ctx->slot->slot_num, SE_KEY_TABLE_TYPE_ORGIV); - clk_disable(se_dev->pclk); + tegra_se_clk_disable(se_dev->pclk); mutex_unlock(&se_hw_lock); memcpy(rng_ctx->dt_buf, dt, TEGRA_SE_RNG_DT_SIZE); @@ -988,7 +1095,6 @@ static int tegra_se_rng_reset(struct crypto_rng *tfm, u8 *seed, u32 slen) return 0; } - int tegra_se_sha_init(struct ahash_request *req) { return 0; @@ -1004,7 +1110,6 @@ int tegra_se_sha_finup(struct ahash_request *req) return 0; } - int tegra_se_sha_final(struct ahash_request *req) { struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); @@ -1032,12 +1137,12 @@ int tegra_se_sha_final(struct ahash_request *req) /* take access to the hw */ mutex_lock(&se_hw_lock); - clk_enable(se_dev->pclk); + tegra_se_clk_enable(se_dev->pclk); num_sgs = tegra_se_count_sgs(req->src, req->nbytes); if ((num_sgs > SE_MAX_SRC_SG_COUNT)) { dev_err(se_dev->dev, "num of SG buffers are more\n"); - clk_disable(se_dev->pclk); + tegra_se_clk_disable(se_dev->pclk); mutex_unlock(&se_hw_lock); return -EINVAL; } @@ -1050,7 +1155,7 @@ int tegra_se_sha_final(struct ahash_request *req) err = dma_map_sg(se_dev->dev, src_sg, 1, DMA_TO_DEVICE); if (!err) { dev_err(se_dev->dev, "dma_map_sg() error\n"); - clk_disable(se_dev->pclk); + tegra_se_clk_disable(se_dev->pclk); mutex_unlock(&se_hw_lock); return -EINVAL; } @@ -1089,7 +1194,7 @@ int tegra_se_sha_final(struct ahash_request *req) total -= src_sg->length; src_sg = sg_next(src_sg); } - clk_disable(se_dev->pclk); + tegra_se_clk_disable(se_dev->pclk); mutex_unlock(&se_hw_lock); return err; @@ -1142,11 +1247,9 @@ int tegra_se_aes_cmac_final(struct ahash_request *req) u8 *temp_buffer = NULL; bool use_orig_iv = true; - /* take access to the hw */ mutex_lock(&se_hw_lock); - clk_enable(se_dev->pclk); - + tegra_se_clk_enable(se_dev->pclk); blocks_to_process = req->nbytes / TEGRA_SE_AES_BLOCK_SIZE; /* num of bytes less than block size */ @@ -1287,7 +1390,7 @@ int tegra_se_aes_cmac_final(struct ahash_request *req) TEGRA_SE_AES_CMAC_DIGEST_SIZE, false); out: - clk_disable(se_dev->pclk); + tegra_se_clk_disable(se_dev->pclk); mutex_unlock(&se_hw_lock); if (cmac_ctx->buffer) @@ -1332,7 +1435,7 @@ int tegra_se_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, /* take access to the hw */ mutex_lock(&se_hw_lock); - clk_enable(se_dev->pclk); + tegra_se_clk_enable(se_dev->pclk); *se_dev->src_ll_buf = 0; *se_dev->dst_ll_buf = 0; @@ -1381,7 +1484,7 @@ int tegra_se_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, ctx->K2[TEGRA_SE_AES_BLOCK_SIZE - 1] ^= rb; out: - clk_disable(se_dev->pclk); + tegra_se_clk_disable(se_dev->pclk); mutex_unlock(&se_hw_lock); if (pbuf) { @@ -1431,7 +1534,6 @@ void tegra_se_aes_cmac_cra_exit(struct crypto_tfm *tfm) ctx->slot = NULL; } - static struct crypto_alg aes_algs[] = { { .cra_name = "cbc(aes)", @@ -1660,8 +1762,6 @@ static int tegra_se_probe(struct platform_device *pdev) struct resource *res = NULL; int err = 0, i = 0, j = 0, k = 0; - dev_info(&pdev->dev, "tegra_se_probe START "); - se_dev = kzalloc(sizeof(struct tegra_se_dev), GFP_KERNEL); if (!se_dev) { dev_err(&pdev->dev, "memory allocation failed\n"); @@ -1695,7 +1795,7 @@ static int tegra_se_probe(struct platform_device *pdev) } err = request_irq(se_dev->irq, tegra_se_irq, IRQF_DISABLED, - sg_driver_name, se_dev); + DRIVER_NAME, se_dev); if (err) { dev_err(se_dev->dev, "request_irq failed - irq[%d] err[%d]\n", se_dev->irq, err); @@ -1703,9 +1803,9 @@ static int tegra_se_probe(struct platform_device *pdev) } /* Initialize the clock */ - se_dev->pclk = clk_get_sys("tegra-se", NULL); - if (!se_dev->pclk) { - dev_err(se_dev->dev, "clock intialization failed.\n"); + se_dev->pclk = clk_get(se_dev->dev, "se"); + if (IS_ERR(se_dev->pclk)) { + dev_err(se_dev->dev, "clock intialization failed (%d)\n", (int)se_dev->pclk); err = -ENODEV; goto clean; } @@ -1748,7 +1848,6 @@ static int tegra_se_probe(struct platform_device *pdev) } } - for (j = 0; j < ARRAY_SIZE(hash_algs); j++) { err = crypto_register_ahash(&hash_algs[j]); if (err) { @@ -1758,7 +1857,7 @@ static int tegra_se_probe(struct platform_device *pdev) } } - dev_info(se_dev->dev, "tegra_se_probe end"); + dev_info(se_dev->dev, "%s: complete", __func__); return 0; clean: @@ -1777,8 +1876,10 @@ clean: clk_put(se_dev->pclk); free_irq(se_dev->irq, &pdev->dev); + err_irq: iounmap(se_dev->io_reg); + fail: platform_set_drvdata(pdev, NULL); kfree(se_dev); @@ -1824,7 +1925,6 @@ static int tegra_se_suspend(struct platform_device *pdev, pm_message_t state) } #endif - static struct platform_driver tegra_se_driver = { .probe = tegra_se_probe, .remove = __devexit_p(tegra_se_remove), @@ -1833,7 +1933,7 @@ static struct platform_driver tegra_se_driver = { .resume = tegra_se_resume, #endif .driver = { - .name = sg_driver_name, + .name = "tegra-se", .owner = THIS_MODULE, }, }; diff --git a/drivers/crypto/tegra-se.h b/drivers/crypto/tegra-se.h index bc2ea191bd2d..29aaf72d8aec 100644 --- a/drivers/crypto/tegra-se.h +++ b/drivers/crypto/tegra-se.h @@ -181,103 +181,4 @@ TEGRA_SE_RNG_DT_SIZE) #define TEGRA_SE_AES_CMAC_DIGEST_SIZE 16 - -/* Security Engine operation modes */ -enum tegra_se_aes_op_mode { - SE_AES_OP_MODE_CBC, /* Cipher Block Chaining (CBC) mode */ - SE_AES_OP_MODE_ECB, /* Electronic Codebook (ECB) mode */ - SE_AES_OP_MODE_CTR, /* Counter (CTR) mode */ - SE_AES_OP_MODE_OFB, /* Output feedback (CFB) mode */ - SE_AES_OP_MODE_RNG_X931, /* Random number generator (RNG) mode */ - SE_AES_OP_MODE_CMAC, /* Cipher-based MAC (CMAC) mode */ - SE_AES_OP_MODE_SHA1, /* Secure Hash Algorithm-1 (SHA1) mode */ - SE_AES_OP_MODE_SHA224, /* Secure Hash Algorithm-224 (SHA224) mode */ - SE_AES_OP_MODE_SHA256, /* Secure Hash Algorithm-256 (SHA256) mode */ - SE_AES_OP_MODE_SHA384, /* Secure Hash Algorithm-384 (SHA384) mode */ - SE_AES_OP_MODE_SHA512 /* Secure Hash Algorithm-512 (SHA512) mode */ -}; - -/* Security Engine key table type */ -enum tegra_se_key_table_type { - SE_KEY_TABLE_TYPE_KEY, /* Key */ - SE_KEY_TABLE_TYPE_ORGIV, /* Original IV */ - SE_KEY_TABLE_TYPE_UPDTDIV /* Updated IV */ -}; - -/* Security Engine request context */ -struct tegra_se_req_context { - enum tegra_se_aes_op_mode op_mode; /* Security Engine operation mode */ - bool encrypt; /* Operation type */ -}; - -/* Security Engine AES context */ -struct tegra_se_aes_context { - struct tegra_se_dev *se_dev; /* Security Engine device */ - struct tegra_se_slot *slot; /* Security Engine key slot */ - u32 keylen; /* key length in bits */ - u32 op_mode; /* AES operation mode */ -}; - -/* Security Engine randon number generator context */ -struct tegra_se_rng_context { - struct tegra_se_dev *se_dev; /* Security Engine device */ - struct tegra_se_slot *slot; /* Security Engine key slot */ - u32 *dt_buf; /* Destination buffer pointer */ - dma_addr_t dt_buf_adr; /* Destination buffer dma address */ - u32 *rng_buf; /* RNG buffer pointer */ - dma_addr_t rng_buf_adr; /* RNG buffer dma address */ - bool use_org_iv; /* Tells whether original IV is be used - or not. If it is false updated IV is used*/ -}; - -/* Security Engine SHA context */ -struct tegra_se_sha_context { - struct tegra_se_dev *se_dev; /* Security Engine device */ - u32 op_mode; /* SHA operation mode */ -}; - -/* Security Engine AES CMAC context */ -struct tegra_se_aes_cmac_context { - struct tegra_se_dev *se_dev; /* Security Engine device */ - struct tegra_se_slot *slot; /* Security Engine key slot */ - u32 keylen; /* key length in bits */ - u8 K1[TEGRA_SE_KEY_128_SIZE]; /* Key1 */ - u8 K2[TEGRA_SE_KEY_128_SIZE]; /* Key2 */ - dma_addr_t dma_addr; /* DMA address of local buffer */ - u32 buflen; /* local buffer length */ - u8 *buffer; /* local buffer pointer */ -}; - -/* Security Engine key slot */ -struct tegra_se_slot { - struct list_head node; - u8 slot_num; /* Key slot number */ - bool available; /* Tells whether key slot is free to use */ -}; - -/* Security Engine Linked List */ -struct tegra_se_ll { - dma_addr_t addr; /* DMA buffer address */ - u32 data_len; /* Data length in DMA buffer */ -}; - -/* Security Engine device */ -struct tegra_se_dev { - struct device *dev; - void __iomem *io_reg; /* device memory/io */ - int irq; /* irq allocated */ - spinlock_t lock; /* spin lock */ - struct clk *pclk; /* Security Engine clock */ - struct crypto_queue queue; /* Security Engine crypto queue */ - struct tegra_se_slot *slot_list; /* pointer to key slots */ - u32 *src_ll_buf; /* pointer to source linked list buffer */ - dma_addr_t src_ll_buf_adr; /* Source linked list buffer dma address */ - u32 src_ll_size; /* Size of source linked list buffer */ - u32 *dst_ll_buf; /* pointer to destination linked list buffer */ - dma_addr_t dst_ll_buf_adr; /* Destination linked list dma address */ - u32 dst_ll_size; /* Size of destination linked list buffer */ - struct completion complete; /* Tells the task completion */ - bool work_q_busy;/* Work queue busy status */ -}; - #endif /* _CRYPTO_TEGRA_SE_H */ |