From 63945d51490f16aede6d635e785faf56521e5e4a Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Tue, 21 Apr 2020 21:35:50 +0800 Subject: drm/lima: add pm resume/suspend ops Add driver pm system and runtime hardware resume/suspend ops. Note this won't enable runtime pm of the device yet. v2: Do clock and power gating when suspend/resume. Tested-by: Bhushan Shah Reviewed-by: Vasily Khoruzhick Signed-off-by: Qiang Yu Link: https://patchwork.freedesktop.org/patch/msgid/20200421133551.31481-10-yuq825@gmail.com --- drivers/gpu/drm/lima/lima_device.c | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'drivers/gpu/drm/lima/lima_device.c') diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c index 1d9b7f415da1..65fdca366e41 100644 --- a/drivers/gpu/drm/lima/lima_device.c +++ b/drivers/gpu/drm/lima/lima_device.c @@ -247,6 +247,27 @@ static void lima_fini_ip(struct lima_device *ldev, int index) desc->fini(ip); } +static int lima_resume_ip(struct lima_device *ldev, int index) +{ + struct lima_ip_desc *desc = lima_ip_desc + index; + struct lima_ip *ip = ldev->ip + index; + int ret = 0; + + if (ip->present) + ret = desc->resume(ip); + + return ret; +} + +static void lima_suspend_ip(struct lima_device *ldev, int index) +{ + struct lima_ip_desc *desc = lima_ip_desc + index; + struct lima_ip *ip = ldev->ip + index; + + if (ip->present) + desc->suspend(ip); +} + static int lima_init_gp_pipe(struct lima_device *dev) { struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp; @@ -441,3 +462,72 @@ void lima_device_fini(struct lima_device *ldev) lima_clk_fini(ldev); } + +int lima_device_resume(struct device *dev) +{ + struct lima_device *ldev = dev_get_drvdata(dev); + int i, err; + + err = lima_clk_enable(ldev); + if (err) { + dev_err(dev, "resume clk fail %d\n", err); + return err; + } + + err = lima_regulator_enable(ldev); + if (err) { + dev_err(dev, "resume regulator fail %d\n", err); + goto err_out0; + } + + for (i = 0; i < lima_ip_num; i++) { + err = lima_resume_ip(ldev, i); + if (err) { + dev_err(dev, "resume ip %d fail\n", i); + goto err_out1; + } + } + + err = lima_devfreq_resume(&ldev->devfreq); + if (err) { + dev_err(dev, "devfreq resume fail\n"); + goto err_out1; + } + + return 0; + +err_out1: + while (--i >= 0) + lima_suspend_ip(ldev, i); + lima_regulator_disable(ldev); +err_out0: + lima_clk_disable(ldev); + return err; +} + +int lima_device_suspend(struct device *dev) +{ + struct lima_device *ldev = dev_get_drvdata(dev); + int i, err; + + /* check any task running */ + for (i = 0; i < lima_pipe_num; i++) { + if (atomic_read(&ldev->pipe[i].base.hw_rq_count)) + return -EBUSY; + } + + err = lima_devfreq_suspend(&ldev->devfreq); + if (err) { + dev_err(dev, "devfreq suspend fail\n"); + return err; + } + + for (i = lima_ip_num - 1; i >= 0; i--) + lima_suspend_ip(ldev, i); + + lima_regulator_disable(ldev); + + lima_clk_disable(ldev); + + return 0; +} -- cgit v1.2.3