crypto: caam - Enable and disable clocks on Freescale i.MX platforms
authorVictoria Milhoan <vicki.milhoan@freescale.com>
Wed, 5 Aug 2015 18:28:37 +0000 (11:28 -0700)
committerHerbert Xu <herbert@gondor.apana.org.au>
Mon, 10 Aug 2015 15:18:56 +0000 (23:18 +0800)
ARM-based systems may disable clocking to the CAAM device on the
Freescale i.MX platform for power management purposes.  This patch
enables the required clocks when the CAAM module is initialized and
disables the required clocks when the CAAM module is shut down.

Signed-off-by: Victoria Milhoan <vicki.milhoan@freescale.com>
Tested-by: Horia Geantă <horia.geanta@freescale.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/caam/compat.h
drivers/crypto/caam/ctrl.c
drivers/crypto/caam/intern.h

index f57f395db33f73e8fb5630bd7d2c779a4ca2ff7f..b6955ecdfb3f67d39116c9362a16222070de51cd 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/debugfs.h>
 #include <linux/circ_buf.h>
+#include <linux/clk.h>
 #include <net/xfrm.h>
 
 #include <crypto/algapi.h>
index 660cc3edd4a7eead721e82059fca1d29599b1ed9..37c2d8d965a643e93b445690409bd5e478c5f8a9 100644 (file)
 #include "desc_constr.h"
 #include "error.h"
 
+/*
+ * ARM targets tend to have clock control subsystems that can
+ * enable/disable clocking to our device.
+ */
+#ifdef CONFIG_ARM
+static inline struct clk *caam_drv_identify_clk(struct device *dev,
+                                               char *clk_name)
+{
+       return devm_clk_get(dev, clk_name);
+}
+#else
+static inline struct clk *caam_drv_identify_clk(struct device *dev,
+                                               char *clk_name)
+{
+       return NULL;
+}
+#endif
+
 /*
  * Descriptor to instantiate RNG State Handle 0 in normal mode and
  * load the JDKEK, TDKEK and TDSK registers
@@ -304,6 +322,12 @@ static int caam_remove(struct platform_device *pdev)
        /* Unmap controller region */
        iounmap(ctrl);
 
+       /* shut clocks off before finalizing shutdown */
+       clk_disable_unprepare(ctrlpriv->caam_ipg);
+       clk_disable_unprepare(ctrlpriv->caam_mem);
+       clk_disable_unprepare(ctrlpriv->caam_aclk);
+       clk_disable_unprepare(ctrlpriv->caam_emi_slow);
+
        return ret;
 }
 
@@ -391,6 +415,7 @@ static int caam_probe(struct platform_device *pdev)
        struct device_node *nprop, *np;
        struct caam_ctrl __iomem *ctrl;
        struct caam_drv_private *ctrlpriv;
+       struct clk *clk;
 #ifdef CONFIG_DEBUG_FS
        struct caam_perfmon *perfmon;
 #endif
@@ -409,6 +434,69 @@ static int caam_probe(struct platform_device *pdev)
        ctrlpriv->pdev = pdev;
        nprop = pdev->dev.of_node;
 
+       /* Enable clocking */
+       clk = caam_drv_identify_clk(&pdev->dev, "ipg");
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               dev_err(&pdev->dev,
+                       "can't identify CAAM ipg clk: %d\n", ret);
+               return -ENODEV;
+       }
+       ctrlpriv->caam_ipg = clk;
+
+       clk = caam_drv_identify_clk(&pdev->dev, "mem");
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               dev_err(&pdev->dev,
+                       "can't identify CAAM mem clk: %d\n", ret);
+               return -ENODEV;
+       }
+       ctrlpriv->caam_mem = clk;
+
+       clk = caam_drv_identify_clk(&pdev->dev, "aclk");
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               dev_err(&pdev->dev,
+                       "can't identify CAAM aclk clk: %d\n", ret);
+               return -ENODEV;
+       }
+       ctrlpriv->caam_aclk = clk;
+
+       clk = caam_drv_identify_clk(&pdev->dev, "emi_slow");
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               dev_err(&pdev->dev,
+                       "can't identify CAAM emi_slow clk: %d\n", ret);
+               return -ENODEV;
+       }
+       ctrlpriv->caam_emi_slow = clk;
+
+       ret = clk_prepare_enable(ctrlpriv->caam_ipg);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can't enable CAAM ipg clock: %d\n", ret);
+               return -ENODEV;
+       }
+
+       ret = clk_prepare_enable(ctrlpriv->caam_mem);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n",
+                       ret);
+               return -ENODEV;
+       }
+
+       ret = clk_prepare_enable(ctrlpriv->caam_aclk);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n", ret);
+               return -ENODEV;
+       }
+
+       ret = clk_prepare_enable(ctrlpriv->caam_emi_slow);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n",
+                       ret);
+               return -ENODEV;
+       }
+
        /* Get configuration properties from device tree */
        /* First, get register page */
        ctrl = of_iomap(nprop, 0);
index 89b94cc9e7a29b57654ad5931e9999be3d80e664..e2bcacc1a921675cf30f70a40816e1306a8c3ef9 100644 (file)
@@ -91,6 +91,11 @@ struct caam_drv_private {
                                   Handles of the RNG4 block are initialized
                                   by this driver */
 
+       struct clk *caam_ipg;
+       struct clk *caam_mem;
+       struct clk *caam_aclk;
+       struct clk *caam_emi_slow;
+
        /*
         * debugfs entries for developer view into driver/device
         * variables at runtime.