diff options
author | venu byravarasu <vbyravarasu@nvidia.com> | 2011-10-13 18:22:41 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:49:25 -0800 |
commit | 53049d978228515bbe963fcdbacd171c8e26e401 (patch) | |
tree | 224545991635b552feecf9db6e17eb4aeca7b429 /drivers | |
parent | 24f93b889fa1ccbebbde3e929ada725489c6a7cc (diff) |
crypto: tegra-se: Adding runtime PM support
bug 886813
Change-Id: Ia016c0f783b0396d8433b202ccef1659d10085f5
Reviewed-on: http://git-master/r/57850
Tested-by: Mallikarjun Kasoju <mkasoju@nvidia.com>
Tested-by: Venu Byravarasu <vbyravarasu@nvidia.com>
Reviewed-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Rebase-Id: R5a13865e200c1345bc30ab86b8d3286d47af5796
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/crypto/tegra-se.c | 115 |
1 files changed, 67 insertions, 48 deletions
diff --git a/drivers/crypto/tegra-se.c b/drivers/crypto/tegra-se.c index 655520a1db8a..cd515fcf9d28 100644 --- a/drivers/crypto/tegra-se.c +++ b/drivers/crypto/tegra-se.c @@ -40,6 +40,7 @@ #include <crypto/internal/rng.h> #include <crypto/internal/hash.h> #include <crypto/sha.h> +#include <linux/pm_runtime.h> #include "tegra-se.h" @@ -212,21 +213,6 @@ static void tegra_se_free_key_slot(struct tegra_se_slot *slot) } } -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; @@ -293,12 +279,12 @@ static void tegra_se_key_read_disable_all(void) u8 slot_num; mutex_lock(&se_hw_lock); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); for (slot_num = 0; slot_num < TEGRA_SE_KEYSLOT_COUNT; slot_num++) tegra_se_key_read_disable(slot_num); - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); } @@ -830,7 +816,7 @@ static void tegra_se_work_handler(struct work_struct *work) struct crypto_async_request *async_req = NULL; struct crypto_async_request *backlog = NULL; - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); do { spin_lock_irq(&se_dev->lock); @@ -851,7 +837,7 @@ static void tegra_se_work_handler(struct work_struct *work) async_req = NULL; } } while (se_dev->work_q_busy); - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); } static int tegra_se_aes_queue_req(struct ablkcipher_request *req) @@ -989,13 +975,13 @@ static int tegra_se_aes_setkey(struct crypto_ablkcipher *tfm, /* take access to the hw */ mutex_lock(&se_hw_lock); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); /* load the key */ tegra_se_write_key_table(pdata, keylen, ctx->slot->slot_num, SE_KEY_TABLE_TYPE_KEY); - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); return 0; @@ -1089,7 +1075,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); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); *se_dev->src_ll_buf = 0; *se_dev->dst_ll_buf = 0; @@ -1130,7 +1116,7 @@ static int tegra_se_rng_get_random(struct crypto_rng *tfm, u8 *rdata, u32 dlen) } } - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); return dlen; @@ -1150,7 +1136,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); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); tegra_se_write_key_table(key, TEGRA_SE_RNG_KEY_SIZE, rng_ctx->slot->slot_num, SE_KEY_TABLE_TYPE_KEY); @@ -1158,7 +1144,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); - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); if (slen < TEGRA_SE_RNG_SEED_SIZE) { @@ -1221,12 +1207,12 @@ int tegra_se_sha_final(struct ahash_request *req) /* take access to the hw */ mutex_lock(&se_hw_lock); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); 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"); - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); return -EINVAL; } @@ -1239,7 +1225,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"); - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); return -EINVAL; } @@ -1278,7 +1264,7 @@ int tegra_se_sha_final(struct ahash_request *req) total -= src_sg->length; src_sg = sg_next(src_sg); } - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); return err; @@ -1331,7 +1317,7 @@ int tegra_se_aes_cmac_final(struct ahash_request *req) /* take access to the hw */ mutex_lock(&se_hw_lock); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); blocks_to_process = req->nbytes / TEGRA_SE_AES_BLOCK_SIZE; /* num of bytes less than block size */ @@ -1472,7 +1458,7 @@ int tegra_se_aes_cmac_final(struct ahash_request *req) TEGRA_SE_AES_CMAC_DIGEST_SIZE, false); out: - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); if (cmac_ctx->buffer) @@ -1528,7 +1514,7 @@ int tegra_se_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, /* take access to the hw */ mutex_lock(&se_hw_lock); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); *se_dev->src_ll_buf = 0; *se_dev->dst_ll_buf = 0; @@ -1577,7 +1563,7 @@ int tegra_se_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, ctx->K2[TEGRA_SE_AES_BLOCK_SIZE - 1] ^= rb; out: - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); if (pbuf) { @@ -1924,6 +1910,7 @@ static int tegra_se_probe(struct platform_device *pdev) } sg_tegra_se_dev = se_dev; + pm_runtime_enable(se_dev->dev); tegra_se_key_read_disable_all(); err = tegra_se_alloc_ll_buf(se_dev, SE_MAX_SRC_SG_COUNT, @@ -1965,6 +1952,7 @@ static int tegra_se_probe(struct platform_device *pdev) return 0; clean: + pm_runtime_disable(se_dev->dev); for (k = 0; k < i; k++) crypto_unregister_alg(&aes_algs[k]); @@ -2002,6 +1990,8 @@ static int __devexit tegra_se_remove(struct platform_device *pdev) if (!se_dev) return -ENODEV; + pm_runtime_disable(se_dev->dev); + cancel_work_sync(&se_work); if (se_work_q) destroy_workqueue(se_work_q); @@ -2068,11 +2058,11 @@ static int tegra_se_generate_srk(struct tegra_se_dev *se_dev) u32 val = 0; mutex_lock(&se_hw_lock); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); ret = tegra_se_generate_rng_key(se_dev); if (ret) { - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); return ret; } @@ -2094,7 +2084,7 @@ static int tegra_se_generate_srk(struct tegra_se_dev *se_dev) se_writel(se_dev, val, SE_CRYPTO_REG_OFFSET); ret = tegra_se_start_operation(se_dev, TEGRA_SE_KEY_128_SIZE, false); - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); return ret; @@ -2107,7 +2097,7 @@ static int tegra_se_lp_generate_random_data(struct tegra_se_dev *se_dev) u32 val; mutex_lock(&se_hw_lock); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); *se_dev->src_ll_buf = 0; *se_dev->dst_ll_buf = 0; @@ -2132,7 +2122,7 @@ static int tegra_se_lp_generate_random_data(struct tegra_se_dev *se_dev) ret = tegra_se_start_operation(se_dev, SE_CONTEXT_SAVE_RANDOM_DATA_SIZE, false); - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); return ret; @@ -2146,7 +2136,7 @@ static int tegra_se_lp_encrypt_context_data(struct tegra_se_dev *se_dev, int ret = 0; mutex_lock(&se_hw_lock); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); *se_dev->src_ll_buf = 0; *se_dev->dst_ll_buf = 0; @@ -2162,7 +2152,7 @@ static int tegra_se_lp_encrypt_context_data(struct tegra_se_dev *se_dev, ret = tegra_se_start_operation(se_dev, data_size, true); - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); @@ -2175,7 +2165,7 @@ static int tegra_se_lp_sticky_bits_context_save(struct tegra_se_dev *se_dev) int ret = 0; mutex_lock(&se_hw_lock); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); *se_dev->src_ll_buf = 0; *se_dev->dst_ll_buf = 0; @@ -2190,7 +2180,7 @@ static int tegra_se_lp_sticky_bits_context_save(struct tegra_se_dev *se_dev) ret = tegra_se_start_operation(se_dev, SE_CONTEXT_SAVE_STICKY_BITS_SIZE, true); - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); return ret; @@ -2204,7 +2194,7 @@ static int tegra_se_lp_keytable_context_save(struct tegra_se_dev *se_dev) /* take access to the hw */ mutex_lock(&se_hw_lock); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); *se_dev->dst_ll_buf = 0; dst_ll = (struct tegra_se_ll *)(se_dev->dst_ll_buf + 1); @@ -2226,7 +2216,7 @@ static int tegra_se_lp_keytable_context_save(struct tegra_se_dev *se_dev) } } - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); return ret; @@ -2240,7 +2230,7 @@ static int tegra_se_lp_iv_context_save(struct tegra_se_dev *se_dev, u32 val = 0; mutex_lock(&se_hw_lock); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); *se_dev->dst_ll_buf = 0; dst_ll = (struct tegra_se_ll *)(se_dev->dst_ll_buf + 1); @@ -2260,7 +2250,7 @@ static int tegra_se_lp_iv_context_save(struct tegra_se_dev *se_dev, dst_ll->addr += TEGRA_SE_AES_IV_SIZE; } - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); return ret; @@ -2271,13 +2261,13 @@ static int tegra_se_save_SRK(struct tegra_se_dev *se_dev) int ret = 0; mutex_lock(&se_hw_lock); - tegra_se_clk_enable(se_dev->pclk); + pm_runtime_get_sync(se_dev->dev); se_writel(se_dev, SE_CONTEXT_SAVE_SRC(SRK), SE_CONTEXT_SAVE_CONFIG_REG_OFFSET); ret = tegra_se_start_operation(se_dev, 0, true); - tegra_se_clk_disable(se_dev->pclk); + pm_runtime_put_sync(se_dev->dev); mutex_unlock(&se_hw_lock); return ret; @@ -2376,6 +2366,31 @@ out: } #endif +#if defined(CONFIG_PM_RUNTIME) +static int tegra_se_runtime_idle(struct device *dev) +{ + /* + * 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(sg_tegra_se_dev->pclk); + return 0; +} + +static int tegra_se_runtime_resume(struct device *dev) +{ + clk_enable(sg_tegra_se_dev->pclk); + return 0; +} + +static const struct dev_pm_ops tegra_se_dev_pm_ops = { + .runtime_idle = tegra_se_runtime_idle, + .runtime_resume = tegra_se_runtime_resume, +}; +#endif + static struct platform_driver tegra_se_driver = { .probe = tegra_se_probe, .remove = __devexit_p(tegra_se_remove), @@ -2386,6 +2401,10 @@ static struct platform_driver tegra_se_driver = { .driver = { .name = "tegra-se", .owner = THIS_MODULE, + +#if defined(CONFIG_PM_RUNTIME) + .pm = &tegra_se_dev_pm_ops, +#endif }, }; |