diff options
author | Radu Solea <radu.solea@nxp.com> | 2017-04-13 16:14:06 +0300 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:26:20 +0800 |
commit | fd77d57c39d72d36f37cf3ca5a228aa6f8c45ce7 (patch) | |
tree | bc22b1ace2193160de0d930751a7838a5221b2ce | |
parent | 8c81901173d5a51ada5c5c364a4ed90cee0acc25 (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.dtsi | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/imx6sx.dtsi | 1 | ||||
-rw-r--r-- | drivers/crypto/caam/ctrl.c | 102 | ||||
-rw-r--r-- | drivers/crypto/caam/ctrl.h | 1 | ||||
-rw-r--r-- | drivers/crypto/caam/intern.h | 7 | ||||
-rw-r--r-- | drivers/crypto/caam/regs.h | 5 |
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 */ |