diff mbox series

[RFC,4/4] crypto: caam - use job ring for RNG instantiation instead of DECO

Message ID 20190222100613.2290-5-christopher.spencer@sea.co.uk (mailing list archive)
State RFC
Delegated to: Herbert Xu
Headers show
Series crypto: caam - Add i.MX8MQ support | expand

Commit Message

Chris Spencer Feb. 22, 2019, 10:06 a.m. UTC
From: Chris Spencer <christopher.spencer@sea.co.uk>

This is required to support the i.MX8.

Signed-off-by: Chris Spencer <christopher.spencer@sea.co.uk>
---
 drivers/crypto/caam/Makefile   |   2 +-
 drivers/crypto/caam/ctrl.c     | 399 +--------------------------------
 drivers/crypto/caam/inst_rng.c | 374 ++++++++++++++++++++++++++++++
 drivers/crypto/caam/inst_rng.h |  18 ++
 drivers/crypto/caam/jr.c       |  15 +-
 5 files changed, 408 insertions(+), 400 deletions(-)
 create mode 100644 drivers/crypto/caam/inst_rng.c
 create mode 100644 drivers/crypto/caam/inst_rng.h

Comments

Horia Geanta Feb. 25, 2019, 2:22 p.m. UTC | #1
On 2/22/2019 12:07 PM, spencercw@gmail.com wrote:
> From: Chris Spencer <christopher.spencer@sea.co.uk>
> 
> This is required to support the i.MX8.
> 
Why exactly is this required?
You should provide more details.

Strictly related to the implementation, why is the code moved to a new file?
Please do not shuffle the code without providing a good reason.

Horia
Chris Spencer Feb. 25, 2019, 2:36 p.m. UTC | #2
On Mon, 25 Feb 2019 at 14:22, Horia Geanta <horia.geanta@nxp.com> wrote:
>
> On 2/22/2019 12:07 PM, spencercw@gmail.com wrote:
> > From: Chris Spencer <christopher.spencer@sea.co.uk>
> >
> > This is required to support the i.MX8.
> >
> Why exactly is this required?
> You should provide more details.

I don't know. :) These changes were made in [1], although the change
is actually described in [2] where it says: "Use a Job ring for RNG
instantiation rather than DECO, even for i.MX6/7 families." This does
indeed seem to be necessary to get it to work, but I can only
speculate why.

The original commit which added the run_descriptor_deco0 function [3]
states "[...] and another function that performs the running of the
said descriptor using the DECO debug mechanism." My best guess is that
the DECO debug mechanism is no longer available so it has to go via
the job ring.

> Strictly related to the implementation, why is the code moved to a new file?
> Please do not shuffle the code without providing a good reason.

This was done in an attempt to keep it reasonably close to the changes
in the downstream driver. The file was moved in [1] with the
description "Move the code related to RNG instanciation to another
file to ease comprehension."

The RNG initialisation code is not really needed in ctrl.c anymore
since it is only used in jr.c, so moving it out seems sensible.

Thanks,
Chris

