summaryrefslogtreecommitdiff
path: root/drivers/mxc
diff options
context:
space:
mode:
authorJoakim Zhang <qiangqing.zhang@nxp.com>2020-04-15 13:36:06 +0800
committerJoakim Zhang <qiangqing.zhang@nxp.com>2020-04-16 12:51:20 +0800
commitd4944201493570c1760a317367570fbde7c27808 (patch)
treebfb0cec8c7800df2e1a20348f16f155dc0703b69 /drivers/mxc
parent4522d69bd94df0dd5e409419801b3ba707431569 (diff)
MLK-23793-2 mxc: emvsim: add runtime pm support
Add runtime pm support in emvsim driver. Reading power mode from debug monitor, EMVSIM_0 was on and with this patch it is lp. Reviewed-by: Fugang Duan <fugang.duan@nxp.com> Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Diffstat (limited to 'drivers/mxc')
-rw-r--r--drivers/mxc/sim/imx_emvsim.c88
1 files changed, 57 insertions, 31 deletions
diff --git a/drivers/mxc/sim/imx_emvsim.c b/drivers/mxc/sim/imx_emvsim.c
index 96822e894f43..4ccac7c62420 100644
--- a/drivers/mxc/sim/imx_emvsim.c
+++ b/drivers/mxc/sim/imx_emvsim.c
@@ -31,6 +31,7 @@
#include <linux/types.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
#define DRIVER_NAME "mxc_emvsim"
@@ -1474,6 +1475,7 @@ copy_data:
static int emvsim_open(struct inode *inode, struct file *file)
{
+ int err;
int errval = SIM_OK;
struct emvsim_t *emvsim = dev_get_drvdata(emvsim_dev.parent);
@@ -1485,12 +1487,11 @@ static int emvsim_open(struct inode *inode, struct file *file)
return errval;
}
- if (!emvsim->open_cnt) {
- clk_prepare_enable(emvsim->ipg);
- clk_prepare_enable(emvsim->clk);
- }
-
emvsim->open_cnt = 1;
+ err = pm_runtime_get_sync(emvsim_dev.parent);
+ if (err < 0)
+ return err;
+
init_completion(&emvsim->xfer_done);
errval = emvsim_reset_module(emvsim);
emvsim_data_reset(emvsim);
@@ -1510,11 +1511,7 @@ static int emvsim_release(struct inode *inode, struct file *file)
if (emvsim->present != SIM_PRESENT_REMOVED)
emvsim_deactivate(emvsim);
- if (emvsim->open_cnt) {
- clk_disable_unprepare(emvsim->clk);
- clk_disable_unprepare(emvsim->ipg);
- }
-
+ pm_runtime_put(emvsim_dev.parent);
emvsim->open_cnt = 0;
return 0;
@@ -1593,7 +1590,6 @@ static int emvsim_probe(struct platform_device *pdev)
return -EINVAL;
emvsim->clk_rate = FCLK_FREQ;
- emvsim->open_cnt = 0;
emvsim->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!emvsim->res) {
@@ -1642,7 +1638,22 @@ static int emvsim_probe(struct platform_device *pdev)
if (ret)
return ret;
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
ret = misc_register(&emvsim_dev);
+
+ emvsim->open_cnt = 1;
+ clk_prepare_enable(emvsim->ipg);
+ clk_prepare_enable(emvsim->clk);
+
+ /* Let pm_runtime_put() disable the clocks.
+ * If CONFIG_PM is not enabled, the clocks will stay powered.
+ */
+ pm_runtime_put(&pdev->dev);
+ emvsim->open_cnt = 0;
+
dev_info(&pdev->dev, "emvsim register %s\n", ret ? "fail" : "success");
return ret;
@@ -1650,62 +1661,77 @@ static int emvsim_probe(struct platform_device *pdev)
static int emvsim_remove(struct platform_device *pdev)
{
- struct emvsim_t *emvsim = platform_get_drvdata(pdev);
-
- if (emvsim->open_cnt) {
- clk_disable_unprepare(emvsim->clk);
- clk_disable_unprepare(emvsim->ipg);
- }
+ pm_runtime_disable(&pdev->dev);
misc_deregister(&emvsim_dev);
return 0;
}
-#ifdef CONFIG_PM
-static int emvsim_suspend(struct platform_device *pdev, pm_message_t state)
+static int __maybe_unused emvsim_suspend(struct device *dev)
{
- struct emvsim_t *emvsim = platform_get_drvdata(pdev);
+ int err;
+
+ err = pm_runtime_force_suspend(dev);
+ if (err)
+ return err;
+
+ pinctrl_pm_select_sleep_state(dev);
+
+ return 0;
+}
+
+static int __maybe_unused emvsim_runtime_suspend(struct device *dev)
+{
+ struct emvsim_t *emvsim = dev_get_drvdata(dev);
if (emvsim->open_cnt) {
clk_disable_unprepare(emvsim->clk);
clk_disable_unprepare(emvsim->ipg);
}
- pinctrl_pm_select_sleep_state(&pdev->dev);
+ return 0;
+}
+
+static int __maybe_unused emvsim_resume(struct device *dev)
+{
+ int err;
+
+ err = pm_runtime_force_resume(dev);
+ if (err)
+ return err;
+
+ pinctrl_pm_select_default_state(dev);
return 0;
}
-static int emvsim_resume(struct platform_device *pdev)
+static int __maybe_unused emvsim_runtime_resume(struct device *dev)
{
- struct emvsim_t *emvsim = platform_get_drvdata(pdev);
+ struct emvsim_t *emvsim = dev_get_drvdata(dev);
if (emvsim->open_cnt) {
clk_prepare_enable(emvsim->ipg);
clk_prepare_enable(emvsim->clk);
}
- pinctrl_pm_select_default_state(&pdev->dev);
-
return 0;
}
-#else
-#define emvsim_suspend NULL
-#define emvsim_resume NULL
-#endif
+static const struct dev_pm_ops emvsim_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(emvsim_suspend, emvsim_resume)
+ SET_RUNTIME_PM_OPS(emvsim_runtime_suspend, emvsim_runtime_resume, NULL)
+};
static struct platform_driver emvsim_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
+ .pm = &emvsim_pm_ops,
.of_match_table = emvsim_imx_dt_ids,
},
.probe = emvsim_probe,
.remove = emvsim_remove,
- .suspend = emvsim_suspend,
- .resume = emvsim_resume,
};
static int __init emvsim_drv_init(void)