From fec60b6e6e299151d446f4bccc5fd64a23b704d2 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Tue, 8 Jul 2014 18:00:18 +0530 Subject: gpu: nvgpu: force idle if railgate not supported Add a way to force idle and reset the GPU in case where GPU rail gating is not supported (i.e. platform->can_railgate = false) In this case, we follow below sequence : - once GPU is idle, get runtime reference which enables the clocks - call prepare_poweroff() to save the state explicitly - perform explicit reset assert/deassert - call finalize_poweron() to restore the state - drop the runtime reference taken earlier Bug 1525284 Change-Id: Id5f3ec152093acd585631dfbf785d8e0561f9048 Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/435620 GVS: Gerrit_Virtual_Submit Reviewed-by: Arto Merilainen Tested-by: Arto Merilainen --- drivers/gpu/nvgpu/gk20a/gk20a.c | 50 ++++++++++++++++++++++++++++------------- drivers/gpu/nvgpu/gk20a/gk20a.h | 1 + 2 files changed, 36 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index cd104580..c69df460 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -1743,9 +1743,6 @@ int gk20a_do_idle(void) int ref_cnt; bool is_railgated; - if (!platform->can_railgate) - return -ENOSYS; - /* acquire busy lock to block other busy() calls */ down_write(&g->busy_lock); @@ -1772,25 +1769,39 @@ int gk20a_do_idle(void) /* * if GPU is now idle, we will have only one ref count - * drop this ref which will rail gate the GPU + * drop this ref which will rail gate the GPU (if GPU + * railgate is supported) + * if GPU railgate is not supported then we need to + * explicitly reset it */ pm_runtime_put_sync(&pdev->dev); - /* add sufficient delay to allow GPU to rail gate */ - msleep(platform->railgate_delay); + if (platform->can_railgate) { + /* add sufficient delay to allow GPU to rail gate */ + msleep(platform->railgate_delay); - timeout = jiffies + msecs_to_jiffies(GK20A_WAIT_FOR_IDLE_MS); + timeout = jiffies + msecs_to_jiffies(GK20A_WAIT_FOR_IDLE_MS); - /* check in loop if GPU is railgated or not */ - do { - msleep(1); - is_railgated = platform->is_railgated(pdev); - } while (!is_railgated && time_before(jiffies, timeout)); + /* check in loop if GPU is railgated or not */ + do { + msleep(1); + is_railgated = platform->is_railgated(pdev); + } while (!is_railgated && time_before(jiffies, timeout)); + + if (is_railgated) + return 0; + else + goto fail_timeout; + } else { + pm_runtime_get_sync(&pdev->dev); + gk20a_pm_prepare_poweroff(&pdev->dev); + + tegra_periph_reset_assert(platform->clk[0]); + udelay(10); - if (is_railgated) + g->forced_reset = true; return 0; - else - goto fail_timeout; + } fail: pm_runtime_put_noidle(&pdev->dev); @@ -1811,6 +1822,15 @@ int gk20a_do_unidle(void) struct gk20a *g = get_gk20a(pdev); struct gk20a_platform *platform = dev_get_drvdata(&pdev->dev); + if (g->forced_reset) { + tegra_periph_reset_deassert(platform->clk[0]); + + gk20a_pm_finalize_poweron(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); + + g->forced_reset = false; + } + /* release the lock and open up all other busy() calls */ mutex_unlock(&platform->railgate_lock); up_write(&g->busy_lock); diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 55bc6b20..774e4e85 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -271,6 +271,7 @@ struct gk20a { bool elpg_enabled; bool aelpg_enabled; bool forced_idle; + bool forced_reset; #ifdef CONFIG_DEBUG_FS spinlock_t debugfs_lock; -- cgit v1.2.2