@@ -23,6 +23,10 @@
#include <linux/types.h>
#include <linux/debugfs.h>
#include <linux/circ_buf.h>
+
+#ifdef CONFIG_ARM /* needs the clock control subsystem */
+#include <linux/clk.h>
+#endif
#include <net/xfrm.h>
#include <crypto/algapi.h>
@@ -303,6 +303,14 @@ static int caam_remove(struct platform_device *pdev)
/* Unmap controller region */
iounmap(&ctrl);
+#ifdef CONFIG_ARM
+ /* 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);
+#endif
+
return ret;
}
@@ -408,6 +416,79 @@ static int caam_probe(struct platform_device *pdev)
ctrlpriv->pdev = pdev;
nprop = pdev->dev.of_node;
+/*
+ * ARM targets tend to have clock control subsystems that can
+ * enable/disable clocking to our device. Turn clocking on to proceed
+ */
+#ifdef CONFIG_ARM
+ ctrlpriv->caam_ipg = devm_clk_get(&pdev->dev, "caam_ipg");
+ if (IS_ERR(ctrlpriv->caam_ipg)) {
+ ret = PTR_ERR(ctrlpriv->caam_ipg);
+ dev_err(&pdev->dev,
+ "can't identify CAAM ipg clk: %d\n", ret);
+ return -ENODEV;
+ }
+
+ ctrlpriv->caam_mem = devm_clk_get(&pdev->dev, "caam_mem");
+ if (IS_ERR(ctrlpriv->caam_mem)) {
+ ret = PTR_ERR(ctrlpriv->caam_mem);
+ dev_err(&pdev->dev,
+ "can't identify CAAM secure mem clk: %d\n", ret);
+ return -ENODEV;
+ }
+
+ ctrlpriv->caam_aclk = devm_clk_get(&pdev->dev, "caam_aclk");
+ if (IS_ERR(ctrlpriv->caam_aclk)) {
+ ret = PTR_ERR(ctrlpriv->caam_aclk);
+ dev_err(&pdev->dev,
+ "can't identify CAAM aclk clk: %d\n", ret);
+ return -ENODEV;
+ }
+
+ ctrlpriv->caam_emi_slow = devm_clk_get(&pdev->dev, "caam_emi_slow");
+ if (IS_ERR(ctrlpriv->caam_emi_slow)) {
+ ret = PTR_ERR(ctrlpriv->caam_emi_slow);
+ dev_err(&pdev->dev,
+ "can't identify CAAM emi slow clk: %d\n", ret);
+ return -ENODEV;
+ }
+
+ 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;
+ }
+
+ dev_info(dev, "%s caam_ipg clock:%d\n", __func__,
+ (int)clk_get_rate(ctrlpriv->caam_ipg));
+ dev_info(dev, "%s caam_mem clock:%d\n", __func__,
+ (int)clk_get_rate(ctrlpriv->caam_mem));
+ dev_info(dev, "%s caam_aclk clock:%d\n", __func__,
+ (int)clk_get_rate(ctrlpriv->caam_aclk));
+ dev_info(dev, "%s caam_emi_slow clock:%d\n", __func__,
+ (int)clk_get_rate(ctrlpriv->caam_emi_slow));
+#endif
+
/* Get configuration properties from device tree */
/* First, get register page */
ctrl = of_iomap(nprop, 0);
@@ -91,6 +91,13 @@ struct caam_drv_private {
Handles of the RNG4 block are initialized
by this driver */
+#ifdef CONFIG_ARM
+ struct clk *caam_ipg;
+ struct clk *caam_mem;
+ struct clk *caam_aclk;
+ struct clk *caam_emi_slow;
+#endif
+
/*
* debugfs entries for developer view into driver/device
* variables at runtime.
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> --- drivers/crypto/caam/compat.h | 4 +++ drivers/crypto/caam/ctrl.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ drivers/crypto/caam/intern.h | 7 ++++ 3 files changed, 92 insertions(+)