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>
This commit is contained in:
@ -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)
|
||||
|
||||
Reference in New Issue
Block a user