mirror of
https://github.com/torvalds/linux.git
synced 2024-12-01 16:41:39 +00:00
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: Horia GeantA <horia.geanta@nxp.com> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com> Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com> Reviewed-by: Gaurav Jain <gaurav.jain@nxp.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
ac9a78681b
commit
da2f2a039f
@ -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
|
||||
* 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.
|
||||
*/
|
||||
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(ctrldev);
|
||||
struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
|
||||
struct caam_ctrl __iomem *ctrl;
|
||||
struct rng4tst __iomem *r4tst;
|
||||
u32 val;
|
||||
@ -618,10 +617,115 @@ static bool needs_entropy_delay_adjustment(void)
|
||||
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 */
|
||||
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;
|
||||
const struct soc_device_attribute *imx_soc_match;
|
||||
struct device *dev;
|
||||
@ -631,10 +735,8 @@ static int caam_probe(struct platform_device *pdev)
|
||||
struct caam_perfmon __iomem *perfmon;
|
||||
struct dentry *dfs_root;
|
||||
u32 scfgr, comp_params;
|
||||
u8 rng_vid;
|
||||
int pg_size;
|
||||
int BLOCK_OFFSET = 0;
|
||||
bool pr_support = false;
|
||||
bool reg_access = true;
|
||||
|
||||
ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(*ctrlpriv), GFP_KERNEL);
|
||||
@ -770,7 +872,8 @@ static int caam_probe(struct platform_device *pdev)
|
||||
|
||||
mc_version = fsl_mc_get_version();
|
||||
if (mc_version)
|
||||
pr_support = check_version(mc_version, 10, 20, 0);
|
||||
ctrlpriv->pr_support = check_version(mc_version, 10, 20,
|
||||
0);
|
||||
else
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
@ -861,9 +964,6 @@ set_dma_mask:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!reg_access)
|
||||
goto report_live;
|
||||
|
||||
comp_params = rd_reg32(&perfmon->comp_parms_ls);
|
||||
ctrlpriv->blob_present = !!(comp_params & CTPR_LS_BLOB);
|
||||
|
||||
@ -873,8 +973,6 @@ set_dma_mask:
|
||||
* check both here.
|
||||
*/
|
||||
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 &&
|
||||
(rd_reg32(&perfmon->cha_num_ls) & CHA_ID_LS_AES_MASK);
|
||||
} else {
|
||||
@ -884,91 +982,16 @@ set_dma_mask:
|
||||
(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;
|
||||
ctrlpriv->blob_present = ctrlpriv->blob_present &&
|
||||
(rd_reg32(&vreg->aesa) & CHA_VER_MISC_AES_NUM_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 && 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");
|
||||
if (reg_access) {
|
||||
ret = caam_ctrl_rng_init(dev);
|
||||
if (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 |
|
||||
(u64)rd_reg32(&perfmon->caam_id_ls);
|
||||
|
||||
|
@ -95,6 +95,7 @@ struct caam_drv_private {
|
||||
u8 blob_present; /* Nonzero if BLOB support present in device */
|
||||
u8 mc_en; /* Nonzero if MC 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 virt_en; /* Virtualization enabled in CAAM */
|
||||
int era; /* CAAM Era (internal HW revision) */
|
||||
|
Loading…
Reference in New Issue
Block a user