These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / crypto / caam / ctrl.c
index efba4cc..69d4a13 100644 (file)
 #include "desc_constr.h"
 #include "error.h"
 
+/*
+ * i.MX targets tend to have clock control subsystems that can
+ * enable/disable clocking to our device.
+ */
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_IMX
+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
@@ -121,7 +139,7 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
                flags |= DECO_JQCR_FOUR;
 
        /* Instruct the DECO to execute it */
-       wr_reg32(&deco->jr_ctl_hi, flags);
+       setbits32(&deco->jr_ctl_hi, flags);
 
        timeout = 10000000;
        do {
@@ -175,7 +193,7 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
 {
        struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
        struct caam_ctrl __iomem *ctrl;
-       u32 *desc, status, rdsta_val;
+       u32 *desc, status = 0, rdsta_val;
        int ret = 0, sh_idx;
 
        ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
@@ -207,7 +225,8 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
                 * CAAM eras), then try again.
                 */
                rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK;
-               if (status || !(rdsta_val & (1 << sh_idx)))
+               if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) ||
+                   !(rdsta_val & (1 << sh_idx)))
                        ret = -EAGAIN;
                if (ret)
                        break;
@@ -279,7 +298,7 @@ static int caam_remove(struct platform_device *pdev)
        struct device *ctrldev;
        struct caam_drv_private *ctrlpriv;
        struct caam_ctrl __iomem *ctrl;
-       int ring, ret = 0;
+       int ring;
 
        ctrldev = &pdev->dev;
        ctrlpriv = dev_get_drvdata(ctrldev);
@@ -301,9 +320,15 @@ static int caam_remove(struct platform_device *pdev)
 #endif
 
        /* Unmap controller region */
-       iounmap(&ctrl);
+       iounmap(ctrl);
 
-       return ret;
+       /* 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 0;
 }
 
 /*
@@ -370,14 +395,14 @@ static void kick_trng(struct platform_device *pdev, int ent_delay)
 int caam_get_era(void)
 {
        struct device_node *caam_node;
-       for_each_compatible_node(caam_node, NULL, "fsl,sec-v4.0") {
-               const uint32_t *prop = (uint32_t *)of_get_property(caam_node,
-                               "fsl,sec-era",
-                               NULL);
-               return prop ? *prop : -ENOTSUPP;
-       }
+       int ret;
+       u32 prop;
 
-       return -ENOTSUPP;
+       caam_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+       ret = of_property_read_u32(caam_node, "fsl,sec-era", &prop);
+       of_node_put(caam_node);
+
+       return IS_ERR_VALUE(ret) ? -ENOTSUPP : prop;
 }
 EXPORT_SYMBOL(caam_get_era);
 
@@ -390,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
@@ -398,8 +424,7 @@ static int caam_probe(struct platform_device *pdev)
        int pg_size;
        int BLOCK_OFFSET = 0;
 
-       ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(struct caam_drv_private),
-                               GFP_KERNEL);
+       ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(*ctrlpriv), GFP_KERNEL);
        if (!ctrlpriv)
                return -ENOMEM;
 
@@ -408,12 +433,76 @@ 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 ret;
+       }
+       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 ret;
+       }
+       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 ret;
+       }
+       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 ret;
+       }
+       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 ret;
+       }
+
+       ret = clk_prepare_enable(ctrlpriv->caam_mem);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n",
+                       ret);
+               goto disable_caam_ipg;
+       }
+
+       ret = clk_prepare_enable(ctrlpriv->caam_aclk);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n", ret);
+               goto disable_caam_mem;
+       }
+
+       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);
+               goto disable_caam_aclk;
+       }
+
        /* Get configuration properties from device tree */
        /* First, get register page */
        ctrl = of_iomap(nprop, 0);
        if (ctrl == NULL) {
                dev_err(dev, "caam: of_iomap() failed\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto disable_caam_emi_slow;
        }
        /* Finding the page size for using the CTPR_MS register */
        comp_params = rd_reg32(&ctrl->perfmon.comp_parms_ms);
@@ -444,8 +533,9 @@ static int caam_probe(struct platform_device *pdev)
         * Enable DECO watchdogs and, if this is a PHYS_ADDR_T_64BIT kernel,
         * long pointers in master configuration register
         */
-       setbits32(&ctrl->mcr, MCFGR_WDENABLE |
-                 (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0));
+       clrsetbits_32(&ctrl->mcr, MCFGR_AWCACHE_MASK, MCFGR_AWCACHE_CACH |
+                     MCFGR_AWCACHE_BUFF | MCFGR_WDENABLE |
+                     (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0));
 
        /*
         *  Read the Compile Time paramters and SCFGR to determine
@@ -492,12 +582,11 @@ static int caam_probe(struct platform_device *pdev)
                    of_device_is_compatible(np, "fsl,sec4.0-job-ring"))
                        rspec++;
 
-       ctrlpriv->jrpdev = devm_kzalloc(&pdev->dev,
-                                       sizeof(struct platform_device *) * rspec,
-                                       GFP_KERNEL);
+       ctrlpriv->jrpdev = devm_kcalloc(&pdev->dev, rspec,
+                                       sizeof(*ctrlpriv->jrpdev), GFP_KERNEL);
        if (ctrlpriv->jrpdev == NULL) {
-               iounmap(&ctrl);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto iounmap_ctrl;
        }
 
        ring = 0;
@@ -537,8 +626,8 @@ static int caam_probe(struct platform_device *pdev)
        /* If no QI and no rings specified, quit and go home */
        if ((!ctrlpriv->qi_present) && (!ctrlpriv->total_jobrs)) {
                dev_err(dev, "no queues configured, terminating\n");
-               caam_remove(pdev);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto caam_remove;
        }
 
        cha_vid_ls = rd_reg32(&ctrl->perfmon.cha_id_ls);
@@ -595,8 +684,7 @@ static int caam_probe(struct platform_device *pdev)
                } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
                if (ret) {
                        dev_err(dev, "failed to instantiate RNG");
-                       caam_remove(pdev);
-                       return ret;
+                       goto caam_remove;
                }
                /*
                 * Set handles init'ed by this module as the complement of the
@@ -700,6 +788,20 @@ static int caam_probe(struct platform_device *pdev)
                                                 &ctrlpriv->ctl_tdsk_wrap);
 #endif
        return 0;
+
+caam_remove:
+       caam_remove(pdev);
+iounmap_ctrl:
+       iounmap(ctrl);
+disable_caam_emi_slow:
+       clk_disable_unprepare(ctrlpriv->caam_emi_slow);
+disable_caam_aclk:
+       clk_disable_unprepare(ctrlpriv->caam_aclk);
+disable_caam_mem:
+       clk_disable_unprepare(ctrlpriv->caam_mem);
+disable_caam_ipg:
+       clk_disable_unprepare(ctrlpriv->caam_ipg);
+       return ret;
 }
 
 static struct of_device_id caam_match[] = {