[PATCH v3 1/1] misc: sram: add dev_pm_ops to support module power gate
Shenwei Wang
Shenwei.Wang at freescale.com
Thu Aug 20 07:48:43 PDT 2015
3rd Ping.
Shenwei
> -----Original Message-----
> From: linux-arm-kernel [mailto:linux-arm-kernel-bounces at lists.infradead.org] On
> Behalf Of Shenwei Wang
> Sent: 2015年8月12日 10:47
> To: gregkh at linuxfoundation.org; arnd at arndb.de
> Cc: Huang Yongcai-B20788; linux-arm-kernel at lists.infradead.org
> Subject: RE: [PATCH v3 1/1] misc: sram: add dev_pm_ops to support module
> power gate
>
> 2nd Ping.
>
> Regards,
> Shenwei
>
> > -----Original Message-----
> > From: linux-arm-kernel
> > [mailto:linux-arm-kernel-bounces at lists.infradead.org] On Behalf Of
> > Shenwei Wang
> > Sent: 2015年7月30日 11:11
> > To: gregkh at linuxfoundation.org; arnd at arndb.de
> > Cc: Huang Yongcai-B20788; linux-arm-kernel at lists.infradead.org
> > Subject: [PATCH v3 1/1] misc: sram: add dev_pm_ops to support module
> > power gate
> >
> > When system goes into low power states like SUSPEND_MEM and
> > HIBERNATION, the hardware IP block may be powered off to reduce the power
> consumption.
> > This power down will lost all the data inside the ram. This patch
> > added the dev_pm_ops and implemented two callbacks: suspend_noirq and
> > resume_noirq, which will save the data in the on-chip-ram right before
> > power down and restore it after system resumes.
> >
> > A new property string named "can-power-gate" is added to the
> > devicetree bindings too.
> >
> > Signed-off-by: Shenwei Wang <shenwei.wang at freescale.com>
> > Signed-off-by: Anson Huang <b20788 at freescale.com>
> > ---
> > Change log:
> >
> > PATCH v3
> > Removed the unnecessary clk_enable/clk_disable.
> >
> > PATCH v2
> > Use vmalloc to allocate the SRAM backup memory.
> > Code clean up.
> >
> > Documentation/devicetree/bindings/misc/sram.txt | 2 ++
> > drivers/misc/sram.c | 42
> > +++++++++++++++++++++++++
> > 2 files changed, 44 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/misc/sram.txt
> > b/Documentation/devicetree/bindings/misc/sram.txt
> > index 36cbe5a..1170086 100644
> > --- a/Documentation/devicetree/bindings/misc/sram.txt
> > +++ b/Documentation/devicetree/bindings/misc/sram.txt
> > @@ -33,6 +33,8 @@ Optional properties in the area nodes:
> >
> > - compatible : standard definition, should contain a vendor specific string
> > in the form <vendor>,[<device>-]<usage>
> > +- can-power-gate: a property to tell the driver that the sram can support
> > + power gate
> >
> > Example:
> >
> > diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index
> > 15c33cc..db9f1fa
> > 100644
> > --- a/drivers/misc/sram.c
> > +++ b/drivers/misc/sram.c
> > @@ -30,7 +30,9 @@
> >
> > struct sram_dev {
> > struct device *dev;
> > + void *power_off_save;
> > void __iomem *virt_base;
> > + u32 size;
> >
> > struct gen_pool *pool;
> > struct clk *clk;
> > @@ -156,6 +158,33 @@ static int sram_reserve_regions(struct sram_dev
> > *sram, struct resource *res)
> > return ret;
> > }
> >
> > +static int sram_suspend_noirq(struct device *dev) {
> > + struct platform_device *pdev = to_platform_device(dev);
> > + struct sram_dev *sram = platform_get_drvdata(pdev);
> > +
> > + if (!sram->power_off_save)
> > + return 0;
> > +
> > + /* Save necessary regs */
> > + memcpy(sram->power_off_save, sram->virt_base, sram->size);
> > +
> > + return 0;
> > +}
> > +
> > +static int sram_resume_noirq(struct device *dev) {
> > + struct platform_device *pdev = to_platform_device(dev);
> > + struct sram_dev *sram = platform_get_drvdata(pdev);
> > +
> > + if (!sram->power_off_save)
> > + return 0;
> > +
> > + memcpy(sram->virt_base, sram->power_off_save, sram->size);
> > +
> > + return 0;
> > +}
> > +
> > static int sram_probe(struct platform_device *pdev) {
> > struct sram_dev *sram;
> > @@ -176,6 +205,7 @@ static int sram_probe(struct platform_device *pdev)
> > }
> >
> > size = resource_size(res);
> > + sram->size = size;
> >
> > if (!devm_request_mem_region(sram->dev, res->start, size, pdev->name)) {
> > dev_err(sram->dev, "could not request region for resource\n"); @@
> > -203,6 +233,9 @@ static int sram_probe(struct platform_device *pdev)
> >
> > platform_set_drvdata(pdev, sram);
> >
> > + if (of_property_read_bool(pdev->dev.of_node, "can-power-gate"))
> > + sram->power_off_save = vmalloc(size);
> > +
> > dev_dbg(sram->dev, "SRAM pool: %zu KiB @ 0x%p\n",
> > gen_pool_size(sram->pool) / 1024, sram->virt_base);
> >
> > @@ -219,6 +252,9 @@ static int sram_remove(struct platform_device *pdev)
> > if (sram->clk)
> > clk_disable_unprepare(sram->clk);
> >
> > + if (sram->power_off_save)
> > + vfree(sram->power_off_save);
> > +
> > return 0;
> > }
> >
> > @@ -229,10 +265,16 @@ static const struct of_device_id sram_dt_ids[] =
> > { }; #endif
> >
> > +static const struct dev_pm_ops sram_pm_ops = {
> > + .suspend_noirq = sram_suspend_noirq,
> > + .resume_noirq = sram_resume_noirq,
> > +};
> > +
> > static struct platform_driver sram_driver = {
> > .driver = {
> > .name = "sram",
> > .of_match_table = of_match_ptr(sram_dt_ids),
> > + .pm = &sram_pm_ops,
> > },
> > .probe = sram_probe,
> > .remove = sram_remove,
> > --
> > 2.5.0.rc2
> >
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
More information about the linux-arm-kernel
mailing list