summaryrefslogtreecommitdiff
path: root/drivers/crypto
diff options
context:
space:
mode:
authorvenu byravarasu <vbyravarasu@nvidia.com>2011-10-13 18:22:41 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:25 -0800
commit53049d978228515bbe963fcdbacd171c8e26e401 (patch)
tree224545991635b552feecf9db6e17eb4aeca7b429 /drivers/crypto
parent24f93b889fa1ccbebbde3e929ada725489c6a7cc (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/crypto')
-rw-r--r--drivers/crypto/tegra-se.c115
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
},
};