Commit da2f2a03 authored by Horia GeantA's avatar Horia GeantA Committed by Herbert Xu

crypto: caam - refactor RNG initialization

RNG (re-)initialization will be needed on pm resume path,
thus refactor the corresponding code out of the probe callback.
Signed-off-by: default avatarHoria GeantA <horia.geanta@nxp.com>
Signed-off-by: default avatarLeonard Crestez <leonard.crestez@nxp.com>
Signed-off-by: default avatarDong Aisheng <aisheng.dong@nxp.com>
Signed-off-by: default avatarMeenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Reviewed-by: default avatarGaurav Jain <gaurav.jain@nxp.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent ac9a7868
...@@ -344,13 +344,12 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask, ...@@ -344,13 +344,12 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
/* /*
* kick_trng - sets the various parameters for enabling the initialization * kick_trng - sets the various parameters for enabling the initialization
* of the RNG4 block in CAAM * of the RNG4 block in CAAM
* @pdev - pointer to the platform device * @dev - pointer to the controller device
* @ent_delay - Defines the length (in system clocks) of each entropy sample. * @ent_delay - Defines the length (in system clocks) of each entropy sample.
*/ */
static void kick_trng(struct platform_device *pdev, int ent_delay) static void kick_trng(struct device *dev, int ent_delay)
{ {
struct device *ctrldev = &pdev->dev; struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
struct caam_ctrl __iomem *ctrl; struct caam_ctrl __iomem *ctrl;
struct rng4tst __iomem *r4tst; struct rng4tst __iomem *r4tst;
u32 val; u32 val;
...@@ -618,10 +617,115 @@ static bool needs_entropy_delay_adjustment(void) ...@@ -618,10 +617,115 @@ static bool needs_entropy_delay_adjustment(void)
return false; return false;
} }
static int caam_ctrl_rng_init(struct device *dev)
{
struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl;
int ret, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
u8 rng_vid;
if (ctrlpriv->era < 10) {
struct caam_perfmon __iomem *perfmon;
perfmon = ctrlpriv->total_jobrs ?
(struct caam_perfmon __iomem *)&ctrlpriv->jr[0]->perfmon :
(struct caam_perfmon __iomem *)&ctrl->perfmon;
rng_vid = (rd_reg32(&perfmon->cha_id_ls) &
CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
} else {
struct version_regs __iomem *vreg;
vreg = ctrlpriv->total_jobrs ?
(struct version_regs __iomem *)&ctrlpriv->jr[0]->vreg :
(struct version_regs __iomem *)&ctrl->vreg;
rng_vid = (rd_reg32(&vreg->rng) & CHA_VER_VID_MASK) >>
CHA_VER_VID_SHIFT;
}
/*
* If SEC has RNG version >= 4 and RNG state handle has not been
* already instantiated, do RNG instantiation
* In case of SoCs with Management Complex, RNG is managed by MC f/w.
*/
if (!(ctrlpriv->mc_en && ctrlpriv->pr_support) && rng_vid >= 4) {
ctrlpriv->rng4_sh_init =
rd_reg32(&ctrl->r4tst[0].rdsta);
/*
* If the secure keys (TDKEK, JDKEK, TDSK), were already
* generated, signal this to the function that is instantiating
* the state handles. An error would occur if RNG4 attempts
* to regenerate these keys before the next POR.
*/
gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1;
ctrlpriv->rng4_sh_init &= RDSTA_MASK;
do {
int inst_handles =
rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_MASK;
/*
* If either SH were instantiated by somebody else
* (e.g. u-boot) then it is assumed that the entropy
* parameters are properly set and thus the function
* setting these (kick_trng(...)) is skipped.
* Also, if a handle was instantiated, do not change
* the TRNG parameters.
*/
if (needs_entropy_delay_adjustment())
ent_delay = 12000;
if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
dev_info(dev,
"Entropy delay = %u\n",
ent_delay);
kick_trng(dev, ent_delay);
ent_delay += 400;
}
/*
* if instantiate_rng(...) fails, the loop will rerun
* and the kick_trng(...) function will modify the
* upper and lower limits of the entropy sampling
* interval, leading to a successful initialization of
* the RNG.
*/
ret = instantiate_rng(dev, inst_handles,
gen_sk);
/*
* Entropy delay is determined via TRNG characterization.
* TRNG characterization is run across different voltages
* and temperatures.
* If worst case value for ent_dly is identified,
* the loop can be skipped for that platform.
*/
if (needs_entropy_delay_adjustment())
break;
if (ret == -EAGAIN)
/*
* if here, the loop will rerun,
* so don't hog the CPU
*/
cpu_relax();
} while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
if (ret) {
dev_err(dev, "failed to instantiate RNG");
return ret;
}
/*
* Set handles initialized by this module as the complement of
* the already initialized ones
*/
ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_MASK;
/* Enable RDB bit so that RNG works faster */
clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
}
return 0;
}
/* Probe routine for CAAM top (controller) level */ /* Probe routine for CAAM top (controller) level */
static int caam_probe(struct platform_device *pdev) static int caam_probe(struct platform_device *pdev)
{ {
int ret, ring, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN; int ret, ring;
u64 caam_id; u64 caam_id;
const struct soc_device_attribute *imx_soc_match; const struct soc_device_attribute *imx_soc_match;
struct device *dev; struct device *dev;
...@@ -631,10 +735,8 @@ static int caam_probe(struct platform_device *pdev) ...@@ -631,10 +735,8 @@ static int caam_probe(struct platform_device *pdev)
struct caam_perfmon __iomem *perfmon; struct caam_perfmon __iomem *perfmon;
struct dentry *dfs_root; struct dentry *dfs_root;
u32 scfgr, comp_params; u32 scfgr, comp_params;
u8 rng_vid;
int pg_size; int pg_size;
int BLOCK_OFFSET = 0; int BLOCK_OFFSET = 0;
bool pr_support = false;
bool reg_access = true; bool reg_access = true;
ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(*ctrlpriv), GFP_KERNEL); ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(*ctrlpriv), GFP_KERNEL);
...@@ -770,7 +872,8 @@ static int caam_probe(struct platform_device *pdev) ...@@ -770,7 +872,8 @@ static int caam_probe(struct platform_device *pdev)
mc_version = fsl_mc_get_version(); mc_version = fsl_mc_get_version();
if (mc_version) if (mc_version)
pr_support = check_version(mc_version, 10, 20, 0); ctrlpriv->pr_support = check_version(mc_version, 10, 20,
0);
else else
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
...@@ -861,9 +964,6 @@ static int caam_probe(struct platform_device *pdev) ...@@ -861,9 +964,6 @@ static int caam_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
if (!reg_access)
goto report_live;
comp_params = rd_reg32(&perfmon->comp_parms_ls); comp_params = rd_reg32(&perfmon->comp_parms_ls);
ctrlpriv->blob_present = !!(comp_params & CTPR_LS_BLOB); ctrlpriv->blob_present = !!(comp_params & CTPR_LS_BLOB);
...@@ -873,8 +973,6 @@ static int caam_probe(struct platform_device *pdev) ...@@ -873,8 +973,6 @@ static int caam_probe(struct platform_device *pdev)
* check both here. * check both here.
*/ */
if (ctrlpriv->era < 10) { if (ctrlpriv->era < 10) {
rng_vid = (rd_reg32(&perfmon->cha_id_ls) &
CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
ctrlpriv->blob_present = ctrlpriv->blob_present && ctrlpriv->blob_present = ctrlpriv->blob_present &&
(rd_reg32(&perfmon->cha_num_ls) & CHA_ID_LS_AES_MASK); (rd_reg32(&perfmon->cha_num_ls) & CHA_ID_LS_AES_MASK);
} else { } else {
...@@ -884,91 +982,16 @@ static int caam_probe(struct platform_device *pdev) ...@@ -884,91 +982,16 @@ static int caam_probe(struct platform_device *pdev)
(struct version_regs __iomem *)&ctrlpriv->jr[0]->vreg : (struct version_regs __iomem *)&ctrlpriv->jr[0]->vreg :
(struct version_regs __iomem *)&ctrl->vreg; (struct version_regs __iomem *)&ctrl->vreg;
rng_vid = (rd_reg32(&vreg->rng) & CHA_VER_VID_MASK) >>
CHA_VER_VID_SHIFT;
ctrlpriv->blob_present = ctrlpriv->blob_present && ctrlpriv->blob_present = ctrlpriv->blob_present &&
(rd_reg32(&vreg->aesa) & CHA_VER_MISC_AES_NUM_MASK); (rd_reg32(&vreg->aesa) & CHA_VER_MISC_AES_NUM_MASK);
} }
/* if (reg_access) {
* If SEC has RNG version >= 4 and RNG state handle has not been ret = caam_ctrl_rng_init(dev);
* already instantiated, do RNG instantiation if (ret)
* In case of SoCs with Management Complex, RNG is managed by MC f/w.
*/
if (!(ctrlpriv->mc_en && pr_support) && rng_vid >= 4) {
ctrlpriv->rng4_sh_init =
rd_reg32(&ctrl->r4tst[0].rdsta);
/*
* If the secure keys (TDKEK, JDKEK, TDSK), were already
* generated, signal this to the function that is instantiating
* the state handles. An error would occur if RNG4 attempts
* to regenerate these keys before the next POR.
*/
gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1;
ctrlpriv->rng4_sh_init &= RDSTA_MASK;
do {
int inst_handles =
rd_reg32(&ctrl->r4tst[0].rdsta) &
RDSTA_MASK;
/*
* If either SH were instantiated by somebody else
* (e.g. u-boot) then it is assumed that the entropy
* parameters are properly set and thus the function
* setting these (kick_trng(...)) is skipped.
* Also, if a handle was instantiated, do not change
* the TRNG parameters.
*/
if (needs_entropy_delay_adjustment())
ent_delay = 12000;
if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
dev_info(dev,
"Entropy delay = %u\n",
ent_delay);
kick_trng(pdev, ent_delay);
ent_delay += 400;
}
/*
* if instantiate_rng(...) fails, the loop will rerun
* and the kick_trng(...) function will modify the
* upper and lower limits of the entropy sampling
* interval, leading to a successful initialization of
* the RNG.
*/
ret = instantiate_rng(dev, inst_handles,
gen_sk);
/*
* Entropy delay is determined via TRNG characterization.
* TRNG characterization is run across different voltages
* and temperatures.
* If worst case value for ent_dly is identified,
* the loop can be skipped for that platform.
*/
if (needs_entropy_delay_adjustment())
break;
if (ret == -EAGAIN)
/*
* if here, the loop will rerun,
* so don't hog the CPU
*/
cpu_relax();
} while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
if (ret) {
dev_err(dev, "failed to instantiate RNG");
return ret; return ret;
}
/*
* Set handles initialized by this module as the complement of
* the already initialized ones
*/
ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_MASK;
/* Enable RDB bit so that RNG works faster */
clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
} }
report_live:
/* NOTE: RTIC detection ought to go here, around Si time */
caam_id = (u64)rd_reg32(&perfmon->caam_id_ms) << 32 | caam_id = (u64)rd_reg32(&perfmon->caam_id_ms) << 32 |
(u64)rd_reg32(&perfmon->caam_id_ls); (u64)rd_reg32(&perfmon->caam_id_ls);
......
...@@ -95,6 +95,7 @@ struct caam_drv_private { ...@@ -95,6 +95,7 @@ struct caam_drv_private {
u8 blob_present; /* Nonzero if BLOB support present in device */ u8 blob_present; /* Nonzero if BLOB support present in device */
u8 mc_en; /* Nonzero if MC f/w is active */ u8 mc_en; /* Nonzero if MC f/w is active */
u8 optee_en; /* Nonzero if OP-TEE f/w is active */ u8 optee_en; /* Nonzero if OP-TEE f/w is active */
bool pr_support; /* RNG prediction resistance available */
int secvio_irq; /* Security violation interrupt number */ int secvio_irq; /* Security violation interrupt number */
int virt_en; /* Virtualization enabled in CAAM */ int virt_en; /* Virtualization enabled in CAAM */
int era; /* CAAM Era (internal HW revision) */ int era; /* CAAM Era (internal HW revision) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment