From c3661adef806869a7e0df884fc621c48436961d4 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Mon, 3 Nov 2014 14:35:53 +0530 Subject: gpu: nvgpu: fix reset clock in gm20b To assert reset on GPU, we store "gpu_ref" clock in platform->clk[0] and use it to assert/deassert reset But for gm20b, "gpu_ref" is no longer resettable. To fix this, add two callbacks in gk20a_platform : .reset_assert and .reset_deassert Also, add a pointer "clk_reset" to store the clock which needs to be reset For gk20a specific implementation, we continue to reset platform->clk[0] For gm20b specific implementation, we first request "gpu_gate" clock, store it and use it to assert reset Bug 1513685 Bug 1517584 Change-Id: I15a583a4a07eb663b442084be8b8c7d0c7c7a142 Signed-off-by: Deepak Nibade --- drivers/gpu/nvgpu/gk20a/gk20a.c | 8 +++- drivers/gpu/nvgpu/gk20a/platform_gk20a.h | 5 +++ drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c | 51 ++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index d411d011..c7d40fcd 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -1671,10 +1671,14 @@ int __gk20a_do_idle(struct platform_device *pdev) else goto fail_timeout; } else { + if (!platform->reset_assert || !platform->reset_deassert) + goto fail_timeout; + pm_runtime_get_sync(&pdev->dev); gk20a_pm_prepare_poweroff(&pdev->dev); - tegra_periph_reset_assert(platform->clk[0]); + platform->reset_assert(pdev); + udelay(10); g->forced_reset = true; @@ -1717,7 +1721,7 @@ int __gk20a_do_unidle(struct platform_device *pdev) struct gk20a_platform *platform = dev_get_drvdata(&pdev->dev); if (g->forced_reset) { - tegra_periph_reset_deassert(platform->clk[0]); + platform->reset_deassert(pdev); gk20a_pm_finalize_poweron(&pdev->dev); pm_runtime_put_sync(&pdev->dev); diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h index 0cc04595..5f7285bf 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h @@ -155,6 +155,11 @@ struct gk20a_platform { */ void (*dump_platform_dependencies)(struct platform_device *dev); + /* Callbacks to assert/deassert GPU reset */ + int (*reset_assert)(struct platform_device *pdev); + int (*reset_deassert)(struct platform_device *pdev); + struct clk *clk_reset; + bool virtual_dev; #ifdef CONFIG_TEGRA_GR_VIRTUALIZATION u64 virt_handle; diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c index e9530844..185d661e 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "gk20a.h" #include "hal_gk20a.h" @@ -321,6 +322,47 @@ err_get_clock: return ret; } +static int gk20a_tegra_reset_assert(struct platform_device *dev) +{ + struct gk20a_platform *platform = gk20a_get_platform(dev); + + if (!platform->clk_reset) + platform->clk_reset = platform->clk[0]; + + tegra_periph_reset_assert(platform->clk_reset); + + return 0; +} + +static int gk20a_tegra_reset_deassert(struct platform_device *dev) +{ + struct gk20a_platform *platform = gk20a_get_platform(dev); + + if (!platform->clk_reset) + return -EINVAL; + + tegra_periph_reset_deassert(platform->clk_reset); + + return 0; +} + +static int gm20b_tegra_reset_assert(struct platform_device *dev) +{ + struct gk20a_platform *platform = gk20a_get_platform(dev); + + if (!platform->clk_reset) { + platform->clk_reset = clk_get(&dev->dev, "gpu_gate"); + if (IS_ERR(platform->clk_reset)) { + gk20a_err(&dev->dev, "fail to get gpu reset clk\n"); + return PTR_ERR(platform->clk_reset); + } + } + + tegra_periph_reset_assert(platform->clk_reset); + + return 0; +} + static void gk20a_tegra_scale_init(struct platform_device *pdev) { struct gk20a_platform *platform = gk20a_get_platform(pdev); @@ -457,6 +499,9 @@ struct gk20a_platform t132_gk20a_tegra_platform = { .busy = gk20a_tegra_busy, .idle = gk20a_tegra_idle, + .reset_assert = gk20a_tegra_reset_assert, + .reset_deassert = gk20a_tegra_reset_deassert, + /* frequency scaling configuration */ .prescale = gk20a_tegra_prescale, .postscale = gk20a_tegra_postscale, @@ -495,6 +540,9 @@ struct gk20a_platform gk20a_tegra_platform = { .busy = gk20a_tegra_busy, .idle = gk20a_tegra_idle, + .reset_assert = gk20a_tegra_reset_assert, + .reset_deassert = gk20a_tegra_reset_deassert, + /* frequency scaling configuration */ .prescale = gk20a_tegra_prescale, .postscale = gk20a_tegra_postscale, @@ -534,6 +582,9 @@ struct gk20a_platform gm20b_tegra_platform = { .busy = gk20a_tegra_busy, .idle = gk20a_tegra_idle, + .reset_assert = gm20b_tegra_reset_assert, + .reset_deassert = gk20a_tegra_reset_deassert, + /* frequency scaling configuration */ .prescale = gk20a_tegra_prescale, .postscale = gk20a_tegra_postscale, -- cgit v1.2.2