LKML Archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] Add power management support in CAAM driver
@ 2023-07-12  6:07 meenakshi.aggarwal
  2023-07-12  6:07 ` [PATCH 1/2] crypto: caam - Change structure type representing DECO MID meenakshi.aggarwal
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: meenakshi.aggarwal @ 2023-07-12  6:07 UTC (permalink / raw
  To: horia.geanta, V.sethi, pankaj.gupta, gaurav.jain, herbert, davem,
	linux-crypto, linux-kernel
  Cc: Meenakshi Aggarwal

From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

This patch set add support of Power Management in CAAM driver

We are saving the state of the CAAM:
 - JRs MID
 - Address of input and output rings
in suspend function and getting same state in resume function
on platforms where power of CAAM is turned off.

Franck LENORMAND (1):
  crypto: caam - Change structure type representing DECO MID

Horia Geanta (1):
  crypto: caam - add power management support

 drivers/crypto/caam/ctrl.c   | 114 ++++++++++++++++++++
 drivers/crypto/caam/intern.h |  33 +++++-
 drivers/crypto/caam/jr.c     | 199 +++++++++++++++++++++++++++++++----
 drivers/crypto/caam/regs.h   |   9 +-
 4 files changed, 328 insertions(+), 27 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/2] crypto: caam - Change structure type representing DECO MID
  2023-07-12  6:07 [PATCH 0/2] Add power management support in CAAM driver meenakshi.aggarwal
@ 2023-07-12  6:07 ` meenakshi.aggarwal
  2023-07-17  5:42   ` Gaurav Jain
  2023-07-12  6:07 ` [PATCH 2/2] crypto: caam - add power management support meenakshi.aggarwal
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 11+ messages in thread
From: meenakshi.aggarwal @ 2023-07-12  6:07 UTC (permalink / raw
  To: horia.geanta, V.sethi, pankaj.gupta, gaurav.jain, herbert, davem,
	linux-crypto, linux-kernel
  Cc: Franck LENORMAND, Meenakshi Aggarwal

From: Franck LENORMAND <franck.lenormand@nxp.com>

The structure partid is not suitable to represent the DECO MID register.

This patch replace partid by masterid which is more appropriate.

Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
---
 drivers/crypto/caam/regs.h | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 189e74c21f0c..0f87bd365582 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -459,12 +459,6 @@ struct masterid {
 	u32 liodn_ls;	/* LIODN for non-sequence and seq access */
 };
 
-/* Partition ID for DMA configuration */
-struct partid {
-	u32 rsvd1;
-	u32 pidr;	/* partition ID, DECO */
-};
-
 /* RNGB test mode (replicated twice in some configurations) */
 /* Padded out to 0x100 */
 struct rngtst {
@@ -590,7 +584,7 @@ struct caam_ctrl {
 	u32 deco_rsr;			/* DECORSR - Deco Request Source */
 	u32 rsvd11;
 	u32 deco_rq;			/* DECORR - DECO Request */
-	struct partid deco_mid[5];	/* DECOxLIODNR - 1 per DECO */
+	struct masterid deco_mid[5];	/* DECOxLIODNR - 1 per DECO */
 	u32 rsvd5[22];
 
 	/* DECO Availability/Reset Section			120-3ff */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/2] crypto: caam - add power management support
  2023-07-12  6:07 [PATCH 0/2] Add power management support in CAAM driver meenakshi.aggarwal
  2023-07-12  6:07 ` [PATCH 1/2] crypto: caam - Change structure type representing DECO MID meenakshi.aggarwal
@ 2023-07-12  6:07 ` meenakshi.aggarwal
  2023-07-17  5:42   ` Gaurav Jain
  2023-07-22  1:42   ` Herbert Xu
  2023-07-17  5:41 ` [PATCH 0/2] Add power management support in CAAM driver Gaurav Jain
  2023-07-24  6:52 ` [PATCH v2 " meenakshi.aggarwal
  3 siblings, 2 replies; 11+ messages in thread
From: meenakshi.aggarwal @ 2023-07-12  6:07 UTC (permalink / raw
  To: horia.geanta, V.sethi, pankaj.gupta, gaurav.jain, herbert, davem,
	linux-crypto, linux-kernel
  Cc: Victoria Milhoan, Dan Douglass, Vipul Kumar, Franck LENORMAND,
	Meenakshi Aggarwal

From: Horia Geanta <horia.geanta@nxp.com>

Add support for suspend and resume operation for PM in CAAM driver.

When the CAAM goes in suspend, the hardware is considered to do nothing.

On some platforms, the power of the CAAM is not turned off so it keeps
its configuration.
On other platforms, it doesn't so it is necessary to save the state of
the CAAM:
 - JRs MID
 - Address of input and output rings

Signed-off-by: Horia Geanta <horia.geanta@nxp.com>
Signed-off-by: Victoria Milhoan <vicki.milhoan@freescale.com>
Signed-off-by: Dan Douglass <dan.douglass@nxp.com>
Signed-off-by: Vipul Kumar <vipul_kumar@mentor.com>
Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
---
 drivers/crypto/caam/ctrl.c   | 114 ++++++++++++++++++++
 drivers/crypto/caam/intern.h |  33 +++++-
 drivers/crypto/caam/jr.c     | 199 +++++++++++++++++++++++++++++++----
 drivers/crypto/caam/regs.h   |   3 +-
 4 files changed, 328 insertions(+), 21 deletions(-)

diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index ff9ddbbca377..64b6cd09d8a8 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -740,6 +740,113 @@ static int caam_ctrl_rng_init(struct device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+
+/* Indicate if the internal state of the CAAM is lost during PM */
+static int caam_off_during_pm(void)
+{
+	bool not_off_during_pm = of_machine_is_compatible("fsl,imx6q") ||
+				 of_machine_is_compatible("fsl,imx6qp") ||
+				 of_machine_is_compatible("fsl,imx6dl");
+
+	return not_off_during_pm ? 0 : 1;
+}
+
+static void caam_state_save(struct device *dev)
+{
+	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
+	struct caam_ctl_state *state = &ctrlpriv->state;
+	struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl;
+	u32 deco_inst, jr_inst;
+	int i;
+
+	state->mcr = rd_reg32(&ctrl->mcr);
+	state->scfgr = rd_reg32(&ctrl->scfgr);
+
+	deco_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) &
+		     CHA_ID_MS_DECO_MASK) >> CHA_ID_MS_DECO_SHIFT;
+	for (i = 0; i < deco_inst; i++) {
+		state->deco_mid[i].liodn_ms =
+			rd_reg32(&ctrl->deco_mid[i].liodn_ms);
+		state->deco_mid[i].liodn_ls =
+			rd_reg32(&ctrl->deco_mid[i].liodn_ls);
+	}
+
+	jr_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) &
+		   CHA_ID_MS_JR_MASK) >> CHA_ID_MS_JR_SHIFT;
+	for (i = 0; i < jr_inst; i++) {
+		state->jr_mid[i].liodn_ms =
+			rd_reg32(&ctrl->jr_mid[i].liodn_ms);
+		state->jr_mid[i].liodn_ls =
+			rd_reg32(&ctrl->jr_mid[i].liodn_ls);
+	}
+}
+
+static void caam_state_restore(const struct device *dev)
+{
+	const struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
+	const struct caam_ctl_state *state = &ctrlpriv->state;
+	struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl;
+	u32 deco_inst, jr_inst;
+	int i;
+
+	wr_reg32(&ctrl->mcr, state->mcr);
+	wr_reg32(&ctrl->scfgr, state->scfgr);
+
+	deco_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) &
+		     CHA_ID_MS_DECO_MASK) >> CHA_ID_MS_DECO_SHIFT;
+	for (i = 0; i < deco_inst; i++) {
+		wr_reg32(&ctrl->deco_mid[i].liodn_ms,
+			 state->deco_mid[i].liodn_ms);
+		wr_reg32(&ctrl->deco_mid[i].liodn_ls,
+			 state->deco_mid[i].liodn_ls);
+	}
+
+	jr_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) &
+		   CHA_ID_MS_JR_MASK) >> CHA_ID_MS_JR_SHIFT;
+	for (i = 0; i < jr_inst; i++) {
+		wr_reg32(&ctrl->jr_mid[i].liodn_ms,
+			 state->jr_mid[i].liodn_ms);
+		wr_reg32(&ctrl->jr_mid[i].liodn_ls,
+			 state->jr_mid[i].liodn_ls);
+	}
+
+	if (ctrlpriv->virt_en == 1)
+		clrsetbits_32(&ctrl->jrstart, 0, JRSTART_JR0_START |
+			      JRSTART_JR1_START | JRSTART_JR2_START |
+			      JRSTART_JR3_START);
+}
+
+static int caam_ctrl_suspend(struct device *dev)
+{
+	const struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
+
+	if (ctrlpriv->caam_off_during_pm && !ctrlpriv->optee_en)
+		caam_state_save(dev);
+
+	return 0;
+}
+
+static int caam_ctrl_resume(struct device *dev)
+{
+	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (ctrlpriv->caam_off_during_pm && !ctrlpriv->optee_en) {
+		caam_state_restore(dev);
+
+		/* HW and rng will be reset so deinstantiation can be removed */
+		devm_remove_action(dev, devm_deinstantiate_rng, dev);
+		ret = caam_ctrl_rng_init(dev);
+	}
+
+	return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(caam_ctrl_pm_ops, caam_ctrl_suspend, caam_ctrl_resume);
+
+#endif /* CONFIG_PM_SLEEP */
+
 /* Probe routine for CAAM top (controller) level */
 static int caam_probe(struct platform_device *pdev)
 {
@@ -771,6 +878,10 @@ static int caam_probe(struct platform_device *pdev)
 
 	caam_imx = (bool)imx_soc_match;
 
+#ifdef CONFIG_PM_SLEEP
+	ctrlpriv->caam_off_during_pm = caam_imx && caam_off_during_pm();
+#endif
+
 	if (imx_soc_match) {
 		/*
 		 * Until Layerscape and i.MX OP-TEE get in sync,
@@ -1033,6 +1144,9 @@ static struct platform_driver caam_driver = {
 	.driver = {
 		.name = "caam",
 		.of_match_table = caam_match,
+#ifdef CONFIG_PM_SLEEP
+		.pm = &caam_ctrl_pm_ops,
+#endif
 	},
 	.probe       = caam_probe,
 };
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index b4f7bf77f487..fcf0a080b5d6 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -4,7 +4,7 @@
  * Private/internal definitions between modules
  *
  * Copyright 2008-2011 Freescale Semiconductor, Inc.
- * Copyright 2019 NXP
+ * Copyright 2019, 2023 NXP
  */
 
 #ifndef INTERN_H
@@ -47,6 +47,18 @@ struct caam_jrentry_info {
 	u32 desc_size;	/* Stored size for postprocessing, header derived */
 };
 
+#ifdef CONFIG_PM_SLEEP
+struct caam_jr_state {
+	dma_addr_t inpbusaddr;
+	dma_addr_t outbusaddr;
+};
+#endif
+
+struct caam_jr_dequeue_params {
+	struct device *dev;
+	int enable_itr;
+};
+
 /* Private sub-storage for a single JobR */
 struct caam_drv_private_jr {
 	struct list_head	list_node;	/* Job Ring device list */
@@ -54,6 +66,7 @@ struct caam_drv_private_jr {
 	int ridx;
 	struct caam_job_ring __iomem *rregs;	/* JobR's register space */
 	struct tasklet_struct irqtask;
+	struct caam_jr_dequeue_params tasklet_params;
 	int irq;			/* One per queue */
 	bool hwrng;
 
@@ -71,7 +84,20 @@ struct caam_drv_private_jr {
 	int tail;			/* entinfo (s/w ring) tail index */
 	void *outring;			/* Base of output ring, DMA-safe */
 	struct crypto_engine *engine;
+
+#ifdef CONFIG_PM_SLEEP
+	struct caam_jr_state state;	/* State of the JR during PM */
+#endif
+};
+
+#ifdef CONFIG_PM_SLEEP
+struct caam_ctl_state {
+	struct masterid deco_mid[16];
+	struct masterid jr_mid[4];
+	u32 mcr;
+	u32 scfgr;
 };
+#endif
 
 /*
  * Driver-private storage for a single CAAM block instance
@@ -116,6 +142,11 @@ struct caam_drv_private {
 	struct dentry *ctl; /* controller dir */
 	struct debugfs_blob_wrapper ctl_kek_wrap, ctl_tkek_wrap, ctl_tdsk_wrap;
 #endif
+
+#ifdef CONFIG_PM_SLEEP
+	int caam_off_during_pm;		/* If the CAAM is reset after suspend */
+	struct caam_ctl_state state;	/* State of the CTL during PM */
+#endif
 };
 
 #ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 96dea5304d22..1801638eb1c8 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -117,6 +117,25 @@ static int caam_jr_flush(struct device *dev)
 	return caam_jr_stop_processing(dev, JRCR_RESET);
 }
 
+#ifdef CONFIG_PM_SLEEP
+/* The resume can be used after a park or a flush if CAAM has not been reset */
+static int caam_jr_restart_processing(struct device *dev)
+{
+	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+	u32 halt_status = rd_reg32(&jrp->rregs->jrintstatus) &
+			  JRINT_ERR_HALT_MASK;
+
+	/* Check that the flush/park is completed */
+	if (halt_status != JRINT_ERR_HALT_COMPLETE)
+		return -1;
+
+	/* Resume processing of jobs */
+	clrsetbits_32(&jrp->rregs->jrintstatus, 0, JRINT_ERR_HALT_COMPLETE);
+
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
 static int caam_reset_hw_jr(struct device *dev)
 {
 	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
@@ -245,7 +264,8 @@ static irqreturn_t caam_jr_interrupt(int irq, void *st_dev)
 static void caam_jr_dequeue(unsigned long devarg)
 {
 	int hw_idx, sw_idx, i, head, tail;
-	struct device *dev = (struct device *)devarg;
+	struct caam_jr_dequeue_params *params = (void *)devarg;
+	struct device *dev = params->dev;
 	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
 	void (*usercall)(struct device *dev, u32 *desc, u32 status, void *arg);
 	u32 *userdesc, userstatus;
@@ -319,8 +339,9 @@ static void caam_jr_dequeue(unsigned long devarg)
 		outring_used--;
 	}
 
-	/* reenable / unmask IRQs */
-	clrsetbits_32(&jrp->rregs->rconfig_lo, JRCFG_IMSK, 0);
+	if (params->enable_itr)
+		/* reenable / unmask IRQs */
+		clrsetbits_32(&jrp->rregs->rconfig_lo, JRCFG_IMSK, 0);
 }
 
 /**
@@ -470,6 +491,29 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
 }
 EXPORT_SYMBOL(caam_jr_enqueue);
 
+static void caam_jr_init_hw(struct device *dev, dma_addr_t inpbusaddr,
+			    dma_addr_t outbusaddr)
+{
+	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+
+	wr_reg64(&jrp->rregs->inpring_base, inpbusaddr);
+	wr_reg64(&jrp->rregs->outring_base, outbusaddr);
+	wr_reg32(&jrp->rregs->inpring_size, JOBR_DEPTH);
+	wr_reg32(&jrp->rregs->outring_size, JOBR_DEPTH);
+
+	/* Select interrupt coalescing parameters */
+	clrsetbits_32(&jrp->rregs->rconfig_lo, 0, JOBR_INTC |
+		      (JOBR_INTC_COUNT_THLD << JRCFG_ICDCT_SHIFT) |
+		      (JOBR_INTC_TIME_THLD << JRCFG_ICTT_SHIFT));
+}
+
+static void caam_jr_reset_index(struct caam_drv_private_jr *jrp)
+{
+	jrp->out_ring_read_index = 0;
+	jrp->head = 0;
+	jrp->tail = 0;
+}
+
 /*
  * Init JobR independent of platform property detection
  */
@@ -506,25 +550,16 @@ static int caam_jr_init(struct device *dev)
 		jrp->entinfo[i].desc_addr_dma = !0;
 
 	/* Setup rings */
-	jrp->out_ring_read_index = 0;
-	jrp->head = 0;
-	jrp->tail = 0;
-
-	wr_reg64(&jrp->rregs->inpring_base, inpbusaddr);
-	wr_reg64(&jrp->rregs->outring_base, outbusaddr);
-	wr_reg32(&jrp->rregs->inpring_size, JOBR_DEPTH);
-	wr_reg32(&jrp->rregs->outring_size, JOBR_DEPTH);
-
+	caam_jr_reset_index(jrp);
 	jrp->inpring_avail = JOBR_DEPTH;
+	caam_jr_init_hw(dev, inpbusaddr, outbusaddr);
 
 	spin_lock_init(&jrp->inplock);
 
-	/* Select interrupt coalescing parameters */
-	clrsetbits_32(&jrp->rregs->rconfig_lo, 0, JOBR_INTC |
-		      (JOBR_INTC_COUNT_THLD << JRCFG_ICDCT_SHIFT) |
-		      (JOBR_INTC_TIME_THLD << JRCFG_ICTT_SHIFT));
-
-	tasklet_init(&jrp->irqtask, caam_jr_dequeue, (unsigned long)dev);
+	jrp->tasklet_params.dev = dev;
+	jrp->tasklet_params.enable_itr = 1;
+	tasklet_init(&jrp->irqtask, caam_jr_dequeue,
+		     (unsigned long)&jrp->tasklet_params);
 
 	/* Connect job ring interrupt handler. */
 	error = devm_request_irq(dev, jrp->irq, caam_jr_interrupt, IRQF_SHARED,
@@ -635,11 +670,136 @@ static int caam_jr_probe(struct platform_device *pdev)
 
 	atomic_set(&jrpriv->tfm_count, 0);
 
+	device_init_wakeup(&pdev->dev, 1);
+	device_set_wakeup_enable(&pdev->dev, false);
+
 	register_algs(jrpriv, jrdev->parent);
 
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static void caam_jr_get_hw_state(struct device *dev)
+{
+	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+
+	jrp->state.inpbusaddr = rd_reg64(&jrp->rregs->inpring_base);
+	jrp->state.outbusaddr = rd_reg64(&jrp->rregs->outring_base);
+}
+
+static int caam_jr_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct caam_drv_private_jr *jrpriv = platform_get_drvdata(pdev);
+	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev->parent);
+	struct caam_jr_dequeue_params suspend_params = {
+		.dev = dev,
+		.enable_itr = 0,
+	};
+
+	/* Remove the node from Physical JobR list maintained by driver */
+	spin_lock(&driver_data.jr_alloc_lock);
+	list_del(&jrpriv->list_node);
+	spin_unlock(&driver_data.jr_alloc_lock);
+
+	if (jrpriv->hwrng)
+		caam_rng_exit(dev->parent);
+
+	if (ctrlpriv->caam_off_during_pm) {
+		int err;
+
+		tasklet_disable(&jrpriv->irqtask);
+
+		/* mask itr to call flush */
+		clrsetbits_32(&jrpriv->rregs->rconfig_lo, 0, JRCFG_IMSK);
+
+		/* Invalid job in process */
+		err = caam_jr_flush(dev);
+		if (err) {
+			dev_err(dev, "Failed to flush\n");
+			return err;
+		}
+
+		/* Dequeing jobs flushed */
+		caam_jr_dequeue((unsigned long)&suspend_params);
+
+		/* Save state */
+		caam_jr_get_hw_state(dev);
+	} else if (device_may_wakeup(&pdev->dev)) {
+		enable_irq_wake(jrpriv->irq);
+	}
+
+	return 0;
+}
+
+static int caam_jr_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct caam_drv_private_jr *jrpriv = platform_get_drvdata(pdev);
+	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev->parent);
+
+	if (ctrlpriv->caam_off_during_pm) {
+		u64 inp_addr;
+		int err;
+
+		/*
+		 * Check if the CAAM has been resetted checking the address of
+		 * the input ring
+		 */
+		inp_addr = rd_reg64(&jrpriv->rregs->inpring_base);
+		if (inp_addr != 0) {
+			/* JR still has some configuration */
+			if (inp_addr == jrpriv->state.inpbusaddr) {
+				/* JR has not been resetted */
+				err = caam_jr_restart_processing(dev);
+				if (err) {
+					dev_err(dev,
+						"Restart processing failed\n");
+					return err;
+				}
+
+				tasklet_enable(&jrpriv->irqtask);
+
+				clrsetbits_32(&jrpriv->rregs->rconfig_lo,
+					      JRCFG_IMSK, 0);
+
+				goto add_jr;
+			} else if (ctrlpriv->optee_en) {
+				/* JR has been used by OPTEE, reset it */
+				err = caam_reset_hw_jr(dev);
+				if (err) {
+					dev_err(dev, "Failed to reset JR\n");
+					return err;
+				}
+			} else {
+				/* No explanation, return error */
+				return -EIO;
+			}
+		}
+
+		caam_jr_reset_index(jrpriv);
+		caam_jr_init_hw(dev, jrpriv->state.inpbusaddr,
+				jrpriv->state.outbusaddr);
+
+		tasklet_enable(&jrpriv->irqtask);
+	} else if (device_may_wakeup(&pdev->dev)) {
+		disable_irq_wake(jrpriv->irq);
+	}
+
+add_jr:
+	spin_lock(&driver_data.jr_alloc_lock);
+	list_add_tail(&jrpriv->list_node, &driver_data.jr_list);
+	spin_unlock(&driver_data.jr_alloc_lock);
+
+	if (jrpriv->hwrng)
+		jrpriv->hwrng = !caam_rng_init(dev->parent);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(caam_jr_pm_ops, caam_jr_suspend, caam_jr_resume);
+#endif /* CONFIG_PM_SLEEP */
+
 static const struct of_device_id caam_jr_match[] = {
 	{
 		.compatible = "fsl,sec-v4.0-job-ring",
@@ -655,6 +815,9 @@ static struct platform_driver caam_jr_driver = {
 	.driver = {
 		.name = "caam_jr",
 		.of_match_table = caam_jr_match,
+#ifdef CONFIG_PM_SLEEP
+		.pm = &caam_jr_pm_ops,
+#endif
 	},
 	.probe       = caam_jr_probe,
 	.remove      = caam_jr_remove,
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 0f87bd365582..873df9de9890 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -584,8 +584,7 @@ struct caam_ctrl {
 	u32 deco_rsr;			/* DECORSR - Deco Request Source */
 	u32 rsvd11;
 	u32 deco_rq;			/* DECORR - DECO Request */
-	struct masterid deco_mid[5];	/* DECOxLIODNR - 1 per DECO */
-	u32 rsvd5[22];
+	struct masterid deco_mid[16];	/* DECOxLIODNR - 1 per DECO */
 
 	/* DECO Availability/Reset Section			120-3ff */
 	u32 deco_avail;		/* DAR - DECO availability */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* RE: [PATCH 0/2] Add power management support in CAAM driver
  2023-07-12  6:07 [PATCH 0/2] Add power management support in CAAM driver meenakshi.aggarwal
  2023-07-12  6:07 ` [PATCH 1/2] crypto: caam - Change structure type representing DECO MID meenakshi.aggarwal
  2023-07-12  6:07 ` [PATCH 2/2] crypto: caam - add power management support meenakshi.aggarwal
@ 2023-07-17  5:41 ` Gaurav Jain
  2023-07-24  6:52 ` [PATCH v2 " meenakshi.aggarwal
  3 siblings, 0 replies; 11+ messages in thread
From: Gaurav Jain @ 2023-07-17  5:41 UTC (permalink / raw
  To: Meenakshi Aggarwal, Horia Geanta, Varun Sethi, Pankaj Gupta,
	herbert@gondor.apana.org.au, davem@davemloft.net,
	linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org

Reviewed-by: Gaurav Jain <gaurav.jain@nxp.com>

> -----Original Message-----
> From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> Sent: Wednesday, July 12, 2023 11:37 AM
> To: Horia Geanta <horia.geanta@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
> Pankaj Gupta <pankaj.gupta@nxp.com>; Gaurav Jain <gaurav.jain@nxp.com>;
> herbert@gondor.apana.org.au; davem@davemloft.net; linux-
> crypto@vger.kernel.org; linux-kernel@vger.kernel.org
> Cc: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> Subject: [PATCH 0/2] Add power management support in CAAM driver
> 
> From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> 
> This patch set add support of Power Management in CAAM driver
> 
> We are saving the state of the CAAM:
>  - JRs MID
>  - Address of input and output rings
> in suspend function and getting same state in resume function on platforms
> where power of CAAM is turned off.
> 
> Franck LENORMAND (1):
>   crypto: caam - Change structure type representing DECO MID
> 
> Horia Geanta (1):
>   crypto: caam - add power management support
> 
>  drivers/crypto/caam/ctrl.c   | 114 ++++++++++++++++++++
>  drivers/crypto/caam/intern.h |  33 +++++-
>  drivers/crypto/caam/jr.c     | 199 +++++++++++++++++++++++++++++++----
>  drivers/crypto/caam/regs.h   |   9 +-
>  4 files changed, 328 insertions(+), 27 deletions(-)
> 
> --
> 2.25.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH 1/2] crypto: caam - Change structure type representing DECO MID
  2023-07-12  6:07 ` [PATCH 1/2] crypto: caam - Change structure type representing DECO MID meenakshi.aggarwal
@ 2023-07-17  5:42   ` Gaurav Jain
  0 siblings, 0 replies; 11+ messages in thread
From: Gaurav Jain @ 2023-07-17  5:42 UTC (permalink / raw
  To: Meenakshi Aggarwal, Horia Geanta, Varun Sethi, Pankaj Gupta,
	herbert@gondor.apana.org.au, davem@davemloft.net,
	linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org
  Cc: Franck Lenormand

Reviewed-by: Gaurav Jain <gaurav.jain@nxp.com>

> -----Original Message-----
> From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> Sent: Wednesday, July 12, 2023 11:37 AM
> To: Horia Geanta <horia.geanta@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
> Pankaj Gupta <pankaj.gupta@nxp.com>; Gaurav Jain <gaurav.jain@nxp.com>;
> herbert@gondor.apana.org.au; davem@davemloft.net; linux-
> crypto@vger.kernel.org; linux-kernel@vger.kernel.org
> Cc: Franck Lenormand <franck.lenormand@nxp.com>; Meenakshi Aggarwal
> <meenakshi.aggarwal@nxp.com>
> Subject: [PATCH 1/2] crypto: caam - Change structure type representing DECO
> MID
> 
> From: Franck LENORMAND <franck.lenormand@nxp.com>
> 
> The structure partid is not suitable to represent the DECO MID register.
> 
> This patch replace partid by masterid which is more appropriate.
> 
> Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
> Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
> Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> ---
>  drivers/crypto/caam/regs.h | 8 +-------
>  1 file changed, 1 insertion(+), 7 deletions(-)
> 
> diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index
> 189e74c21f0c..0f87bd365582 100644
> --- a/drivers/crypto/caam/regs.h
> +++ b/drivers/crypto/caam/regs.h
> @@ -459,12 +459,6 @@ struct masterid {
>  	u32 liodn_ls;	/* LIODN for non-sequence and seq access */
>  };
> 
> -/* Partition ID for DMA configuration */ -struct partid {
> -	u32 rsvd1;
> -	u32 pidr;	/* partition ID, DECO */
> -};
> -
>  /* RNGB test mode (replicated twice in some configurations) */
>  /* Padded out to 0x100 */
>  struct rngtst {
> @@ -590,7 +584,7 @@ struct caam_ctrl {
>  	u32 deco_rsr;			/* DECORSR - Deco Request Source */
>  	u32 rsvd11;
>  	u32 deco_rq;			/* DECORR - DECO Request */
> -	struct partid deco_mid[5];	/* DECOxLIODNR - 1 per DECO */
> +	struct masterid deco_mid[5];	/* DECOxLIODNR - 1 per DECO */
>  	u32 rsvd5[22];
> 
>  	/* DECO Availability/Reset Section			120-3ff */
> --
> 2.25.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH 2/2] crypto: caam - add power management support
  2023-07-12  6:07 ` [PATCH 2/2] crypto: caam - add power management support meenakshi.aggarwal
@ 2023-07-17  5:42   ` Gaurav Jain
  2023-07-22  1:42   ` Herbert Xu
  1 sibling, 0 replies; 11+ messages in thread
From: Gaurav Jain @ 2023-07-17  5:42 UTC (permalink / raw
  To: Meenakshi Aggarwal, Horia Geanta, Varun Sethi, Pankaj Gupta,
	herbert@gondor.apana.org.au, davem@davemloft.net,
	linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org
  Cc: Victoria Milhoan, Dan Douglass, Vipul Kumar, Franck Lenormand

Reviewed-by: Gaurav Jain <gaurav.jain@nxp.com>

> -----Original Message-----
> From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> Sent: Wednesday, July 12, 2023 11:37 AM
> To: Horia Geanta <horia.geanta@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
> Pankaj Gupta <pankaj.gupta@nxp.com>; Gaurav Jain <gaurav.jain@nxp.com>;
> herbert@gondor.apana.org.au; davem@davemloft.net; linux-
> crypto@vger.kernel.org; linux-kernel@vger.kernel.org
> Cc: Victoria Milhoan <vicki.milhoan@freescale.com>; Dan Douglass
> <dan.douglass@nxp.com>; Vipul Kumar <vipul_kumar@mentor.com>; Franck
> Lenormand <franck.lenormand@nxp.com>; Meenakshi Aggarwal
> <meenakshi.aggarwal@nxp.com>
> Subject: [PATCH 2/2] crypto: caam - add power management support
> 
> From: Horia Geanta <horia.geanta@nxp.com>
> 
> Add support for suspend and resume operation for PM in CAAM driver.
> 
> When the CAAM goes in suspend, the hardware is considered to do nothing.
> 
> On some platforms, the power of the CAAM is not turned off so it keeps its
> configuration.
> On other platforms, it doesn't so it is necessary to save the state of the CAAM:
>  - JRs MID
>  - Address of input and output rings
> 
> Signed-off-by: Horia Geanta <horia.geanta@nxp.com>
> Signed-off-by: Victoria Milhoan <vicki.milhoan@freescale.com>
> Signed-off-by: Dan Douglass <dan.douglass@nxp.com>
> Signed-off-by: Vipul Kumar <vipul_kumar@mentor.com>
> Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
> Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> ---
>  drivers/crypto/caam/ctrl.c   | 114 ++++++++++++++++++++
>  drivers/crypto/caam/intern.h |  33 +++++-
>  drivers/crypto/caam/jr.c     | 199 +++++++++++++++++++++++++++++++----
>  drivers/crypto/caam/regs.h   |   3 +-
>  4 files changed, 328 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index
> ff9ddbbca377..64b6cd09d8a8 100644
> --- a/drivers/crypto/caam/ctrl.c
> +++ b/drivers/crypto/caam/ctrl.c
> @@ -740,6 +740,113 @@ static int caam_ctrl_rng_init(struct device *dev)
>  	return 0;
>  }
> 
> +#ifdef CONFIG_PM_SLEEP
> +
> +/* Indicate if the internal state of the CAAM is lost during PM */
> +static int caam_off_during_pm(void) {
> +	bool not_off_during_pm = of_machine_is_compatible("fsl,imx6q") ||
> +				 of_machine_is_compatible("fsl,imx6qp") ||
> +				 of_machine_is_compatible("fsl,imx6dl");
> +
> +	return not_off_during_pm ? 0 : 1;
> +}
> +
> +static void caam_state_save(struct device *dev) {
> +	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
> +	struct caam_ctl_state *state = &ctrlpriv->state;
> +	struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl;
> +	u32 deco_inst, jr_inst;
> +	int i;
> +
> +	state->mcr = rd_reg32(&ctrl->mcr);
> +	state->scfgr = rd_reg32(&ctrl->scfgr);
> +
> +	deco_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) &
> +		     CHA_ID_MS_DECO_MASK) >> CHA_ID_MS_DECO_SHIFT;
> +	for (i = 0; i < deco_inst; i++) {
> +		state->deco_mid[i].liodn_ms =
> +			rd_reg32(&ctrl->deco_mid[i].liodn_ms);
> +		state->deco_mid[i].liodn_ls =
> +			rd_reg32(&ctrl->deco_mid[i].liodn_ls);
> +	}
> +
> +	jr_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) &
> +		   CHA_ID_MS_JR_MASK) >> CHA_ID_MS_JR_SHIFT;
> +	for (i = 0; i < jr_inst; i++) {
> +		state->jr_mid[i].liodn_ms =
> +			rd_reg32(&ctrl->jr_mid[i].liodn_ms);
> +		state->jr_mid[i].liodn_ls =
> +			rd_reg32(&ctrl->jr_mid[i].liodn_ls);
> +	}
> +}
> +
> +static void caam_state_restore(const struct device *dev) {
> +	const struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
> +	const struct caam_ctl_state *state = &ctrlpriv->state;
> +	struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl;
> +	u32 deco_inst, jr_inst;
> +	int i;
> +
> +	wr_reg32(&ctrl->mcr, state->mcr);
> +	wr_reg32(&ctrl->scfgr, state->scfgr);
> +
> +	deco_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) &
> +		     CHA_ID_MS_DECO_MASK) >> CHA_ID_MS_DECO_SHIFT;
> +	for (i = 0; i < deco_inst; i++) {
> +		wr_reg32(&ctrl->deco_mid[i].liodn_ms,
> +			 state->deco_mid[i].liodn_ms);
> +		wr_reg32(&ctrl->deco_mid[i].liodn_ls,
> +			 state->deco_mid[i].liodn_ls);
> +	}
> +
> +	jr_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) &
> +		   CHA_ID_MS_JR_MASK) >> CHA_ID_MS_JR_SHIFT;
> +	for (i = 0; i < jr_inst; i++) {
> +		wr_reg32(&ctrl->jr_mid[i].liodn_ms,
> +			 state->jr_mid[i].liodn_ms);
> +		wr_reg32(&ctrl->jr_mid[i].liodn_ls,
> +			 state->jr_mid[i].liodn_ls);
> +	}
> +
> +	if (ctrlpriv->virt_en == 1)
> +		clrsetbits_32(&ctrl->jrstart, 0, JRSTART_JR0_START |
> +			      JRSTART_JR1_START | JRSTART_JR2_START |
> +			      JRSTART_JR3_START);
> +}
> +
> +static int caam_ctrl_suspend(struct device *dev) {
> +	const struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
> +
> +	if (ctrlpriv->caam_off_during_pm && !ctrlpriv->optee_en)
> +		caam_state_save(dev);
> +
> +	return 0;
> +}
> +
> +static int caam_ctrl_resume(struct device *dev) {
> +	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	if (ctrlpriv->caam_off_during_pm && !ctrlpriv->optee_en) {
> +		caam_state_restore(dev);
> +
> +		/* HW and rng will be reset so deinstantiation can be removed
> */
> +		devm_remove_action(dev, devm_deinstantiate_rng, dev);
> +		ret = caam_ctrl_rng_init(dev);
> +	}
> +
> +	return ret;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(caam_ctrl_pm_ops, caam_ctrl_suspend,
> +caam_ctrl_resume);
> +
> +#endif /* CONFIG_PM_SLEEP */
> +
>  /* Probe routine for CAAM top (controller) level */  static int caam_probe(struct
> platform_device *pdev)  { @@ -771,6 +878,10 @@ static int caam_probe(struct
> platform_device *pdev)
> 
>  	caam_imx = (bool)imx_soc_match;
> 
> +#ifdef CONFIG_PM_SLEEP
> +	ctrlpriv->caam_off_during_pm = caam_imx && caam_off_during_pm();
> +#endif
> +
>  	if (imx_soc_match) {
>  		/*
>  		 * Until Layerscape and i.MX OP-TEE get in sync, @@ -1033,6
> +1144,9 @@ static struct platform_driver caam_driver = {
>  	.driver = {
>  		.name = "caam",
>  		.of_match_table = caam_match,
> +#ifdef CONFIG_PM_SLEEP
> +		.pm = &caam_ctrl_pm_ops,
> +#endif
>  	},
>  	.probe       = caam_probe,
>  };
> diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h index
> b4f7bf77f487..fcf0a080b5d6 100644
> --- a/drivers/crypto/caam/intern.h
> +++ b/drivers/crypto/caam/intern.h
> @@ -4,7 +4,7 @@
>   * Private/internal definitions between modules
>   *
>   * Copyright 2008-2011 Freescale Semiconductor, Inc.
> - * Copyright 2019 NXP
> + * Copyright 2019, 2023 NXP
>   */
> 
>  #ifndef INTERN_H
> @@ -47,6 +47,18 @@ struct caam_jrentry_info {
>  	u32 desc_size;	/* Stored size for postprocessing, header derived */
>  };
> 
> +#ifdef CONFIG_PM_SLEEP
> +struct caam_jr_state {
> +	dma_addr_t inpbusaddr;
> +	dma_addr_t outbusaddr;
> +};
> +#endif
> +
> +struct caam_jr_dequeue_params {
> +	struct device *dev;
> +	int enable_itr;
> +};
> +
>  /* Private sub-storage for a single JobR */  struct caam_drv_private_jr {
>  	struct list_head	list_node;	/* Job Ring device list */
> @@ -54,6 +66,7 @@ struct caam_drv_private_jr {
>  	int ridx;
>  	struct caam_job_ring __iomem *rregs;	/* JobR's register space */
>  	struct tasklet_struct irqtask;
> +	struct caam_jr_dequeue_params tasklet_params;
>  	int irq;			/* One per queue */
>  	bool hwrng;
> 
> @@ -71,7 +84,20 @@ struct caam_drv_private_jr {
>  	int tail;			/* entinfo (s/w ring) tail index */
>  	void *outring;			/* Base of output ring, DMA-safe */
>  	struct crypto_engine *engine;
> +
> +#ifdef CONFIG_PM_SLEEP
> +	struct caam_jr_state state;	/* State of the JR during PM */
> +#endif
> +};
> +
> +#ifdef CONFIG_PM_SLEEP
> +struct caam_ctl_state {
> +	struct masterid deco_mid[16];
> +	struct masterid jr_mid[4];
> +	u32 mcr;
> +	u32 scfgr;
>  };
> +#endif
> 
>  /*
>   * Driver-private storage for a single CAAM block instance @@ -116,6 +142,11
> @@ struct caam_drv_private {
>  	struct dentry *ctl; /* controller dir */
>  	struct debugfs_blob_wrapper ctl_kek_wrap, ctl_tkek_wrap,
> ctl_tdsk_wrap;  #endif
> +
> +#ifdef CONFIG_PM_SLEEP
> +	int caam_off_during_pm;		/* If the CAAM is reset after
> suspend */
> +	struct caam_ctl_state state;	/* State of the CTL during PM */
> +#endif
>  };
> 
>  #ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API
> diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index
> 96dea5304d22..1801638eb1c8 100644
> --- a/drivers/crypto/caam/jr.c
> +++ b/drivers/crypto/caam/jr.c
> @@ -117,6 +117,25 @@ static int caam_jr_flush(struct device *dev)
>  	return caam_jr_stop_processing(dev, JRCR_RESET);  }
> 
> +#ifdef CONFIG_PM_SLEEP
> +/* The resume can be used after a park or a flush if CAAM has not been
> +reset */ static int caam_jr_restart_processing(struct device *dev) {
> +	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
> +	u32 halt_status = rd_reg32(&jrp->rregs->jrintstatus) &
> +			  JRINT_ERR_HALT_MASK;
> +
> +	/* Check that the flush/park is completed */
> +	if (halt_status != JRINT_ERR_HALT_COMPLETE)
> +		return -1;
> +
> +	/* Resume processing of jobs */
> +	clrsetbits_32(&jrp->rregs->jrintstatus, 0, JRINT_ERR_HALT_COMPLETE);
> +
> +	return 0;
> +}
> +#endif /* CONFIG_PM_SLEEP */
> +
>  static int caam_reset_hw_jr(struct device *dev)  {
>  	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); @@ -245,7
> +264,8 @@ static irqreturn_t caam_jr_interrupt(int irq, void *st_dev)  static void
> caam_jr_dequeue(unsigned long devarg)  {
>  	int hw_idx, sw_idx, i, head, tail;
> -	struct device *dev = (struct device *)devarg;
> +	struct caam_jr_dequeue_params *params = (void *)devarg;
> +	struct device *dev = params->dev;
>  	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
>  	void (*usercall)(struct device *dev, u32 *desc, u32 status, void *arg);
>  	u32 *userdesc, userstatus;
> @@ -319,8 +339,9 @@ static void caam_jr_dequeue(unsigned long devarg)
>  		outring_used--;
>  	}
> 
> -	/* reenable / unmask IRQs */
> -	clrsetbits_32(&jrp->rregs->rconfig_lo, JRCFG_IMSK, 0);
> +	if (params->enable_itr)
> +		/* reenable / unmask IRQs */
> +		clrsetbits_32(&jrp->rregs->rconfig_lo, JRCFG_IMSK, 0);
>  }
> 
>  /**
> @@ -470,6 +491,29 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,  }
> EXPORT_SYMBOL(caam_jr_enqueue);
> 
> +static void caam_jr_init_hw(struct device *dev, dma_addr_t inpbusaddr,
> +			    dma_addr_t outbusaddr)
> +{
> +	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
> +
> +	wr_reg64(&jrp->rregs->inpring_base, inpbusaddr);
> +	wr_reg64(&jrp->rregs->outring_base, outbusaddr);
> +	wr_reg32(&jrp->rregs->inpring_size, JOBR_DEPTH);
> +	wr_reg32(&jrp->rregs->outring_size, JOBR_DEPTH);
> +
> +	/* Select interrupt coalescing parameters */
> +	clrsetbits_32(&jrp->rregs->rconfig_lo, 0, JOBR_INTC |
> +		      (JOBR_INTC_COUNT_THLD << JRCFG_ICDCT_SHIFT) |
> +		      (JOBR_INTC_TIME_THLD << JRCFG_ICTT_SHIFT)); }
> +
> +static void caam_jr_reset_index(struct caam_drv_private_jr *jrp) {
> +	jrp->out_ring_read_index = 0;
> +	jrp->head = 0;
> +	jrp->tail = 0;
> +}
> +
>  /*
>   * Init JobR independent of platform property detection
>   */
> @@ -506,25 +550,16 @@ static int caam_jr_init(struct device *dev)
>  		jrp->entinfo[i].desc_addr_dma = !0;
> 
>  	/* Setup rings */
> -	jrp->out_ring_read_index = 0;
> -	jrp->head = 0;
> -	jrp->tail = 0;
> -
> -	wr_reg64(&jrp->rregs->inpring_base, inpbusaddr);
> -	wr_reg64(&jrp->rregs->outring_base, outbusaddr);
> -	wr_reg32(&jrp->rregs->inpring_size, JOBR_DEPTH);
> -	wr_reg32(&jrp->rregs->outring_size, JOBR_DEPTH);
> -
> +	caam_jr_reset_index(jrp);
>  	jrp->inpring_avail = JOBR_DEPTH;
> +	caam_jr_init_hw(dev, inpbusaddr, outbusaddr);
> 
>  	spin_lock_init(&jrp->inplock);
> 
> -	/* Select interrupt coalescing parameters */
> -	clrsetbits_32(&jrp->rregs->rconfig_lo, 0, JOBR_INTC |
> -		      (JOBR_INTC_COUNT_THLD << JRCFG_ICDCT_SHIFT) |
> -		      (JOBR_INTC_TIME_THLD << JRCFG_ICTT_SHIFT));
> -
> -	tasklet_init(&jrp->irqtask, caam_jr_dequeue, (unsigned long)dev);
> +	jrp->tasklet_params.dev = dev;
> +	jrp->tasklet_params.enable_itr = 1;
> +	tasklet_init(&jrp->irqtask, caam_jr_dequeue,
> +		     (unsigned long)&jrp->tasklet_params);
> 
>  	/* Connect job ring interrupt handler. */
>  	error = devm_request_irq(dev, jrp->irq, caam_jr_interrupt,
> IRQF_SHARED, @@ -635,11 +670,136 @@ static int caam_jr_probe(struct
> platform_device *pdev)
> 
>  	atomic_set(&jrpriv->tfm_count, 0);
> 
> +	device_init_wakeup(&pdev->dev, 1);
> +	device_set_wakeup_enable(&pdev->dev, false);
> +
>  	register_algs(jrpriv, jrdev->parent);
> 
>  	return 0;
>  }
> 
> +#ifdef CONFIG_PM_SLEEP
> +static void caam_jr_get_hw_state(struct device *dev) {
> +	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
> +
> +	jrp->state.inpbusaddr = rd_reg64(&jrp->rregs->inpring_base);
> +	jrp->state.outbusaddr = rd_reg64(&jrp->rregs->outring_base);
> +}
> +
> +static int caam_jr_suspend(struct device *dev) {
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct caam_drv_private_jr *jrpriv = platform_get_drvdata(pdev);
> +	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev->parent);
> +	struct caam_jr_dequeue_params suspend_params = {
> +		.dev = dev,
> +		.enable_itr = 0,
> +	};
> +
> +	/* Remove the node from Physical JobR list maintained by driver */
> +	spin_lock(&driver_data.jr_alloc_lock);
> +	list_del(&jrpriv->list_node);
> +	spin_unlock(&driver_data.jr_alloc_lock);
> +
> +	if (jrpriv->hwrng)
> +		caam_rng_exit(dev->parent);
> +
> +	if (ctrlpriv->caam_off_during_pm) {
> +		int err;
> +
> +		tasklet_disable(&jrpriv->irqtask);
> +
> +		/* mask itr to call flush */
> +		clrsetbits_32(&jrpriv->rregs->rconfig_lo, 0, JRCFG_IMSK);
> +
> +		/* Invalid job in process */
> +		err = caam_jr_flush(dev);
> +		if (err) {
> +			dev_err(dev, "Failed to flush\n");
> +			return err;
> +		}
> +
> +		/* Dequeing jobs flushed */
> +		caam_jr_dequeue((unsigned long)&suspend_params);
> +
> +		/* Save state */
> +		caam_jr_get_hw_state(dev);
> +	} else if (device_may_wakeup(&pdev->dev)) {
> +		enable_irq_wake(jrpriv->irq);
> +	}
> +
> +	return 0;
> +}
> +
> +static int caam_jr_resume(struct device *dev) {
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct caam_drv_private_jr *jrpriv = platform_get_drvdata(pdev);
> +	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev->parent);
> +
> +	if (ctrlpriv->caam_off_during_pm) {
> +		u64 inp_addr;
> +		int err;
> +
> +		/*
> +		 * Check if the CAAM has been resetted checking the address of
> +		 * the input ring
> +		 */
> +		inp_addr = rd_reg64(&jrpriv->rregs->inpring_base);
> +		if (inp_addr != 0) {
> +			/* JR still has some configuration */
> +			if (inp_addr == jrpriv->state.inpbusaddr) {
> +				/* JR has not been resetted */
> +				err = caam_jr_restart_processing(dev);
> +				if (err) {
> +					dev_err(dev,
> +						"Restart processing failed\n");
> +					return err;
> +				}
> +
> +				tasklet_enable(&jrpriv->irqtask);
> +
> +				clrsetbits_32(&jrpriv->rregs->rconfig_lo,
> +					      JRCFG_IMSK, 0);
> +
> +				goto add_jr;
> +			} else if (ctrlpriv->optee_en) {
> +				/* JR has been used by OPTEE, reset it */
> +				err = caam_reset_hw_jr(dev);
> +				if (err) {
> +					dev_err(dev, "Failed to reset JR\n");
> +					return err;
> +				}
> +			} else {
> +				/* No explanation, return error */
> +				return -EIO;
> +			}
> +		}
> +
> +		caam_jr_reset_index(jrpriv);
> +		caam_jr_init_hw(dev, jrpriv->state.inpbusaddr,
> +				jrpriv->state.outbusaddr);
> +
> +		tasklet_enable(&jrpriv->irqtask);
> +	} else if (device_may_wakeup(&pdev->dev)) {
> +		disable_irq_wake(jrpriv->irq);
> +	}
> +
> +add_jr:
> +	spin_lock(&driver_data.jr_alloc_lock);
> +	list_add_tail(&jrpriv->list_node, &driver_data.jr_list);
> +	spin_unlock(&driver_data.jr_alloc_lock);
> +
> +	if (jrpriv->hwrng)
> +		jrpriv->hwrng = !caam_rng_init(dev->parent);
> +
> +	return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(caam_jr_pm_ops, caam_jr_suspend,
> +caam_jr_resume); #endif /* CONFIG_PM_SLEEP */
> +
>  static const struct of_device_id caam_jr_match[] = {
>  	{
>  		.compatible = "fsl,sec-v4.0-job-ring", @@ -655,6 +815,9 @@
> static struct platform_driver caam_jr_driver = {
>  	.driver = {
>  		.name = "caam_jr",
>  		.of_match_table = caam_jr_match,
> +#ifdef CONFIG_PM_SLEEP
> +		.pm = &caam_jr_pm_ops,
> +#endif
>  	},
>  	.probe       = caam_jr_probe,
>  	.remove      = caam_jr_remove,
> diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index
> 0f87bd365582..873df9de9890 100644
> --- a/drivers/crypto/caam/regs.h
> +++ b/drivers/crypto/caam/regs.h
> @@ -584,8 +584,7 @@ struct caam_ctrl {
>  	u32 deco_rsr;			/* DECORSR - Deco Request Source */
>  	u32 rsvd11;
>  	u32 deco_rq;			/* DECORR - DECO Request */
> -	struct masterid deco_mid[5];	/* DECOxLIODNR - 1 per DECO */
> -	u32 rsvd5[22];
> +	struct masterid deco_mid[16];	/* DECOxLIODNR - 1 per DECO */
> 
>  	/* DECO Availability/Reset Section			120-3ff */
>  	u32 deco_avail;		/* DAR - DECO availability */
> --
> 2.25.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/2] crypto: caam - add power management support
  2023-07-12  6:07 ` [PATCH 2/2] crypto: caam - add power management support meenakshi.aggarwal
  2023-07-17  5:42   ` Gaurav Jain
@ 2023-07-22  1:42   ` Herbert Xu
  1 sibling, 0 replies; 11+ messages in thread
From: Herbert Xu @ 2023-07-22  1:42 UTC (permalink / raw
  To: meenakshi.aggarwal
  Cc: horia.geanta, V.sethi, pankaj.gupta, gaurav.jain, davem,
	linux-crypto, linux-kernel, Victoria Milhoan, Dan Douglass,
	Vipul Kumar, Franck LENORMAND

On Wed, Jul 12, 2023 at 08:07:28AM +0200, meenakshi.aggarwal@nxp.com wrote:
>
> +#ifdef CONFIG_PM_SLEEP
> +		.pm = &caam_jr_pm_ops,
> +#endif

I think this should be unconditional as the pm attribute is always
present.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 0/2] Add power management support in CAAM driver
  2023-07-12  6:07 [PATCH 0/2] Add power management support in CAAM driver meenakshi.aggarwal
                   ` (2 preceding siblings ...)
  2023-07-17  5:41 ` [PATCH 0/2] Add power management support in CAAM driver Gaurav Jain
@ 2023-07-24  6:52 ` meenakshi.aggarwal
  2023-07-24  6:52   ` [PATCH v2 1/2] crypto: caam - Change structure type representing DECO MID meenakshi.aggarwal
                     ` (2 more replies)
  3 siblings, 3 replies; 11+ messages in thread
From: meenakshi.aggarwal @ 2023-07-24  6:52 UTC (permalink / raw
  To: horia.geanta, V.sethi, pankaj.gupta, gaurav.jain, herbert, davem,
	linux-crypto, linux-kernel
  Cc: Meenakshi Aggarwal

From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

This patch set add support of Power Management in CAAM driver

We are saving the state of the CAAM:
 - JRs MID
 - Address of input and output rings
in suspend function and getting same state in resume function
on platforms where power of CAAM is turned off.

Changes in v2:
	- not protecting PM code under macro CONFIG_PM_SLEEP
	as CONFIG_PM_SLEEP is on by default

Franck LENORMAND (1):
  crypto: caam - Change structure type representing DECO MID

Horia Geanta (1):
  crypto: caam - add power management support

 drivers/crypto/caam/ctrl.c   | 106 +++++++++++++++++++
 drivers/crypto/caam/intern.h |  25 ++++-
 drivers/crypto/caam/jr.c     | 193 +++++++++++++++++++++++++++++++----
 drivers/crypto/caam/regs.h   |   9 +-
 4 files changed, 306 insertions(+), 27 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 1/2] crypto: caam - Change structure type representing DECO MID
  2023-07-24  6:52 ` [PATCH v2 " meenakshi.aggarwal
@ 2023-07-24  6:52   ` meenakshi.aggarwal
  2023-07-24  6:52   ` [PATCH v2 2/2] crypto: caam - add power management support meenakshi.aggarwal
  2023-08-04  9:25   ` [PATCH v2 0/2] Add power management support in CAAM driver Herbert Xu
  2 siblings, 0 replies; 11+ messages in thread
From: meenakshi.aggarwal @ 2023-07-24  6:52 UTC (permalink / raw
  To: horia.geanta, V.sethi, pankaj.gupta, gaurav.jain, herbert, davem,
	linux-crypto, linux-kernel
  Cc: Franck LENORMAND, Meenakshi Aggarwal

From: Franck LENORMAND <franck.lenormand@nxp.com>

The structure partid is not suitable to represent the DECO MID register.

This patch replace partid by masterid which is more appropriate.

Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Reviewed-by: Gaurav Jain <gaurav.jain@nxp.com>
---
 drivers/crypto/caam/regs.h | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 189e74c21f0c..0f87bd365582 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -459,12 +459,6 @@ struct masterid {
 	u32 liodn_ls;	/* LIODN for non-sequence and seq access */
 };
 
-/* Partition ID for DMA configuration */
-struct partid {
-	u32 rsvd1;
-	u32 pidr;	/* partition ID, DECO */
-};
-
 /* RNGB test mode (replicated twice in some configurations) */
 /* Padded out to 0x100 */
 struct rngtst {
@@ -590,7 +584,7 @@ struct caam_ctrl {
 	u32 deco_rsr;			/* DECORSR - Deco Request Source */
 	u32 rsvd11;
 	u32 deco_rq;			/* DECORR - DECO Request */
-	struct partid deco_mid[5];	/* DECOxLIODNR - 1 per DECO */
+	struct masterid deco_mid[5];	/* DECOxLIODNR - 1 per DECO */
 	u32 rsvd5[22];
 
 	/* DECO Availability/Reset Section			120-3ff */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 2/2] crypto: caam - add power management support
  2023-07-24  6:52 ` [PATCH v2 " meenakshi.aggarwal
  2023-07-24  6:52   ` [PATCH v2 1/2] crypto: caam - Change structure type representing DECO MID meenakshi.aggarwal
@ 2023-07-24  6:52   ` meenakshi.aggarwal
  2023-08-04  9:25   ` [PATCH v2 0/2] Add power management support in CAAM driver Herbert Xu
  2 siblings, 0 replies; 11+ messages in thread
From: meenakshi.aggarwal @ 2023-07-24  6:52 UTC (permalink / raw
  To: horia.geanta, V.sethi, pankaj.gupta, gaurav.jain, herbert, davem,
	linux-crypto, linux-kernel
  Cc: Victoria Milhoan, Dan Douglass, Vipul Kumar, Franck LENORMAND,
	Meenakshi Aggarwal

From: Horia Geanta <horia.geanta@nxp.com>

Add support for suspend and resume operation for PM in CAAM driver.

When the CAAM goes in suspend, the hardware is considered to do nothing.

On some platforms, the power of the CAAM is not turned off so it keeps
its configuration.
On other platforms, it doesn't so it is necessary to save the state of
the CAAM:
 - JRs MID
 - Address of input and output rings

Signed-off-by: Horia Geanta <horia.geanta@nxp.com>
Signed-off-by: Victoria Milhoan <vicki.milhoan@freescale.com>
Signed-off-by: Dan Douglass <dan.douglass@nxp.com>
Signed-off-by: Vipul Kumar <vipul_kumar@mentor.com>
Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Reviewed-by: Gaurav Jain <gaurav.jain@nxp.com>
---
 drivers/crypto/caam/ctrl.c   | 106 +++++++++++++++++++
 drivers/crypto/caam/intern.h |  25 ++++-
 drivers/crypto/caam/jr.c     | 193 +++++++++++++++++++++++++++++++----
 drivers/crypto/caam/regs.h   |   3 +-
 4 files changed, 306 insertions(+), 21 deletions(-)

diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index ff9ddbbca377..a7a4583107f4 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -740,6 +740,109 @@ static int caam_ctrl_rng_init(struct device *dev)
 	return 0;
 }
 
+/* Indicate if the internal state of the CAAM is lost during PM */
+static int caam_off_during_pm(void)
+{
+	bool not_off_during_pm = of_machine_is_compatible("fsl,imx6q") ||
+				 of_machine_is_compatible("fsl,imx6qp") ||
+				 of_machine_is_compatible("fsl,imx6dl");
+
+	return not_off_during_pm ? 0 : 1;
+}
+
+static void caam_state_save(struct device *dev)
+{
+	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
+	struct caam_ctl_state *state = &ctrlpriv->state;
+	struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl;
+	u32 deco_inst, jr_inst;
+	int i;
+
+	state->mcr = rd_reg32(&ctrl->mcr);
+	state->scfgr = rd_reg32(&ctrl->scfgr);
+
+	deco_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) &
+		     CHA_ID_MS_DECO_MASK) >> CHA_ID_MS_DECO_SHIFT;
+	for (i = 0; i < deco_inst; i++) {
+		state->deco_mid[i].liodn_ms =
+			rd_reg32(&ctrl->deco_mid[i].liodn_ms);
+		state->deco_mid[i].liodn_ls =
+			rd_reg32(&ctrl->deco_mid[i].liodn_ls);
+	}
+
+	jr_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) &
+		   CHA_ID_MS_JR_MASK) >> CHA_ID_MS_JR_SHIFT;
+	for (i = 0; i < jr_inst; i++) {
+		state->jr_mid[i].liodn_ms =
+			rd_reg32(&ctrl->jr_mid[i].liodn_ms);
+		state->jr_mid[i].liodn_ls =
+			rd_reg32(&ctrl->jr_mid[i].liodn_ls);
+	}
+}
+
+static void caam_state_restore(const struct device *dev)
+{
+	const struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
+	const struct caam_ctl_state *state = &ctrlpriv->state;
+	struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl;
+	u32 deco_inst, jr_inst;
+	int i;
+
+	wr_reg32(&ctrl->mcr, state->mcr);
+	wr_reg32(&ctrl->scfgr, state->scfgr);
+
+	deco_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) &
+		     CHA_ID_MS_DECO_MASK) >> CHA_ID_MS_DECO_SHIFT;
+	for (i = 0; i < deco_inst; i++) {
+		wr_reg32(&ctrl->deco_mid[i].liodn_ms,
+			 state->deco_mid[i].liodn_ms);
+		wr_reg32(&ctrl->deco_mid[i].liodn_ls,
+			 state->deco_mid[i].liodn_ls);
+	}
+
+	jr_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) &
+		   CHA_ID_MS_JR_MASK) >> CHA_ID_MS_JR_SHIFT;
+	for (i = 0; i < jr_inst; i++) {
+		wr_reg32(&ctrl->jr_mid[i].liodn_ms,
+			 state->jr_mid[i].liodn_ms);
+		wr_reg32(&ctrl->jr_mid[i].liodn_ls,
+			 state->jr_mid[i].liodn_ls);
+	}
+
+	if (ctrlpriv->virt_en == 1)
+		clrsetbits_32(&ctrl->jrstart, 0, JRSTART_JR0_START |
+			      JRSTART_JR1_START | JRSTART_JR2_START |
+			      JRSTART_JR3_START);
+}
+
+static int caam_ctrl_suspend(struct device *dev)
+{
+	const struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
+
+	if (ctrlpriv->caam_off_during_pm && !ctrlpriv->optee_en)
+		caam_state_save(dev);
+
+	return 0;
+}
+
+static int caam_ctrl_resume(struct device *dev)
+{
+	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (ctrlpriv->caam_off_during_pm && !ctrlpriv->optee_en) {
+		caam_state_restore(dev);
+
+		/* HW and rng will be reset so deinstantiation can be removed */
+		devm_remove_action(dev, devm_deinstantiate_rng, dev);
+		ret = caam_ctrl_rng_init(dev);
+	}
+
+	return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(caam_ctrl_pm_ops, caam_ctrl_suspend, caam_ctrl_resume);
+
 /* Probe routine for CAAM top (controller) level */
 static int caam_probe(struct platform_device *pdev)
 {
@@ -771,6 +874,8 @@ static int caam_probe(struct platform_device *pdev)
 
 	caam_imx = (bool)imx_soc_match;
 
+	ctrlpriv->caam_off_during_pm = caam_imx && caam_off_during_pm();
+
 	if (imx_soc_match) {
 		/*
 		 * Until Layerscape and i.MX OP-TEE get in sync,
@@ -1033,6 +1138,7 @@ static struct platform_driver caam_driver = {
 	.driver = {
 		.name = "caam",
 		.of_match_table = caam_match,
+		.pm = &caam_ctrl_pm_ops,
 	},
 	.probe       = caam_probe,
 };
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index b4f7bf77f487..e51320150872 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -4,7 +4,7 @@
  * Private/internal definitions between modules
  *
  * Copyright 2008-2011 Freescale Semiconductor, Inc.
- * Copyright 2019 NXP
+ * Copyright 2019, 2023 NXP
  */
 
 #ifndef INTERN_H
@@ -47,6 +47,16 @@ struct caam_jrentry_info {
 	u32 desc_size;	/* Stored size for postprocessing, header derived */
 };
 
+struct caam_jr_state {
+	dma_addr_t inpbusaddr;
+	dma_addr_t outbusaddr;
+};
+
+struct caam_jr_dequeue_params {
+	struct device *dev;
+	int enable_itr;
+};
+
 /* Private sub-storage for a single JobR */
 struct caam_drv_private_jr {
 	struct list_head	list_node;	/* Job Ring device list */
@@ -54,6 +64,7 @@ struct caam_drv_private_jr {
 	int ridx;
 	struct caam_job_ring __iomem *rregs;	/* JobR's register space */
 	struct tasklet_struct irqtask;
+	struct caam_jr_dequeue_params tasklet_params;
 	int irq;			/* One per queue */
 	bool hwrng;
 
@@ -71,6 +82,15 @@ struct caam_drv_private_jr {
 	int tail;			/* entinfo (s/w ring) tail index */
 	void *outring;			/* Base of output ring, DMA-safe */
 	struct crypto_engine *engine;
+
+	struct caam_jr_state state;	/* State of the JR during PM */
+};
+
+struct caam_ctl_state {
+	struct masterid deco_mid[16];
+	struct masterid jr_mid[4];
+	u32 mcr;
+	u32 scfgr;
 };
 
 /*
@@ -116,6 +136,9 @@ struct caam_drv_private {
 	struct dentry *ctl; /* controller dir */
 	struct debugfs_blob_wrapper ctl_kek_wrap, ctl_tkek_wrap, ctl_tdsk_wrap;
 #endif
+
+	int caam_off_during_pm;		/* If the CAAM is reset after suspend */
+	struct caam_ctl_state state;	/* State of the CTL during PM */
 };
 
 #ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 96dea5304d22..316180d26f8a 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -117,6 +117,23 @@ static int caam_jr_flush(struct device *dev)
 	return caam_jr_stop_processing(dev, JRCR_RESET);
 }
 
+/* The resume can be used after a park or a flush if CAAM has not been reset */
+static int caam_jr_restart_processing(struct device *dev)
+{
+	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+	u32 halt_status = rd_reg32(&jrp->rregs->jrintstatus) &
+			  JRINT_ERR_HALT_MASK;
+
+	/* Check that the flush/park is completed */
+	if (halt_status != JRINT_ERR_HALT_COMPLETE)
+		return -1;
+
+	/* Resume processing of jobs */
+	clrsetbits_32(&jrp->rregs->jrintstatus, 0, JRINT_ERR_HALT_COMPLETE);
+
+	return 0;
+}
+
 static int caam_reset_hw_jr(struct device *dev)
 {
 	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
@@ -245,7 +262,8 @@ static irqreturn_t caam_jr_interrupt(int irq, void *st_dev)
 static void caam_jr_dequeue(unsigned long devarg)
 {
 	int hw_idx, sw_idx, i, head, tail;
-	struct device *dev = (struct device *)devarg;
+	struct caam_jr_dequeue_params *params = (void *)devarg;
+	struct device *dev = params->dev;
 	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
 	void (*usercall)(struct device *dev, u32 *desc, u32 status, void *arg);
 	u32 *userdesc, userstatus;
@@ -319,8 +337,9 @@ static void caam_jr_dequeue(unsigned long devarg)
 		outring_used--;
 	}
 
-	/* reenable / unmask IRQs */
-	clrsetbits_32(&jrp->rregs->rconfig_lo, JRCFG_IMSK, 0);
+	if (params->enable_itr)
+		/* reenable / unmask IRQs */
+		clrsetbits_32(&jrp->rregs->rconfig_lo, JRCFG_IMSK, 0);
 }
 
 /**
@@ -470,6 +489,29 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
 }
 EXPORT_SYMBOL(caam_jr_enqueue);
 
+static void caam_jr_init_hw(struct device *dev, dma_addr_t inpbusaddr,
+			    dma_addr_t outbusaddr)
+{
+	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+
+	wr_reg64(&jrp->rregs->inpring_base, inpbusaddr);
+	wr_reg64(&jrp->rregs->outring_base, outbusaddr);
+	wr_reg32(&jrp->rregs->inpring_size, JOBR_DEPTH);
+	wr_reg32(&jrp->rregs->outring_size, JOBR_DEPTH);
+
+	/* Select interrupt coalescing parameters */
+	clrsetbits_32(&jrp->rregs->rconfig_lo, 0, JOBR_INTC |
+		      (JOBR_INTC_COUNT_THLD << JRCFG_ICDCT_SHIFT) |
+		      (JOBR_INTC_TIME_THLD << JRCFG_ICTT_SHIFT));
+}
+
+static void caam_jr_reset_index(struct caam_drv_private_jr *jrp)
+{
+	jrp->out_ring_read_index = 0;
+	jrp->head = 0;
+	jrp->tail = 0;
+}
+
 /*
  * Init JobR independent of platform property detection
  */
@@ -506,25 +548,16 @@ static int caam_jr_init(struct device *dev)
 		jrp->entinfo[i].desc_addr_dma = !0;
 
 	/* Setup rings */
-	jrp->out_ring_read_index = 0;
-	jrp->head = 0;
-	jrp->tail = 0;
-
-	wr_reg64(&jrp->rregs->inpring_base, inpbusaddr);
-	wr_reg64(&jrp->rregs->outring_base, outbusaddr);
-	wr_reg32(&jrp->rregs->inpring_size, JOBR_DEPTH);
-	wr_reg32(&jrp->rregs->outring_size, JOBR_DEPTH);
-
+	caam_jr_reset_index(jrp);
 	jrp->inpring_avail = JOBR_DEPTH;
+	caam_jr_init_hw(dev, inpbusaddr, outbusaddr);
 
 	spin_lock_init(&jrp->inplock);
 
-	/* Select interrupt coalescing parameters */
-	clrsetbits_32(&jrp->rregs->rconfig_lo, 0, JOBR_INTC |
-		      (JOBR_INTC_COUNT_THLD << JRCFG_ICDCT_SHIFT) |
-		      (JOBR_INTC_TIME_THLD << JRCFG_ICTT_SHIFT));
-
-	tasklet_init(&jrp->irqtask, caam_jr_dequeue, (unsigned long)dev);
+	jrp->tasklet_params.dev = dev;
+	jrp->tasklet_params.enable_itr = 1;
+	tasklet_init(&jrp->irqtask, caam_jr_dequeue,
+		     (unsigned long)&jrp->tasklet_params);
 
 	/* Connect job ring interrupt handler. */
 	error = devm_request_irq(dev, jrp->irq, caam_jr_interrupt, IRQF_SHARED,
@@ -635,11 +668,134 @@ static int caam_jr_probe(struct platform_device *pdev)
 
 	atomic_set(&jrpriv->tfm_count, 0);
 
+	device_init_wakeup(&pdev->dev, 1);
+	device_set_wakeup_enable(&pdev->dev, false);
+
 	register_algs(jrpriv, jrdev->parent);
 
 	return 0;
 }
 
+static void caam_jr_get_hw_state(struct device *dev)
+{
+	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+
+	jrp->state.inpbusaddr = rd_reg64(&jrp->rregs->inpring_base);
+	jrp->state.outbusaddr = rd_reg64(&jrp->rregs->outring_base);
+}
+
+static int caam_jr_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct caam_drv_private_jr *jrpriv = platform_get_drvdata(pdev);
+	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev->parent);
+	struct caam_jr_dequeue_params suspend_params = {
+		.dev = dev,
+		.enable_itr = 0,
+	};
+
+	/* Remove the node from Physical JobR list maintained by driver */
+	spin_lock(&driver_data.jr_alloc_lock);
+	list_del(&jrpriv->list_node);
+	spin_unlock(&driver_data.jr_alloc_lock);
+
+	if (jrpriv->hwrng)
+		caam_rng_exit(dev->parent);
+
+	if (ctrlpriv->caam_off_during_pm) {
+		int err;
+
+		tasklet_disable(&jrpriv->irqtask);
+
+		/* mask itr to call flush */
+		clrsetbits_32(&jrpriv->rregs->rconfig_lo, 0, JRCFG_IMSK);
+
+		/* Invalid job in process */
+		err = caam_jr_flush(dev);
+		if (err) {
+			dev_err(dev, "Failed to flush\n");
+			return err;
+		}
+
+		/* Dequeing jobs flushed */
+		caam_jr_dequeue((unsigned long)&suspend_params);
+
+		/* Save state */
+		caam_jr_get_hw_state(dev);
+	} else if (device_may_wakeup(&pdev->dev)) {
+		enable_irq_wake(jrpriv->irq);
+	}
+
+	return 0;
+}
+
+static int caam_jr_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct caam_drv_private_jr *jrpriv = platform_get_drvdata(pdev);
+	struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev->parent);
+
+	if (ctrlpriv->caam_off_during_pm) {
+		u64 inp_addr;
+		int err;
+
+		/*
+		 * Check if the CAAM has been resetted checking the address of
+		 * the input ring
+		 */
+		inp_addr = rd_reg64(&jrpriv->rregs->inpring_base);
+		if (inp_addr != 0) {
+			/* JR still has some configuration */
+			if (inp_addr == jrpriv->state.inpbusaddr) {
+				/* JR has not been resetted */
+				err = caam_jr_restart_processing(dev);
+				if (err) {
+					dev_err(dev,
+						"Restart processing failed\n");
+					return err;
+				}
+
+				tasklet_enable(&jrpriv->irqtask);
+
+				clrsetbits_32(&jrpriv->rregs->rconfig_lo,
+					      JRCFG_IMSK, 0);
+
+				goto add_jr;
+			} else if (ctrlpriv->optee_en) {
+				/* JR has been used by OPTEE, reset it */
+				err = caam_reset_hw_jr(dev);
+				if (err) {
+					dev_err(dev, "Failed to reset JR\n");
+					return err;
+				}
+			} else {
+				/* No explanation, return error */
+				return -EIO;
+			}
+		}
+
+		caam_jr_reset_index(jrpriv);
+		caam_jr_init_hw(dev, jrpriv->state.inpbusaddr,
+				jrpriv->state.outbusaddr);
+
+		tasklet_enable(&jrpriv->irqtask);
+	} else if (device_may_wakeup(&pdev->dev)) {
+		disable_irq_wake(jrpriv->irq);
+	}
+
+add_jr:
+	spin_lock(&driver_data.jr_alloc_lock);
+	list_add_tail(&jrpriv->list_node, &driver_data.jr_list);
+	spin_unlock(&driver_data.jr_alloc_lock);
+
+	if (jrpriv->hwrng)
+		jrpriv->hwrng = !caam_rng_init(dev->parent);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(caam_jr_pm_ops, caam_jr_suspend, caam_jr_resume);
+
 static const struct of_device_id caam_jr_match[] = {
 	{
 		.compatible = "fsl,sec-v4.0-job-ring",
@@ -655,6 +811,7 @@ static struct platform_driver caam_jr_driver = {
 	.driver = {
 		.name = "caam_jr",
 		.of_match_table = caam_jr_match,
+		.pm = &caam_jr_pm_ops,
 	},
 	.probe       = caam_jr_probe,
 	.remove      = caam_jr_remove,
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 0f87bd365582..873df9de9890 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -584,8 +584,7 @@ struct caam_ctrl {
 	u32 deco_rsr;			/* DECORSR - Deco Request Source */
 	u32 rsvd11;
 	u32 deco_rq;			/* DECORR - DECO Request */
-	struct masterid deco_mid[5];	/* DECOxLIODNR - 1 per DECO */
-	u32 rsvd5[22];
+	struct masterid deco_mid[16];	/* DECOxLIODNR - 1 per DECO */
 
 	/* DECO Availability/Reset Section			120-3ff */
 	u32 deco_avail;		/* DAR - DECO availability */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 0/2] Add power management support in CAAM driver
  2023-07-24  6:52 ` [PATCH v2 " meenakshi.aggarwal
  2023-07-24  6:52   ` [PATCH v2 1/2] crypto: caam - Change structure type representing DECO MID meenakshi.aggarwal
  2023-07-24  6:52   ` [PATCH v2 2/2] crypto: caam - add power management support meenakshi.aggarwal
@ 2023-08-04  9:25   ` Herbert Xu
  2 siblings, 0 replies; 11+ messages in thread
From: Herbert Xu @ 2023-08-04  9:25 UTC (permalink / raw
  To: meenakshi.aggarwal
  Cc: horia.geanta, V.sethi, pankaj.gupta, gaurav.jain, davem,
	linux-crypto, linux-kernel

On Mon, Jul 24, 2023 at 08:52:28AM +0200, meenakshi.aggarwal@nxp.com wrote:
> From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> 
> This patch set add support of Power Management in CAAM driver
> 
> We are saving the state of the CAAM:
>  - JRs MID
>  - Address of input and output rings
> in suspend function and getting same state in resume function
> on platforms where power of CAAM is turned off.
> 
> Changes in v2:
> 	- not protecting PM code under macro CONFIG_PM_SLEEP
> 	as CONFIG_PM_SLEEP is on by default
> 
> Franck LENORMAND (1):
>   crypto: caam - Change structure type representing DECO MID
> 
> Horia Geanta (1):
>   crypto: caam - add power management support
> 
>  drivers/crypto/caam/ctrl.c   | 106 +++++++++++++++++++
>  drivers/crypto/caam/intern.h |  25 ++++-
>  drivers/crypto/caam/jr.c     | 193 +++++++++++++++++++++++++++++++----
>  drivers/crypto/caam/regs.h   |   9 +-
>  4 files changed, 306 insertions(+), 27 deletions(-)
> 
> -- 
> 2.25.1

All applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2023-08-04  9:26 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-12  6:07 [PATCH 0/2] Add power management support in CAAM driver meenakshi.aggarwal
2023-07-12  6:07 ` [PATCH 1/2] crypto: caam - Change structure type representing DECO MID meenakshi.aggarwal
2023-07-17  5:42   ` Gaurav Jain
2023-07-12  6:07 ` [PATCH 2/2] crypto: caam - add power management support meenakshi.aggarwal
2023-07-17  5:42   ` Gaurav Jain
2023-07-22  1:42   ` Herbert Xu
2023-07-17  5:41 ` [PATCH 0/2] Add power management support in CAAM driver Gaurav Jain
2023-07-24  6:52 ` [PATCH v2 " meenakshi.aggarwal
2023-07-24  6:52   ` [PATCH v2 1/2] crypto: caam - Change structure type representing DECO MID meenakshi.aggarwal
2023-07-24  6:52   ` [PATCH v2 2/2] crypto: caam - add power management support meenakshi.aggarwal
2023-08-04  9:25   ` [PATCH v2 0/2] Add power management support in CAAM driver Herbert Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).