[1] https://source.codeaurora.org/external/imx/linux-imx/commit/drivers/crypto/caam/inst_rng.c?h=imx_4.14.78_1.0.0_ga&id=5fd8fe866172c38e8cd07741d98d79b995f05bc9
[2] https://source.codeaurora.org/external/imx/linux-imx/commit/drivers/crypto/caam/ctrl.c?h=imx_4.14.78_1.0.0_ga&id=afa53c2c96a54b4432a26372e3b5e7dbccbb9671
[3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/crypto/caam/ctrl.c?id=04cddbfe6b5f334aa337a1a9797eb8914822f2f8
Horia Geanta Feb. 26, 2019, 2:53 p.m. UTC | #3
On 2/25/2019 4:37 PM, Chris Spencer wrote:
> On Mon, 25 Feb 2019 at 14:22, Horia Geanta <horia.geanta@nxp.com> wrote:
>>
>> On 2/22/2019 12:07 PM, spencercw@gmail.com wrote:
>>> From: Chris Spencer <christopher.spencer@sea.co.uk>
>>>
>>> This is required to support the i.MX8.
>>>
>> Why exactly is this required?
>> You should provide more details.
> 
> I don't know. :) These changes were made in [1], although the change
> is actually described in [2] where it says: "Use a Job ring for RNG
> instantiation rather than DECO, even for i.MX6/7 families." This does
> indeed seem to be necessary to get it to work, but I can only
> speculate why.
> 
The commit messages you refer are indeed rather poor, however you need to
understand the context: the history reflects NXP internal development.

It's expected for the changes to be clearly explained, justified when reaching
mainline kernel.

> The original commit which added the run_descriptor_deco0 function [3]
> states "[...] and another function that performs the running of the
> said descriptor using the DECO debug mechanism." My best guess is that
> the DECO debug mechanism is no longer available so it has to go via
> the job ring.
> 
This change is actually orthogonal to i.MX8 MQ support and is related to
SECO-based i.MX8 SoCs (QXP, QM) and/or OP-TEE support.

Access to CAAM global registers (CCSR page 0) won't be allowed in cases when
Linux runs in Normal World.
From this perspective, it makes sense to eliminate accesses to these registers.
Some of the accesses are done for RNG initialization via the DECO debug
mechanism; to remove them, RNG is initialized via the Job Ring interface.
However, I still see some illegal accesses - for e.g. reading RDSTA register to
check which virtual RNGs ("state handles" in RM terms) are already initialized.

It looks like cutting access to CAAM global registers must come with some
assumptions (since it implies some checks can no longer be performed, see RDSTA
above).
For e.g. in case OP-TEE is detected, we could assume that RNG was already
initialized. Similar for other cases like SECO f/w (i.MX8 QM and QXP).
If we make this assumption, it actually means RNG initialization is no longer
needed:

if (!ctrlpriv->mc_en && rng_vid >= 4 && !normal_world) {
	... // rng init as before - using DECO debug mechanism
}

>> Strictly related to the implementation, why is the code moved to a new file?
>> Please do not shuffle the code without providing a good reason.
> 
> This was done in an attempt to keep it reasonably close to the changes
> in the downstream driver. The file was moved in [1] with the
> description "Move the code related to RNG instanciation to another
> file to ease comprehension."
> 
> The RNG initialisation code is not really needed in ctrl.c anymore
> since it is only used in jr.c, so moving it out seems sensible.
> 
> Thanks,
> Chris
> 
> [1] https://source.codeaurora.org/external/imx/linux-imx/commit/drivers/crypto/caam/inst_rng.c?h=imx_4.14.78_1.0.0_ga&id=5fd8fe866172c38e8cd07741d98d79b995f05bc9
> [2] https://source.codeaurora.org/external/imx/linux-imx/commit/drivers/crypto/caam/ctrl.c?h=imx_4.14.78_1.0.0_ga&id=afa53c2c96a54b4432a26372e3b5e7dbccbb9671
> [3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/crypto/caam/ctrl.c?id=04cddbfe6b5f334aa337a1a9797eb8914822f2f8
>
Chris Spencer Feb. 26, 2019, 4:24 p.m. UTC | #4
On Tue, 26 Feb 2019 at 14:53, Horia Geanta <horia.geanta@nxp.com> wrote:
> On 2/25/2019 4:37 PM, Chris Spencer wrote:
> > On Mon, 25 Feb 2019 at 14:22, Horia Geanta <horia.geanta@nxp.com> wrote:
> >>
> >> On 2/22/2019 12:07 PM, spencercw@gmail.com wrote:
> >>> From: Chris Spencer <christopher.spencer@sea.co.uk>
> >>>
> >>> This is required to support the i.MX8.
> >>>
> >> Why exactly is this required?
> >> You should provide more details.
> >
> > I don't know. :) These changes were made in [1], although the change
> > is actually described in [2] where it says: "Use a Job ring for RNG
> > instantiation rather than DECO, even for i.MX6/7 families." This does
> > indeed seem to be necessary to get it to work, but I can only
> > speculate why.
> >
> The commit messages you refer are indeed rather poor, however you need to
> understand the context: the history reflects NXP internal development.
>
> It's expected for the changes to be clearly explained, justified when reaching
> mainline kernel.

Ok, I will expand the commit message for the next version.

> > The original commit which added the run_descriptor_deco0 function [3]
> > states "[...] and another function that performs the running of the
> > said descriptor using the DECO debug mechanism." My best guess is that
> > the DECO debug mechanism is no longer available so it has to go via
> > the job ring.
> >
> This change is actually orthogonal to i.MX8 MQ support and is related to
> SECO-based i.MX8 SoCs (QXP, QM) and/or OP-TEE support.
>
> Access to CAAM global registers (CCSR page 0) won't be allowed in cases when
> Linux runs in Normal World.
> From this perspective, it makes sense to eliminate accesses to these registers.
> Some of the accesses are done for RNG initialization via the DECO debug
> mechanism; to remove them, RNG is initialized via the Job Ring interface.
> However, I still see some illegal accesses - for e.g. reading RDSTA register to
> check which virtual RNGs ("state handles" in RM terms) are already initialized.
>
> It looks like cutting access to CAAM global registers must come with some
> assumptions (since it implies some checks can no longer be performed, see RDSTA
> above).
> For e.g. in case OP-TEE is detected, we could assume that RNG was already
> initialized. Similar for other cases like SECO f/w (i.MX8 QM and QXP).
> If we make this assumption, it actually means RNG initialization is no longer
> needed:
>
> if (!ctrlpriv->mc_en && rng_vid >= 4 && !normal_world) {
>         ... // rng init as before - using DECO debug mechanism
> }

Thanks for the information. This is more problematic than I had
anticipated. It sounds like these are the possible scenarios:

1. Linux is running in the normal world without OP-TEE/SECO; RNG must
be initialised via the job ring. No way of checking whether the RNG is
already initialised.
2. Linux is running in the normal world with OP-TEE/SECO; RNG
initialisation is not required.
3. Linux is running in the secure world without OP-TEE/SECO; RNG can
be initialised via DECO debug mechanism or job ring.
4. Linux is running in the secure world with OP-TEE/SECO; RNG
initialisation is not required. This sounds like a very unlikely
configuration.

My build is currently sitting in scenario 1, which would explain why
the RNG initialisation via DECO was failing. Clearly it can be made to
work by running the initialisation via the job ring and assuming the
RNG has not already been initialised, but I'm getting the impression
that this may not be a sensible configuration.

Is running Linux in the secure world a typical configuration? It's not
a conscious choice I've made to run it in the normal world; that's
just what the TF-A is doing. I suppose it's either that or start using
OP-TEE so it can initialise the RNG.

As far as driver support goes, are we only interested in scenarios 2
and 3? I'm not really sure how we would detect which world we are
running in, or whether OP-TEE has initialised the RNG.

Thanks,
Chris
Chris Spencer Feb. 28, 2019, 11:33 a.m. UTC | #5
On Tue, 26 Feb 2019 at 16:24, Chris Spencer <spencercw@gmail.com> wrote:
> > > The original commit which added the run_descriptor_deco0 function [3]
> > > states "[...] and another function that performs the running of the
> > > said descriptor using the DECO debug mechanism." My best guess is that
> > > the DECO debug mechanism is no longer available so it has to go via
> > > the job ring.
> > >
> > This change is actually orthogonal to i.MX8 MQ support and is related to
> > SECO-based i.MX8 SoCs (QXP, QM) and/or OP-TEE support.
> >
> > Access to CAAM global registers (CCSR page 0) won't be allowed in cases when
> > Linux runs in Normal World.
> > From this perspective, it makes sense to eliminate accesses to these registers.
> > Some of the accesses are done for RNG initialization via the DECO debug
> > mechanism; to remove them, RNG is initialized via the Job Ring interface.
> > However, I still see some illegal accesses - for e.g. reading RDSTA register to
> > check which virtual RNGs ("state handles" in RM terms) are already initialized.
> >
> > It looks like cutting access to CAAM global registers must come with some
> > assumptions (since it implies some checks can no longer be performed, see RDSTA
> > above).
> > For e.g. in case OP-TEE is detected, we could assume that RNG was already
> > initialized. Similar for other cases like SECO f/w (i.MX8 QM and QXP).
> > If we make this assumption, it actually means RNG initialization is no longer
> > needed:
> >
> > if (!ctrlpriv->mc_en && rng_vid >= 4 && !normal_world) {
> >         ... // rng init as before - using DECO debug mechanism
> > }
>
> Thanks for the information. This is more problematic than I had
> anticipated. It sounds like these are the possible scenarios:
>
> 1. Linux is running in the normal world without OP-TEE/SECO; RNG must
> be initialised via the job ring. No way of checking whether the RNG is
> already initialised.
> 2. Linux is running in the normal world with OP-TEE/SECO; RNG
> initialisation is not required.
> 3. Linux is running in the secure world without OP-TEE/SECO; RNG can
> be initialised via DECO debug mechanism or job ring.
> 4. Linux is running in the secure world with OP-TEE/SECO; RNG
> initialisation is not required. This sounds like a very unlikely
> configuration.
>
> My build is currently sitting in scenario 1, which would explain why
> the RNG initialisation via DECO was failing. Clearly it can be made to
> work by running the initialisation via the job ring and assuming the
> RNG has not already been initialised, but I'm getting the impression
> that this may not be a sensible configuration.
>
> Is running Linux in the secure world a typical configuration? It's not
> a conscious choice I've made to run it in the normal world; that's
> just what the TF-A is doing. I suppose it's either that or start using
> OP-TEE so it can initialise the RNG.
>
> As far as driver support goes, are we only interested in scenarios 2
> and 3? I'm not really sure how we would detect which world we are
> running in, or whether OP-TEE has initialised the RNG.

Alright I think I'm making some progress on this. It seems that page 0
*is* available on the i.MX8M. I think it is the non-M variants with
the SECO which don't have this access.

What I have found is that if I set virt_en = 1 then the RNG is able to
initialise correctly via the DECO. The register values I am seeing
are:

comp_params = 01914201
scfgr = 00000001

So:
VIRT_EN_INCL = 1 & VIRT_EN_POR = 0 & SCFGR_VIRT_EN = 0

I don't have the i.MX8 security reference manual so there's only so
much analysis I can do, but it seems that virtualisation is enabled in
hardware without the registers reflecting that appropriately. If I
patch the TF-A to set SCFGR_VIRT_EN = 1 in the same place it sets
CAAM_JRxMID = 1 then everything seems to work, but I've got no idea if
that is an appropriate change to make.

Chris
Horia Geanta March 4, 2019, 6:13 p.m. UTC | #6
On 2/28/2019 1:34 PM, Chris Spencer wrote:
> What I have found is that if I set virt_en = 1 then the RNG is able to
> initialise correctly via the DECO. The register values I am seeing
> are:
> 
> comp_params = 01914201
> scfgr = 00000001
> 
> So:
> VIRT_EN_INCL = 1 & VIRT_EN_POR = 0 & SCFGR_VIRT_EN = 0
> 
> I don't have the i.MX8 security reference manual so there's only so
RM should be available from here:
https://www.nxp.com/webapp/sps/download/mod_download.jsp?colCode=IMX8MDQLQSRM&location=null&appType=moderated

> much analysis I can do, but it seems that virtualisation is enabled in
> hardware without the registers reflecting that appropriately. If I
> patch the TF-A to set SCFGR_VIRT_EN = 1 in the same place it sets
> CAAM_JRxMID = 1 then everything seems to work, but I've got no idea if
> that is an appropriate change to make.
> 
RNG initialization should work in both cases.

The root cause for the failure in case virtualization is disabled is probably
the lack of setup of DECO DID registers (offsets A0h, A4h).

Section "Register-based service interface" mentions:
"But before requesting a DECO, software must specify the DID and SDID values
that will be used when executing descriptors under direct software control. When
virtualization is disabled (SCFGR[VIRT_EN]=0), these values are specified by
writing DID and SDID values into the appropriate DECO DID_MS and DECO DID_LS
registers."

Horia
Chris Spencer March 5, 2019, 8:54 a.m. UTC | #7
Hi Horia,

On Mon, 4 Mar 2019 at 18:13, Horia Geanta <horia.geanta@nxp.com> wrote:
> > I don't have the i.MX8 security reference manual so there's only so
> RM should be available from here:
> https://www.nxp.com/webapp/sps/download/mod_download.jsp?colCode=IMX8MDQLQSRM&location=null&appType=moderated

Unfortunately this requires an NXP Salesperson/FAE Name and FAE Email
Address, which I don't have. I did put in a request on Thursday via
the live chat, but so far nobody from sales has contacted me.

> > much analysis I can do, but it seems that virtualisation is enabled in
> > hardware without the registers reflecting that appropriately. If I
> > patch the TF-A to set SCFGR_VIRT_EN = 1 in the same place it sets
> > CAAM_JRxMID = 1 then everything seems to work, but I've got no idea if
> > that is an appropriate change to make.
> >
> RNG initialization should work in both cases.
>
> The root cause for the failure in case virtualization is disabled is probably
> the lack of setup of DECO DID registers (offsets A0h, A4h).
>
> Section "Register-based service interface" mentions:
> "But before requesting a DECO, software must specify the DID and SDID values
> that will be used when executing descriptors under direct software control. When
> virtualization is disabled (SCFGR[VIRT_EN]=0), these values are specified by
> writing DID and SDID values into the appropriate DECO DID_MS and DECO DID_LS
> registers."

Not having much luck here either. In the TF-A it sets JRxMID to 1; I
have added extra lines in the same place to set DECO0MID_MS
(0x309000a0) to 1 and DECO0MID_LS (0x309000a4) to 0x10001, but it
still fails to acquire the DECO when initialising the RNG.

It's possible I'm just using the wrong values. I'm still working from
the i.MX6 security reference manual which doesn't seem to talk about
DIDs or SDIDs so I don't know what these mean.

Thanks,
Chris
diff mbox series

Patch

diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 7bbfd06a11ff..1acd3dd2fb07 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -20,7 +20,7 @@  obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caam_pkc.o
 
 caam-objs := ctrl.o
-caam_jr-objs := jr.o key_gen.o
+caam_jr-objs := jr.o key_gen.o inst_rng.o
 caam_pkc-y := caampkc.o pkc_desc.o
 ifneq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI),)
 	ccflags-y += -DCONFIG_CAAM_QI
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 36543a151e1e..e547e2ee5fcc 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -39,280 +39,6 @@  static inline struct clk *caam_drv_identify_clk(struct device *dev,
 	return caam_imx ? devm_clk_get(dev, clk_name) : NULL;
 }
 
