MLK-14284 Fix CAAM Errata err005766 handling
authorRadu Solea <radu.solea@nxp.com>
Thu, 13 Apr 2017 13:14:06 +0000 (16:14 +0300)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:22:00 +0000 (15:22 -0500)
Update ERA detection code to check 3 sources CCBVID, CAAMVID
and the device tree.
Fix bit handling of CAAMVID data to obtain correct results.
Remove default device tree values.
Update errata handling to target known affected platforms.

Signed-off-by: Radu Solea <radu.solea@nxp.com>
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/imx6sx.dtsi
drivers/crypto/caam/ctrl.c
drivers/crypto/caam/ctrl.h
drivers/crypto/caam/intern.h
drivers/crypto/caam/regs.h

index d1ff51b..b64e783 100644 (file)
 
                        crypto: caam@2100000 {
                                compatible = "fsl,sec-v4.0";
-                               fsl,sec-era = <4>;
                                #address-cells = <1>;
                                #size-cells = <1>;
                                reg = <0x2100000 0x10000>;
index 29f9cae..7359c20 100644 (file)
 
                        crypto: caam@2100000 {
                                compatible = "fsl,sec-v4.0";
-                               fsl,sec-era = <4>;
                                #address-cells = <1>;
                                #size-cells = <1>;
                                reg = <0x2100000 0x40000>;
index e2ae60f..a468f2b 100644 (file)
@@ -398,14 +398,13 @@ static void kick_trng(struct platform_device *pdev, int ent_delay)
        wr_reg32(&r4tst->rtmctl, val);
 }
 
-/**
- * caam_get_era() - Return the ERA of the SEC on SoC, based
- * on the SEC_VID register.
- * Returns the ERA number (1..4) or -ENOTSUPP if the ERA is unknown.
- * @caam_id - the value of the SEC_VID register
- **/
-int caam_get_era(u64 caam_id)
+static void detect_era(struct caam_drv_private *ctrlpriv)
 {
+       int ret, i;
+       u32 caam_era;
+       u32 caam_id_ms;
+       char *era_source;
+       struct device_node *caam_node;
        struct sec_vid sec_vid;
        static const struct {
                u16 ip_id;
@@ -439,19 +438,75 @@ int caam_get_era(u64 caam_id)
                {0x0A12, 5, 8},
                {0x0A16, 3, 8},
        };
-       int i;
 
-       sec_vid.ip_id = caam_id >> SEC_VID_IPID_SHIFT;
-       sec_vid.maj_rev = (caam_id & SEC_VID_MAJ_MASK) >> SEC_VID_MAJ_SHIFT;
+       /* If the user or bootloader has set the property we'll use that */
+       caam_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+       ret = of_property_read_u32(caam_node, "fsl,sec-era", &caam_era);
+       of_node_put(caam_node);
+
+       if (!ret) {
+               era_source = "device tree";
+               goto era_found;
+       }
+
+       /* If ccbvid has the era, use that (era 6 and onwards) */
+       caam_era = rd_reg32(&ctrlpriv->ctrl->perfmon.ccb_id);
+       caam_era = caam_era >> CCB_VID_ERA_SHIFT & CCB_VID_ERA_MASK;
+
+       if (caam_era) {
+               era_source = "CCBVID";
+               goto era_found;
+       }
+
+       /* If we can match caamvid to known versions, use that */
+       caam_id_ms = rd_reg32(&ctrlpriv->ctrl->perfmon.caam_id_ms);
+       sec_vid.ip_id = caam_id_ms >> SEC_VID_IPID_SHIFT;
+       sec_vid.maj_rev = (caam_id_ms & SEC_VID_MAJ_MASK) >> SEC_VID_MAJ_SHIFT;
 
        for (i = 0; i < ARRAY_SIZE(caam_eras); i++)
                if (caam_eras[i].ip_id == sec_vid.ip_id &&
-                   caam_eras[i].maj_rev == sec_vid.maj_rev)
-                       return caam_eras[i].era;
+                   caam_eras[i].maj_rev == sec_vid.maj_rev) {
+                       caam_era = caam_eras[i].era;
+                       era_source = "CAAMVID";
+                       goto era_found;
+               }
 
-       return -ENOTSUPP;
+       ctrlpriv->era = -ENOTSUPP;
+       return;
+
+era_found:
+       ctrlpriv->era = caam_era;
+       dev_info(&ctrlpriv->pdev->dev, "ERA source: %s.\n", era_source);
+}
+
+static void handle_imx6_err005766(struct caam_drv_private *ctrlpriv)
+{
+       /*
+        * ERRATA:  mx6 devices have an issue wherein AXI bus transactions
+        * may not occur in the correct order. This isn't a problem running
+        * single descriptors, but can be if running multiple concurrent
+        * descriptors. Reworking the driver to throttle to single requests
+        * is impractical, thus the workaround is to limit the AXI pipeline
+        * to a depth of 1 (from it's default of 4) to preclude this situation
+        * from occurring.
+        */
+
+       u32 mcr_val;
+
+       if (ctrlpriv->era != IMX_ERR005766_ERA)
+               return;
+
+       if (of_machine_is_compatible("fsl,imx6q") ||
+           of_machine_is_compatible("fsl,imx6dl") ||
+           of_machine_is_compatible("fsl,imx6qp")) {
+               dev_info(&ctrlpriv->pdev->dev,
+                        "AXI pipeline throttling enabled.\n");
+               mcr_val = rd_reg32(&ctrlpriv->ctrl->mcr);
+               wr_reg32(&ctrlpriv->ctrl->mcr,
+                        (mcr_val & ~(MCFGR_AXIPIPE_MASK)) |
+                        ((1 << MCFGR_AXIPIPE_SHIFT) & MCFGR_AXIPIPE_MASK));
+       }
 }
