summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2010-12-27 12:23:47 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 00:47:30 -0700
commit2374073a6602d87421d1c7a38e92aaa15d4035f5 (patch)
treeb4909b14058ebd9f027746df58e30e7e0c2851f5 /drivers
parent0108e3fe57564577e5f61b280f10d753b7f4b9b8 (diff)
crypto: tegra-aes: initialise bsev/vde clocks per operation
Change-Id: Iaddea9ba9d3bee9c987776f37225dee483684274 Signed-off-by: Varun Wadekar <vwadekar@nvidia.com> Rebase-Id: R9a109a6bc046bce0e4c06d3ba8d872cba36174a5
Diffstat (limited to 'drivers')
-rw-r--r--drivers/crypto/tegra-aes.c75
1 files changed, 62 insertions, 13 deletions
diff --git a/drivers/crypto/tegra-aes.c b/drivers/crypto/tegra-aes.c
index 85ea7525fa36..5a69c4cf4d66 100644
--- a/drivers/crypto/tegra-aes.c
+++ b/drivers/crypto/tegra-aes.c
@@ -40,6 +40,7 @@
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
+#include <linux/delay.h>
#include <crypto/scatterwalk.h>
#include <crypto/aes.h>
@@ -152,6 +153,7 @@ struct tegra_aes_dev {
dma_addr_t ivkey_phys_base;
void __iomem *ivkey_base;
struct clk *aes_clk;
+ struct clk *pclk;
struct tegra_aes_ctx *ctx;
int irq;
unsigned long flags;
@@ -211,6 +213,38 @@ static inline void aes_writel(struct tegra_aes_dev *dd, u32 val, u32 offset)
writel(val, dd->io_base + offset);
}
+static int aes_hw_init(struct tegra_aes_dev *dd)
+{
+ int ret = 0;
+
+ ret = clk_prepare_enable(dd->pclk);
+ if (ret < 0) {
+ dev_err(dd->dev, "%s: pclock enable fail(%d)\n", __func__, ret);
+ return ret;
+ }
+
+ tegra_periph_reset_assert(dd->iclk);
+ udelay(50);
+ tegra_periph_reset_deassert(dd->iclk);
+ udelay(50);
+
+ ret = clk_prepare_enable(dd->aes_clk);
+ if (ret < 0) {
+ dev_err(dd->dev, "%s: iclock enable fail(%d)\n", __func__, ret);
+ clk_disable_unprepare(dd->pclk);
+ return ret;
+ }
+
+ aes_writel(dd, 0x33, TEGRA_AES_INT_ENB);
+ return ret;
+}
+
+static void aes_hw_deinit(struct tegra_aes_dev *dd)
+{
+ clk_disable_unprepare(dd->aes_clk);
+ clk_disable_unprepare(dd->pclk);
+}
+
static int aes_start_crypt(struct tegra_aes_dev *dd, u32 in_addr, u32 out_addr,
int nblocks, int mode, bool upd_iv)
{
@@ -570,16 +604,16 @@ static void aes_workqueue_handler(struct work_struct *work)
struct tegra_aes_dev *dd = aes_dev;
int ret;
- ret = clk_prepare_enable(dd->aes_clk);
+ ret = aes_hw_init(dd);
if (ret)
- BUG_ON("clock enable failed");
+ BUG_ON("hw init failed");
/* empty the crypto queue and then return */
do {
ret = tegra_aes_handle_req(dd);
} while (!ret);
- clk_disable_unprepare(dd->aes_clk);
+ aes_hw_deinit(dd);
}
static irqreturn_t aes_irq(int irq, void *dev_id)
@@ -671,10 +705,10 @@ static int tegra_aes_get_random(struct crypto_rng *tfm, u8 *rdata,
/* take mutex to access the aes hw */
mutex_lock(&aes_lock);
- ret = clk_prepare_enable(dd->aes_clk);
- if (ret) {
- mutex_unlock(&aes_lock);
- return ret;
+ ret = aes_hw_init(dd);
+ if (ret < 0) {
+ dev_err(dd->dev, "%s: hw init fail(%d)\n", __func__, ret);
+ goto fail;
}
ctx->dd = dd;
@@ -700,7 +734,9 @@ static int tegra_aes_get_random(struct crypto_rng *tfm, u8 *rdata,
}
out:
- clk_disable_unprepare(dd->aes_clk);
+ aes_hw_deinit(dd);
+
+fail:
mutex_unlock(&aes_lock);
dev_dbg(dd->dev, "%s: done\n", __func__);
@@ -758,10 +794,10 @@ static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
dd->flags = FLAGS_ENCRYPT | FLAGS_RNG;
- ret = clk_prepare_enable(dd->aes_clk);
- if (ret) {
- mutex_unlock(&aes_lock);
- return ret;
+ ret = aes_hw_init(dd);
+ if (ret < 0) {
+ dev_err(dd->dev, "%s: hw init fail(%d)\n", __func__, ret);
+ goto fail;
}
aes_set_key(dd);
@@ -790,7 +826,9 @@ static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
memcpy(dd->dt, dt, DEFAULT_RNG_BLK_SZ);
out:
- clk_disable_unprepare(dd->aes_clk);
+ aes_hw_deinit(dd);
+
+fail:
mutex_unlock(&aes_lock);
dev_dbg(dd->dev, "%s: done\n", __func__);
@@ -923,6 +961,14 @@ static int tegra_aes_probe(struct platform_device *pdev)
goto out;
}
+ /* Initialise the master bsev clock */
+ dd->pclk = clk_get(dev, "bsev");
+ if (IS_ERR(dd->pclk)) {
+ dev_err(dev, "pclock initialization failed.\n");
+ err = -ENODEV;
+ goto out;
+ }
+
/* Initialize the vde clock */
dd->aes_clk = clk_get(dev, "vde");
if (IS_ERR(dd->aes_clk)) {
@@ -1035,6 +1081,8 @@ out:
dd->buf_out, dd->dma_buf_out);
if (!IS_ERR(dd->aes_clk))
clk_put(dd->aes_clk);
+ if (dd->pclk)
+ clk_put(dd->pclk);
if (aes_wq)
destroy_workqueue(aes_wq);
spin_lock(&list_lock);
@@ -1069,6 +1117,7 @@ static int tegra_aes_remove(struct platform_device *pdev)
dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
dd->buf_out, dd->dma_buf_out);
clk_put(dd->aes_clk);
+ clk_put(dd->pclk);
aes_dev = NULL;
return 0;