-/*
- * Descriptor to instantiate RNG State Handle 0 in normal mode and
- * load the JDKEK, TDKEK and TDSK registers
- */
-static void build_instantiation_desc(u32 *desc, int handle, int do_sk)
-{
-	u32 *jump_cmd, op_flags;
-
-	init_job_desc(desc, 0);
-
-	op_flags = OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
-			(handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT;
-
-	/* INIT RNG in non-test mode */
-	append_operation(desc, op_flags);
-
-	if (!handle && do_sk) {
-		/*
-		 * For SH0, Secure Keys must be generated as well
-		 */
-
-		/* wait for done */
-		jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
-		set_jump_tgt_here(desc, jump_cmd);
-
-		/*
-		 * load 1 to clear written reg:
-		 * resets the done interrrupt and returns the RNG to idle.
-		 */
-		append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
-
-		/* Initialize State Handle  */
-		append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
-				 OP_ALG_AAI_RNG4_SK);
-	}
-
-	append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
-}
-
-/* Descriptor for deinstantiation of State Handle 0 of the RNG block. */
-static void build_deinstantiation_desc(u32 *desc, int handle)
-{
-	init_job_desc(desc, 0);
-
-	/* Uninstantiate State Handle 0 */
-	append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
-			 (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INITFINAL);
-
-	append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
-}
-
-/*
- * run_descriptor_deco0 - runs a descriptor on DECO0, under direct control of
- *			  the software (no JR/QI used).
- * @ctrldev - pointer to device
- * @status - descriptor status, after being run
- *
- * Return: - 0 if no error occurred
- *	   - -ENODEV if the DECO couldn't be acquired
- *	   - -EAGAIN if an error occurred while executing the descriptor
- */
-static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
-					u32 *status)
-{
-	struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
-	struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl;
-	struct caam_deco __iomem *deco = ctrlpriv->deco;
-	unsigned int timeout = 100000;
-	u32 deco_dbg_reg, deco_state, flags;
-	int i;
-
-
-	if (ctrlpriv->virt_en == 1) {
-		clrsetbits_32(&ctrl->deco_rsr, 0, DECORSR_JR0);
-
-		while (!(rd_reg32(&ctrl->deco_rsr) & DECORSR_VALID) &&
-		       --timeout)
-			cpu_relax();
-
-		timeout = 100000;
-	}
-
-	clrsetbits_32(&ctrl->deco_rq, 0, DECORR_RQD0ENABLE);
-
-	while (!(rd_reg32(&ctrl->deco_rq) & DECORR_DEN0) &&
-								 --timeout)
-		cpu_relax();
-
-	if (!timeout) {
-		dev_err(ctrldev, "failed to acquire DECO 0\n");
-		clrsetbits_32(&ctrl->deco_rq, DECORR_RQD0ENABLE, 0);
-		return -ENODEV;
-	}
-
-	for (i = 0; i < desc_len(desc); i++)
-		wr_reg32(&deco->descbuf[i], caam32_to_cpu(*(desc + i)));
-
-	flags = DECO_JQCR_WHL;
-	/*
-	 * If the descriptor length is longer than 4 words, then the
-	 * FOUR bit in JRCTRL register must be set.
-	 */
-	if (desc_len(desc) >= 4)
-		flags |= DECO_JQCR_FOUR;
-
-	/* Instruct the DECO to execute it */
-	clrsetbits_32(&deco->jr_ctl_hi, 0, flags);
-
-	timeout = 10000000;
-	do {
-		deco_dbg_reg = rd_reg32(&deco->desc_dbg);
-
-		if (ctrlpriv->era < 10)
-			deco_state = (deco_dbg_reg & DESC_DBG_DECO_STAT_MASK) >>
-				     DESC_DBG_DECO_STAT_SHIFT;
-		else
-			deco_state = (rd_reg32(&deco->dbg_exec) &
-				      DESC_DER_DECO_STAT_MASK) >>
-				     DESC_DER_DECO_STAT_SHIFT;
-
-		/*
-		 * If an error occured in the descriptor, then
-		 * the DECO status field will be set to 0x0D
-		 */
-		if (deco_state == DECO_STAT_HOST_ERR)
-			break;
-
-		cpu_relax();
-	} while ((deco_dbg_reg & DESC_DBG_DECO_STAT_VALID) && --timeout);
-
-	*status = rd_reg32(&deco->op_status_hi) &
-		  DECO_OP_STATUS_HI_ERR_MASK;
-
-	if (ctrlpriv->virt_en == 1)
-		clrsetbits_32(&ctrl->deco_rsr, DECORSR_JR0, 0);
-
-	/* Mark the DECO as free */
-	clrsetbits_32(&ctrl->deco_rq, DECORR_RQD0ENABLE, 0);
-
-	if (!timeout)
-		return -EAGAIN;
-
-	return 0;
-}
-
-/*
- * instantiate_rng - builds and executes a descriptor on DECO0,
- *		     which initializes the RNG block.
- * @ctrldev - pointer to device
- * @state_handle_mask - bitmask containing the instantiation status
- *			for the RNG4 state handles which exist in
- *			the RNG4 block: 1 if it's been instantiated
- *			by an external entry, 0 otherwise.
- * @gen_sk  - generate data to be loaded into the JDKEK, TDKEK and TDSK;
- *	      Caution: this can be done only once; if the keys need to be
- *	      regenerated, a POR is required
- *
- * Return: - 0 if no error occurred
- *	   - -ENOMEM if there isn't enough memory to allocate the descriptor
- *	   - -ENODEV if DECO0 couldn't be acquired
- *	   - -EAGAIN if an error occurred when executing the descriptor
- *	      f.i. there was a RNG hardware error due to not "good enough"
- *	      entropy being aquired.
- */
-static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
-			   int gen_sk)
-{
-	struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
-	struct caam_ctrl __iomem *ctrl;
-	u32 *desc, status = 0, rdsta_val;
-	int ret = 0, sh_idx;
-
-	ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
-	desc = kmalloc(CAAM_CMD_SZ * 7, GFP_KERNEL);
-	if (!desc)
-		return -ENOMEM;
-
-	for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
-		/*
-		 * If the corresponding bit is set, this state handle
-		 * was initialized by somebody else, so it's left alone.
-		 */
-		if ((1 << sh_idx) & state_handle_mask)
-			continue;
-
-		/* Create the descriptor for instantiating RNG State Handle */
-		build_instantiation_desc(desc, sh_idx, gen_sk);
-
-		/* Try to run it through DECO0 */
-		ret = run_descriptor_deco0(ctrldev, desc, &status);
-
-		/*
-		 * If ret is not 0, or descriptor status is not 0, then
-		 * something went wrong. No need to try the next state
-		 * handle (if available), bail out here.
-		 * Also, if for some reason, the State Handle didn't get
-		 * instantiated although the descriptor has finished
-		 * without any error (HW optimizations for later
-		 * CAAM eras), then try again.
-		 */
-		if (ret)
-			break;
-
-		rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK;
-		if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) ||
-		    !(rdsta_val & (1 << sh_idx))) {
-			ret = -EAGAIN;
-			break;
-		}
-
-		dev_info(ctrldev, "Instantiated RNG4 SH%d\n", sh_idx);
-		/* Clear the contents before recreating the descriptor */
-		memset(desc, 0x00, CAAM_CMD_SZ * 7);
-	}
-
-	kfree(desc);
-
-	return ret;
-}
-
-/*
- * deinstantiate_rng - builds and executes a descriptor on DECO0,
- *		       which deinitializes the RNG block.
- * @ctrldev - pointer to device
- * @state_handle_mask - bitmask containing the instantiation status
- *			for the RNG4 state handles which exist in
- *			the RNG4 block: 1 if it's been instantiated
- *
- * Return: - 0 if no error occurred
- *	   - -ENOMEM if there isn't enough memory to allocate the descriptor
- *	   - -ENODEV if DECO0 couldn't be acquired
- *	   - -EAGAIN if an error occurred when executing the descriptor
- */
-static int deinstantiate_rng(struct device *ctrldev, int state_handle_mask)
-{
-	u32 *desc, status;
-	int sh_idx, ret = 0;
-
-	desc = kmalloc(CAAM_CMD_SZ * 3, GFP_KERNEL);
-	if (!desc)
-		return -ENOMEM;
-
-	for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
-		/*
-		 * If the corresponding bit is set, then it means the state
-		 * handle was initialized by us, and thus it needs to be
-		 * deinitialized as well
-		 */
-		if ((1 << sh_idx) & state_handle_mask) {
-			/*
-			 * Create the descriptor for deinstantating this state
-			 * handle
-			 */
-			build_deinstantiation_desc(desc, sh_idx);
-
-			/* Try to run it through DECO0 */
-			ret = run_descriptor_deco0(ctrldev, desc, &status);
-
-			if (ret ||
-			    (status && status != JRSTA_SSRC_JUMP_HALT_CC)) {
-				dev_err(ctrldev,
-					"Failed to deinstantiate RNG4 SH%d\n",
-					sh_idx);
-				break;
-			}
-			dev_info(ctrldev, "Deinstantiated RNG4 SH%d\n", sh_idx);
-		}
-	}
-
-	kfree(desc);
-
-	return ret;
-}
-
 static int caam_remove(struct platform_device *pdev)
 {
 	struct device *ctrldev;
@@ -331,13 +57,6 @@  static int caam_remove(struct platform_device *pdev)
 		caam_qi_shutdown(ctrlpriv->qidev);
 #endif
 
-	/*
-	 * De-initialize RNG state handles initialized by this driver.
-	 * In case of SoCs with Management Complex, RNG is managed by MC f/w.
-	 */
-	if (!ctrlpriv->mc_en && ctrlpriv->rng4_sh_init)
-		deinstantiate_rng(ctrldev, ctrlpriv->rng4_sh_init);
-
 	/* Shut down debug views */
 #ifdef CONFIG_DEBUG_FS
 	debugfs_remove_recursive(ctrlpriv->dfs_root);
@@ -356,57 +75,6 @@  static int caam_remove(struct platform_device *pdev)
 	return 0;
 }
 