-EXPORT_SYMBOL(caam_get_era);
 
 #ifdef CONFIG_DEBUG_FS
 static int caam_debugfs_u64_get(void *data, u64 *val)
@@ -600,6 +655,8 @@ static int caam_probe(struct platform_device *pdev)
                         BLOCK_OFFSET * DECO_BLOCK_NUMBER
                         );
 
+       detect_era(ctrlpriv);
+
        /* Get CAAM-SM node and of_iomap() and save */
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-sm");
        if (!np)
@@ -617,20 +674,7 @@ static int caam_probe(struct platform_device *pdev)
                      MCFGR_WDENABLE | MCFGR_LARGE_BURST |
                      (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0));
 
-#ifdef CONFIG_ARCH_MX6
-       /*
-        * ERRATA:  mx6 devices have an issue wherein AXI bus transactions
-        * may not occur in the correct order. This isn't a problem running
-        * single descriptors, but can be if running multiple concurrent
-        * descriptors. Reworking the driver to throttle to single requests
-        * is impractical, thus the workaround is to limit the AXI pipeline
-        * to a depth of 1 (from it's default of 4) to preclude this situation
-        * from occurring.
-        */
-       wr_reg32(&topregs->ctrl.mcr,
-                (rd_reg32(&topregs->ctrl.mcr) & ~(MCFGR_AXIPIPE_MASK)) |
-                ((1 << MCFGR_AXIPIPE_SHIFT) & MCFGR_AXIPIPE_MASK));
-#endif
+       handle_imx6_err005766(ctrlpriv);
 
        /*
         *  Read the Compile Time paramters and SCFGR to determine
@@ -797,9 +841,8 @@ static int caam_probe(struct platform_device *pdev)
        caam_id = (u64)rd_reg32(&ctrl->perfmon.caam_id_ms) << 32 |
                  (u64)rd_reg32(&ctrl->perfmon.caam_id_ls);
 
-       /* Report "alive" for developer to see */
        dev_info(dev, "device ID = 0x%016llx (Era %d)\n", caam_id,
-                caam_get_era(caam_id));
+                ctrlpriv->era);
 
        dev_info(dev, "job rings = %d, qi = %d\n",
                 ctrlpriv->total_jobrs, ctrlpriv->qi_present);
index 628ce39..d52e883 100644 (file)
@@ -8,6 +8,5 @@
 #define CTRL_H
 
 /* Prototypes for backend-level services exposed to APIs */
-int caam_get_era(u64 caam_id);
 
 #endif /* CTRL_H */
index 357e698..7858764 100644 (file)
@@ -70,6 +70,13 @@ struct caam_drv_private {
        struct platform_device **jrpdev; /* Alloc'ed array per sub-device */
        struct platform_device *pdev;
 
+       /*
+        * ERA of the CAAM block,
+        * -ENOTSUPP if no era version was supplied or detected.
+        */
+#define IMX_ERR005766_ERA 4    /* ERA affected by i.mx AXI errata */
+       int era;
+
        /* Physical-presence section */
        struct caam_ctrl __iomem *ctrl; /* controller region */
        struct caam_deco __iomem *deco; /* DECO/CCB views */
index 0e836ff..0565a07 100644 (file)
@@ -286,7 +286,10 @@ struct sec_vid {
 
 #define SEC_VID_IPID_SHIFT      16
 #define SEC_VID_MAJ_SHIFT       8
-#define SEC_VID_MAJ_MASK        0xFF00
+#define SEC_VID_MAJ_MASK        0x0000FF00
+
+#define CCB_VID_ERA_SHIFT       24
+#define CCB_VID_ERA_MASK        0x000000FF
 
 struct caam_perfmon {
        /* Performance Monitor Registers                        f00-f9f */