@@ -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:
@@ -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,37 @@ 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 */
+ clk_enable(sram->clk);
+ memcpy(sram->power_off_save, sram->virt_base, sram->size);
+ clk_disable(sram->clk);
+
+ 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;
+
+ clk_enable(sram->clk);
+ memcpy(sram->virt_base, sram->power_off_save, sram->size);
+ clk_disable(sram->clk);
+
+ return 0;
+}
+
static int sram_probe(struct platform_device *pdev)
{
struct sram_dev *sram;
@@ -176,6 +209,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 +237,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 +256,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 +269,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,