-/*
- * kick_trng - sets the various parameters for enabling the initialization
- *	       of the RNG4 block in CAAM
- * @pdev - pointer to the platform device
- * @ent_delay - Defines the length (in system clocks) of each entropy sample.
- */
-static void kick_trng(struct platform_device *pdev, int ent_delay)
-{
-	struct device *ctrldev = &pdev->dev;
-	struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
-	struct caam_ctrl __iomem *ctrl;
-	struct rng4tst __iomem *r4tst;
-	u32 val;
-
-	ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
-	r4tst = &ctrl->r4tst[0];
-
-	/* put RNG4 into program mode */
-	clrsetbits_32(&r4tst->rtmctl, 0, RTMCTL_PRGM);
-
-	/*
-	 * Performance-wise, it does not make sense to
-	 * set the delay to a value that is lower
-	 * than the last one that worked (i.e. the state handles
-	 * were instantiated properly. Thus, instead of wasting
-	 * time trying to set the values controlling the sample
-	 * frequency, the function simply returns.
-	 */
-	val = (rd_reg32(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK)
-	      >> RTSDCTL_ENT_DLY_SHIFT;
-	if (ent_delay <= val)
-		goto start_rng;
-
-	val = rd_reg32(&r4tst->rtsdctl);
-	val = (val & ~RTSDCTL_ENT_DLY_MASK) |
-	      (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
-	wr_reg32(&r4tst->rtsdctl, val);
-	/* min. freq. count, equal to 1/4 of the entropy sample length */
-	wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2);
-	/* disable maximum frequency count */
-	wr_reg32(&r4tst->rtfrqmax, RTFRQMAX_DISABLE);
-	/* read the control register */
-	val = rd_reg32(&r4tst->rtmctl);
-start_rng:
-	/*
-	 * select raw sampling in both entropy shifter
-	 * and statistical checker; ; put RNG4 into run mode
-	 */
-	clrsetbits_32(&r4tst->rtmctl, RTMCTL_PRGM, RTMCTL_SAMP_MODE_RAW_ES_SC);
-}
-
 static int caam_get_era_from_hw(struct caam_ctrl __iomem *ctrl)
 {
 	static const struct {
@@ -571,7 +239,7 @@  MODULE_DEVICE_TABLE(of, caam_match);
 /* 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;
 	static const struct soc_device_attribute imx_soc[] = {
 		{.family = "Freescale i.MX"},
@@ -771,71 +439,6 @@  static int caam_probe(struct platform_device *pdev)
 		rng_vid = (rd_reg32(&ctrl->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 && 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_IFMASK;
-		do {
-			int inst_handles =
-				rd_reg32(&ctrl->r4tst[0].rdsta) &
-								RDSTA_IFMASK;
-			/*
-			 * 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 (!(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 modfiy the
-			 * upper and lower limits of the entropy sampling
-			 * interval, leading to a sucessful initialization of
-			 * the RNG.
-			 */
-			ret = instantiate_rng(dev, inst_handles,
-					      gen_sk);
-			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");
-			goto caam_remove;
-		}
-		/*
-		 * Set handles init'ed by this module as the complement of the
-		 * already initialized ones
-		 */
-		ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_IFMASK;
-
-		/* Enable RDB bit so that RNG works faster */
-		clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
-	}
-
 	/* NOTE: RTIC detection ought to go here, around Si time */
 
 	caam_id = (u64)rd_reg32(&ctrl->perfmon.caam_id_ms) << 32 |
diff --git a/drivers/crypto/caam/inst_rng.c b/drivers/crypto/caam/inst_rng.c
new file mode 100644
index 000000000000..851bf7374cdb
--- /dev/null
+++ b/drivers/crypto/caam/inst_rng.c
@@ -0,0 +1,374 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CAAM RNG instantiation driver backend
+ *
+ * Copyright 2017-2018 NXP
+ */
+
+#include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/wait.h>
+#include "compat.h"
+#include "regs.h"
+#include "intern.h"
+#include "jr.h"
+#include "desc_constr.h"
+#include "error.h"
+#include "ctrl.h"
+#include "inst_rng.h"
+
+static DECLARE_WAIT_QUEUE_HEAD(wq_desc);
+static int desc_completed;
+static int desc_status;
+
+/*
+ * Descriptor to instantiate RNG State Handle 0 in normal mode and
+ * load the JDKEK, TDKEK and TDSK registers
+ */
+static void build_instantiation_desc(u32 *desc, int handle, int do_sk)
+{
+	u32 *jump_cmd, op_flags;
+
+	init_job_desc(desc, 0);
+
+	op_flags = OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+			(handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT;
+
+	/* INIT RNG in non-test mode */
+	append_operation(desc, op_flags);
+
+	if (!handle && do_sk) {
+		/*
+		 * For SH0, Secure Keys must be generated as well
+		 */
+
+		/* wait for done */
+		jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
+		set_jump_tgt_here(desc, jump_cmd);
+
+		/*
+		 * load 1 to clear written reg:
+		 * resets the done interrupt and returns the RNG to idle.
+		 */
+		append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
+
+		/* Initialize State Handle  */
+		append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+				 OP_ALG_AAI_RNG4_SK);
+	}
+
+	append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
+}
+
+/* Descriptor for deinstantiation of State Handle 0 of the RNG block. */
+static void build_deinstantiation_desc(u32 *desc, int handle)
+{
+	init_job_desc(desc, 0);
+
+	/* Uninstantiate State Handle 0 */
+	append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+			 (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INITFINAL);
+
+	append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
+}
+
+void cbk_jr_rng_inst(struct device *jrdev, u32 *desc, u32 status, void *areq)
+{
+	if ((status & JRSTA_SSRC_JUMP_HALT_CC) == JRSTA_SSRC_JUMP_HALT_CC) {
+		dev_info(jrdev, "Instantiated RNG4 SH%d.\n", *((int *)areq));
+		desc_status = 0;
+	} else {
+		desc_status = -EAGAIN;
+	}
+	desc_completed = 1;
+	wake_up(&wq_desc);
+}
+
+/*
+ * run_descriptor_jr - runs a descriptor on first JR
+ * @status - descriptor status, after being run
+ *
+ * Return: - 0 if no error occurred
+ *	   - -ENODEV if the JR couldn't be acquired
+ *	   - -EAGAIN if an error occurred while executing the descriptor
+ */
+static int run_descriptor_jr(u32 *desc, int sh_idx)
+{
+	struct device *jrdev;
+	int ret;
+
+	jrdev = caam_jr_alloc();
+	if (IS_ERR(jrdev)) {
+		pr_err("Job Ring Device allocation for transform failed\n");
+		return -ENODEV;
+	}
+	ret = caam_jr_enqueue(jrdev, desc, cbk_jr_rng_inst, &sh_idx);
+	if (ret) {
+		dev_err(jrdev, "caam_jr_enqueue() failed\n");
+		return ret;
+	}
+
+	/* wait for job descriptor completion */
+	wait_event(wq_desc, desc_completed != 0);
+	desc_completed = 0;
+	caam_jr_free(jrdev);
+	return desc_status;
+}
+
+/*
+ * instantiate_rng - builds and executes a descriptor on JR0,
+ *		     which initializes the RNG block.
+ * @state_handle_mask - bitmask containing the instantiation status
+ *			for the RNG4 state handles which exist in
+ *			the RNG4 block: 1 if it's been instantiated
+ *			by an external entry, 0 otherwise.
+ * @gen_sk  - generate data to be loaded into the JDKEK, TDKEK and TDSK;
+ *	      Caution: this can be done only once; if the keys need to be
+ *	      regenerated, a POR is required
+ *
+ * Return: - 0 if no error occurred
+ *	   - -ENOMEM if there isn't enough memory to allocate the descriptor
+ *	   - -ENODEV if DECO0 couldn't be acquired
+ *	   - -EAGAIN if an error occurred when executing the descriptor
+ *	      f.i. there was a RNG hardware error due to not "good enough"
+ *	      entropy being acquired.
+ */
+static int instantiate_rng(int state_handle_mask, int gen_sk)
+{
+	u32 *desc;
+	int sh_idx, ret = 0;
+
+	desc = kmalloc(CAAM_CMD_SZ * 7, GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+
+	for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+		/*
+		 * If the corresponding bit is set, this state handle
+		 * was initialized by somebody else, so it's left alone.
+		 */
+		if ((1 << sh_idx) & state_handle_mask)
+			continue;
+
+		/* Create the descriptor for instantiating RNG State Handle */
+		build_instantiation_desc(desc, sh_idx, gen_sk);
+
+		/* Try to run it through JR */
+		ret = run_descriptor_jr(desc, sh_idx);
+		if (ret)
+			pr_debug("Failed to run desc  RNG4 SH%d status (0x%x)\n",
+				 sh_idx, ret);
+		/* Clear the contents before recreating the descriptor */
+		memset(desc, 0x00, CAAM_CMD_SZ * 7);
+	}
+
+	kfree(desc);
+
+	return ret;
+}
+
+/*
+ * deinstantiate_rng - builds and executes a descriptor on JR0,
+ *		       which deinitializes the RNG block.
+ * @state_handle_mask - bitmask containing the instantiation status
+ *			for the RNG4 state handles which exist in
+ *			the RNG4 block: 1 if it's been instantiated
+ *
+ * Return: - 0 if no error occurred
+ *	   - -ENOMEM if there isn't enough memory to allocate the descriptor
+ *	   - -ENODEV if DECO0 couldn't be acquired
+ *	   - -EAGAIN if an error occurred when executing the descriptor
+ */
+int deinstantiate_rng(int state_handle_mask)
+{
+	u32 *desc;
+	int sh_idx, ret = 0;
+
+	desc = kmalloc(CAAM_CMD_SZ * 3, GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+
+	for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+		/*
+		 * If the corresponding bit is set, then it means the state
+		 * handle was initialized by us, and thus it needs to be
+		 * deinitialized as well
+		 */
+		if ((1 << sh_idx) & state_handle_mask) {
+			/*
+			 * Create the descriptor for deinstantating this state
+			 * handle
+			 */
+			build_deinstantiation_desc(desc, sh_idx);
+
+			/* Try to run it through JR */
+			ret = run_descriptor_jr(desc, sh_idx);
+			if (ret)
+				pr_debug("Failed to run desc to deinstantiate RNG4 SH%d\n",
+					 sh_idx);
+		}
+	}
+
+	kfree(desc);
+
+	return ret;
+}
+
+/*
+ * kick_trng - sets the various parameters for enabling the initialization
+ *	       of the RNG4 block in CAAM
+ * @ctrldev - pointer to the device
+ * @ent_delay - Defines the length (in system clocks) of each entropy sample.
+ */
+static void kick_trng(struct device *ctrldev, int ent_delay)
+{
+	struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
+	struct caam_ctrl __iomem *ctrl;
+	struct rng4tst __iomem *r4tst;
+	u32 val;
+
+	ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
+	r4tst = &ctrl->r4tst[0];
+
+	/* put RNG4 into program mode */
+	clrsetbits_32(&r4tst->rtmctl, 0, RTMCTL_PRGM);
+
+	/*
+	 * Performance-wise, it does not make sense to
+	 * set the delay to a value that is lower
+	 * than the last one that worked (i.e. the state handles
+	 * were instantiated properly. Thus, instead of wasting
+	 * time trying to set the values controlling the sample
+	 * frequency, the function simply returns.
+	 */
+	val = (rd_reg32(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK)
+	      >> RTSDCTL_ENT_DLY_SHIFT;
+	if (ent_delay <= val) {
+		/* put RNG4 into run mode */
+		clrsetbits_32(&r4tst->rtmctl, RTMCTL_PRGM, 0);
+		return;
+	}
+
+	val = rd_reg32(&r4tst->rtsdctl);
+	val = (val & ~RTSDCTL_ENT_DLY_MASK) |
+	      (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
+	wr_reg32(&r4tst->rtsdctl, val);
+	/* min. freq. count, equal to 1/4 of the entropy sample length */
+	wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2);
+	/* max. freq. count, equal to 16 times the entropy sample length */
+	wr_reg32(&r4tst->rtfrqmax, ent_delay << 4);
+	/* read the control register */
+	val = rd_reg32(&r4tst->rtmctl);
+	/*
+	 * select raw sampling in both entropy shifter
+	 * and statistical checker
+	 */
+	clrsetbits_32(&val, 0, RTMCTL_SAMP_MODE_RAW_ES_SC);
+	/* put RNG4 into run mode */
+	clrsetbits_32(&val, RTMCTL_PRGM, 0);
+	/* write back the control register */
+	wr_reg32(&r4tst->rtmctl, val);
+}
+
+/*
+ * inst_rng_imx - RNG instantiation function for i.MX6/7/8m platforms
+ * @pdev - pointer to the device
+ */
+int inst_rng_imx(struct platform_device *pdev)
+{
+	struct device *ctrldev, *dev;
+	struct caam_drv_private *ctrlpriv;
+	struct caam_ctrl __iomem *ctrl;
+	int ret = 0, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
+	u32 cha_vid_ls;
+
+	dev = &pdev->dev;
+	ctrldev = pdev->dev.parent;
+	ctrlpriv = dev_get_drvdata(ctrldev);
+	ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
+
+	cha_vid_ls = rd_reg32(&ctrl->perfmon.cha_id_ls);
+
+	/*
+	 * If SEC has RNG version >= 4 and RNG state handle has not been
+	 * already instantiated, do RNG instantiation
+	 * In case of DPAA 2.x, RNG is managed by MC firmware.
+	 */
+	if (!caam_dpaa2 &&
+		(cha_vid_ls & CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT >= 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_IFMASK;
+		do {
+			int inst_handles =
+				rd_reg32(&ctrl->r4tst[0].rdsta) &
+								RDSTA_IFMASK;
+			/*
+			 * 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 (!(ctrlpriv->rng4_sh_init || inst_handles)) {
+				dev_info(dev,
+					 "Entropy delay = %u\n",
+					 ent_delay);
+				kick_trng(ctrldev, ent_delay);
+				ent_delay += ENT_DELAY_STEP;
+			}
+			/*
+			 * 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 sucessful initialization of
+			 * the RNG.
+			 */
+			ret = instantiate_rng(inst_handles, gen_sk);
+			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 init'ed by this module as the complement of the
+		 * already initialized ones
+		 */
+		ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_IFMASK;
+		/* Enable RDB bit so that RNG works faster */
+		clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
+	}
+	return ret;
+}
+
+/*
+ * deinst_rng - RNG de-instantiation function
+ * @pdev - pointer to the device
+ */
+int deinst_rng(struct platform_device *pdev)
+{
+	struct device *ctrldev, *dev;
+	struct caam_drv_private *ctrlpriv;
+	int ret = 0;
+
+	dev = &pdev->dev;
+	ctrldev = pdev->dev.parent;
+	ctrlpriv = dev_get_drvdata(ctrldev);
+
+	ret = deinstantiate_rng(ctrlpriv->rng4_sh_init);
+	return ret;
+}
diff --git a/drivers/crypto/caam/inst_rng.h b/drivers/crypto/caam/inst_rng.h
new file mode 100644
index 000000000000..e0477262fe2a
--- /dev/null
+++ b/drivers/crypto/caam/inst_rng.h
@@ -0,0 +1,18 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * CAAM Private/internal definitions between modules
+ *
+ * Copyright 2017-2018 NXP
+ */
+
+#ifndef INST_RNG_H
+#define INST_RNG_H
+
+#include <linux/platform_device.h>
+
+#define ENT_DELAY_STEP	(400)
+int inst_rng_imx(struct platform_device *pdev);
+
+int deinst_rng(struct platform_device *pdev);
+
+#endif /* INST_RNG_H */
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index ac5ae14be233..a94860bc21a1 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -15,6 +15,7 @@ 
 #include "jr.h"
 #include "desc.h"
 #include "intern.h"
+#include "inst_rng.h"
 
 struct jr_driver_data {
 	/* List of Physical JobR's with the Driver */
@@ -101,6 +102,12 @@  static int caam_jr_remove(struct platform_device *pdev)
 	jrdev = &pdev->dev;
 	jrpriv = dev_get_drvdata(jrdev);
 
+	/*
+	 * Deinstantiate RNG by first JR
+	 */
+	if (jrpriv->ridx == 0)
+		deinst_rng(pdev);
+
 	/*
 	 * Return EBUSY if job ring already allocated.
 	 */
@@ -542,7 +549,13 @@  static int caam_jr_probe(struct platform_device *pdev)
 
 	atomic_set(&jrpriv->tfm_count, 0);
 
-	return 0;
+	/*
+	 * Instantiate RNG by JR rather than DECO
+	 */
+	if (jrpriv->ridx == 0)
+		error = inst_rng_imx(pdev);
+
+	return error;
 }
 
 static const struct of_device_id caam_jr_match[] = {