* [PATCH 1/2] drivers/memory: Add deep sleep support for IFC
@ 2015-10-27 11:04 Raghav Dogra
2015-10-29 16:21 ` Scott Wood
0 siblings, 1 reply; 2+ messages in thread
From: Raghav Dogra @ 2015-10-27 11:04 UTC (permalink / raw)
To: linux-kernel; +Cc: scottwood, Raghav Dogra
Add support of suspend, resume function to support deep sleep.
Also make sure of SRAM initialization during resume.
Signed-off-by: Raghav Dogra <raghav@freescale.com>
---
drivers/memory/fsl_ifc.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/fsl_ifc.h | 6 ++++++
2 files changed, 62 insertions(+)
diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c
index e87459f..163ccf2 100644
--- a/drivers/memory/fsl_ifc.c
+++ b/drivers/memory/fsl_ifc.c
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/compiler.h>
#include <linux/spinlock.h>
+#include <linux/delay.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/io.h>
@@ -35,6 +36,9 @@
struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev;
EXPORT_SYMBOL(fsl_ifc_ctrl_dev);
+#define FSL_IFC_V1_3_0 0x01030000
+#define IFC_TIMEOUT_MSECS 100000 /* 100ms */
+
/*
* convert_ifc_address - convert the base address
* @addr_base: base address of the memory bank
@@ -308,6 +312,53 @@ err:
return ret;
}
+#ifdef CONFIG_PM_SLEEP
+/* save ifc registers */
+static int fsl_ifc_suspend(struct device *dev)
+{
+ struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(dev);
+ struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+
+ ctrl->saved_regs = kzalloc(sizeof(struct fsl_ifc_regs), GFP_KERNEL);
+ if (!ctrl->saved_regs)
+ return -ENOMEM;
+
+ _memcpy_fromio(ctrl->saved_regs, ifc, sizeof(struct fsl_ifc_regs));
+
+ return 0;
+}
+
+/* restore ifc registers */
+static int fsl_ifc_resume(struct device *dev)
+{
+ struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(dev);
+ struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+ uint32_t ver = 0, ncfgr, status;
+
+ if (ctrl->saved_regs) {
+ _memcpy_toio(ifc, ctrl->saved_regs,
+ sizeof(struct fsl_ifc_regs));
+ kfree(ctrl->saved_regs);
+ ctrl->saved_regs = NULL;
+ }
+
+ ver = in_be32(&ctrl->regs->ifc_rev);
+ ncfgr = in_be32(&ifc->ifc_nand.ncfgr);
+ if (ver >= FSL_IFC_V1_3_0) {
+ out_be32(&ifc->ifc_nand.ncfgr, ncfgr | IFC_NAND_SRAM_INIT_EN);
+
+ /* wait for SRAM_INIT bit to be clear or timeout */
+ status = spin_event_timeout(!(in_be32(&ifc->ifc_nand.ncfgr)
+ & IFC_NAND_SRAM_INIT_EN),
+ IFC_TIMEOUT_MSECS, 0);
+ if (!status)
+ dev_err(ctrl->dev, "Timeout waiting for IFC SRAM INIT");
+ }
+
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
static const struct of_device_id fsl_ifc_match[] = {
{
.compatible = "fsl,ifc",
@@ -315,10 +366,15 @@ static const struct of_device_id fsl_ifc_match[] = {
{},
};
+static const struct dev_pm_ops ifc_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(fsl_ifc_suspend, fsl_ifc_resume)
+};
+
static struct platform_driver fsl_ifc_ctrl_driver = {
.driver = {
.name = "fsl-ifc",
.of_match_table = fsl_ifc_match,
+ .pm = &ifc_pm_ops,
},
.probe = fsl_ifc_ctrl_probe,
.remove = fsl_ifc_ctrl_remove,
diff --git a/include/linux/fsl_ifc.h b/include/linux/fsl_ifc.h
index 0023088..2776df2 100644
--- a/include/linux/fsl_ifc.h
+++ b/include/linux/fsl_ifc.h
@@ -270,6 +270,8 @@
*/
/* Auto Boot Mode */
#define IFC_NAND_NCFGR_BOOT 0x80000000
+/* SRAM INIT EN */
+#define IFC_NAND_SRAM_INIT_EN 0x20000000
/* Addressing Mode-ROW0+n/COL0 */
#define IFC_NAND_NCFGR_ADDR_MODE_RC0 0x00000000
/* Addressing Mode-ROW0+n/COL0+n */
@@ -841,6 +843,10 @@ struct fsl_ifc_ctrl {
u32 nand_stat;
wait_queue_head_t nand_wait;
+#ifdef CONFIG_PM_SLEEP
+ /* save regs when system go to deep-sleep */
+ struct fsl_ifc_regs *saved_regs;
+#endif
bool little_endian;
};
--
1.9.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH 1/2] drivers/memory: Add deep sleep support for IFC
2015-10-27 11:04 [PATCH 1/2] drivers/memory: Add deep sleep support for IFC Raghav Dogra
@ 2015-10-29 16:21 ` Scott Wood
0 siblings, 0 replies; 2+ messages in thread
From: Scott Wood @ 2015-10-29 16:21 UTC (permalink / raw)
To: Raghav Dogra; +Cc: linux-kernel, prabhakar
On Tue, 2015-10-27 at 16:34 +0530, Raghav Dogra wrote:
> Add support of suspend, resume function to support deep sleep.
> Also make sure of SRAM initialization during resume.
>
> Signed-off-by: Raghav Dogra <raghav@freescale.com>
> ---
> drivers/memory/fsl_ifc.c | 56
> ++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/fsl_ifc.h | 6 ++++++
> 2 files changed, 62 insertions(+)
Who are you asking to apply this? If me, please send to
linuxppc-dev@lists.ozlabs.orgso it gets on patchwork.
Also keep Prabhakar CCed on IFC patches.
> diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c
> index e87459f..163ccf2 100644
> --- a/drivers/memory/fsl_ifc.c
> +++ b/drivers/memory/fsl_ifc.c
> @@ -23,6 +23,7 @@
> #include <linux/kernel.h>
> #include <linux/compiler.h>
> #include <linux/spinlock.h>
> +#include <linux/delay.h>
> #include <linux/types.h>
> #include <linux/slab.h>
> #include <linux/io.h>
> @@ -35,6 +36,9 @@
> struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev;
> EXPORT_SYMBOL(fsl_ifc_ctrl_dev);
>
> +#define FSL_IFC_V1_3_0 0x01030000
> +#define IFC_TIMEOUT_MSECS 100000 /* 100ms */
> +
> /*
> * convert_ifc_address - convert the base address
> * @addr_base: base address of the memory bank
> @@ -308,6 +312,53 @@ err:
> return ret;
> }
>
> +#ifdef CONFIG_PM_SLEEP
> +/* save ifc registers */
> +static int fsl_ifc_suspend(struct device *dev)
> +{
> + struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(dev);
> + struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
> +
> + ctrl->saved_regs = kzalloc(sizeof(struct fsl_ifc_regs), GFP_KERNEL);
> + if (!ctrl->saved_regs)
> + return -ENOMEM;
> +
> + _memcpy_fromio(ctrl->saved_regs, ifc, sizeof(struct fsl_ifc_regs));
> +
> + return 0;
> +}
Why _memcpy_fromio() rather than memcpy_fromio()?
> +/* restore ifc registers */
> +static int fsl_ifc_resume(struct device *dev)
> +{
> + struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(dev);
> + struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
> + uint32_t ver = 0, ncfgr, status;
> +
> + if (ctrl->saved_regs) {
> + _memcpy_toio(ifc, ctrl->saved_regs,
> + sizeof(struct fsl_ifc_regs));
This is too simplistic, and doesn't account for things like read-to-clear
bits, or the possibility of reserved fields that expose internal state that
shouldn't be messed with. Registers that need state saving or
reinitialization should be handled individually.
You should also make sure that interrupts are disabled at the device.
> + kfree(ctrl->saved_regs);
> + ctrl->saved_regs = NULL;
> + }
> +
> + ver = in_be32(&ctrl->regs->ifc_rev);
> + ncfgr = in_be32(&ifc->ifc_nand.ncfgr);
> + if (ver >= FSL_IFC_V1_3_0) {
> + out_be32(&ifc->ifc_nand.ncfgr, ncfgr | IFC_NAND_SRAM_INIT_EN);
> +
> + /* wait for SRAM_INIT bit to be clear or timeout */
> + status = spin_event_timeout(!(in_be32(&ifc->ifc_nand.ncfgr)
> + & IFC_NAND_SRAM_INIT_EN),
> + IFC_TIMEOUT_MSECS, 0);
> + if (!status)
> + dev_err(ctrl->dev, "Timeout waiting for IFC SRAM INIT");
> + }
> +
> + return 0;
> +}
> +#endif /* CONFIG_PM_SLEEP */
Normally we do NAND SRAM init in the NAND driver. Why are you doing it here?
How is SRAM going to be reset on older IFCs?
BTW, I see that Linux is missing SRAM init for IFCs newer than v1.1 -- we're
relying on U-Boot to do so, which we shouldn't be.
-Scott
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2015-10-29 16:21 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-27 11:04 [PATCH 1/2] drivers/memory: Add deep sleep support for IFC Raghav Dogra
2015-10-29 16:21 ` Scott Wood
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 NNTP newsgroup(s).