summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRadu Solea <radu.solea@nxp.com>2017-04-13 16:14:06 +0300
committerJason Liu <jason.hui.liu@nxp.com>2019-02-12 10:26:20 +0800
commitfd77d57c39d72d36f37cf3ca5a228aa6f8c45ce7 (patch)
treebc22b1ace2193160de0d930751a7838a5221b2ce
parent8c81901173d5a51ada5c5c364a4ed90cee0acc25 (diff)
MLK-14284 Fix CAAM Errata err005766 handling
* 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>
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6sx.dtsi1
-rw-r--r--drivers/crypto/caam/ctrl.c102
-rw-r--r--drivers/crypto/caam/ctrl.h1
-rw-r--r--drivers/crypto/caam/intern.h7
-rw-r--r--drivers/crypto/caam/regs.h5
6 files changed, 83 insertions, 34 deletions
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 9a6d2abb6be5..eedb12b15d1d 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -1044,7 +1044,6 @@
crypto: caam@2100000 {
compatible = "fsl,sec-v4.0";
- fsl,sec-era = <4>;
#address-cells = <1>;
#size-cells = <1>;
reg = <0x2100000 0x10000>;
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index 703b1659a4d2..b7c4066e1830 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -920,7 +920,6 @@
crypto: caam@2100000 {
compatible = "fsl,sec-v4.0";
- fsl,sec-era = <4>;
#address-cells = <1>;
#size-cells = <1>;
reg = <0x2100000 0x40000>;
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index c6f031a16a30..79c3bd60d07e 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -396,14 +396,13 @@ start_rng:
clrsetbits_32(&r4tst->rtmctl, RTMCTL_PRGM, RTMCTL_SAMP_MODE_RAW_ES_SC);
}
-/**
- * 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;
@@ -437,19 +436,74 @@ 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;
+ }
+
+ ctrlpriv->era = -ENOTSUPP;
+ return;
+
+era_found:
+ ctrlpriv->era = caam_era;
+ pr_info("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;
- return -ENOTSUPP;
+ 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")) {
+ pr_info("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);
static const struct of_device_id caam_match[] = {
{
@@ -598,6 +652,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");
@@ -621,20 +677,7 @@ static int caam_probe(struct platform_device *pdev)
(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
@@ -806,9 +849,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, dpaa2 = %s\n",
ctrlpriv->total_jobrs, ctrlpriv->qi_present,
caam_dpaa2 ? "yes" : "no");
diff --git a/drivers/crypto/caam/ctrl.h b/drivers/crypto/caam/ctrl.h
index 467f128f39a8..c0a7b89e81af 100644
--- a/drivers/crypto/caam/ctrl.h
+++ b/drivers/crypto/caam/ctrl.h
@@ -9,7 +9,6 @@
#define CTRL_H
/* Prototypes for backend-level services exposed to APIs */
-int caam_get_era(u64 caam_id);
extern bool caam_dpaa2;
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 7a0575118a5d..54334b87906a 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -71,6 +71,13 @@ struct caam_drv_private {
struct device *smdev;
+ /*
+ * 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 */
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 0753c4407566..4726c15267e0 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -284,7 +284,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 */