diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 355b20390..fa6e0cce5 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -1604,16 +1604,30 @@ int gk20a_busy(struct platform_device *pdev) { int ret = 0; struct gk20a *g = get_gk20a(pdev); + struct gk20a_platform *platform = gk20a_get_platform(pdev); down_read(&g->busy_lock); #ifdef CONFIG_PM_RUNTIME + if (platform->busy) { + ret = platform->busy(pdev); + if (ret < 0) { + dev_err(&pdev->dev, "%s: failed to poweron platform dependency\n", + __func__); + goto fail; + } + } + ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) + if (ret < 0) { pm_runtime_put_noidle(&pdev->dev); + if (platform->idle) + platform->idle(pdev); + } #endif gk20a_scale_notify_busy(pdev); +fail: up_read(&g->busy_lock); return ret < 0 ? ret : 0; @@ -1621,11 +1635,15 @@ int gk20a_busy(struct platform_device *pdev) void gk20a_idle(struct platform_device *pdev) { + struct gk20a_platform *platform = gk20a_get_platform(pdev); #ifdef CONFIG_PM_RUNTIME if (atomic_read(&pdev->dev.power.usage_count) == 1) gk20a_scale_notify_idle(pdev); pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_sync_autosuspend(&pdev->dev); + + if (platform->idle) + platform->idle(pdev); #else gk20a_scale_notify_idle(pdev); #endif diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h index 76e9cf6c5..6dd0c0db8 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h @@ -94,6 +94,12 @@ struct gk20a_platform { */ int (*late_probe)(struct platform_device *dev); + /* Poweron platform dependencies */ + int (*busy)(struct platform_device *dev); + + /* Powerdown platform dependencies */ + void (*idle)(struct platform_device *dev); + /* This function is called to allocate secure memory (memory that the * CPU cannot see). The function should fill the context buffer * descriptor (especially fields destroy, sgt, size). diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c index 148496dd5..f234fdec1 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c @@ -449,6 +449,25 @@ static void gk20a_tegra_debug_dump(struct platform_device *pdev) nvhost_debug_dump_device(g->host1x_dev); } +static int gk20a_tegra_busy(struct platform_device *dev) +{ + struct gk20a_platform *platform = gk20a_get_platform(dev); + struct gk20a *g = platform->g; + + if (g->host1x_dev) + return nvhost_module_busy_ext(g->host1x_dev); + return 0; +} + +static void gk20a_tegra_idle(struct platform_device *dev) +{ + struct gk20a_platform *platform = gk20a_get_platform(dev); + struct gk20a *g = platform->g; + + if (g->host1x_dev) + nvhost_module_idle_ext(g->host1x_dev); +} + static int gk20a_tegra_probe(struct platform_device *dev) { struct gk20a_platform *platform = gk20a_get_platform(dev); @@ -554,6 +573,9 @@ struct gk20a_platform t132_gk20a_tegra_platform = { .unrailgate = gk20a_tegra_unrailgate, .is_railgated = gk20a_tegra_is_railgated, + .busy = gk20a_tegra_busy, + .idle = gk20a_tegra_idle, + /* frequency scaling configuration */ .prescale = gk20a_tegra_prescale, .postscale = gk20a_tegra_postscale, @@ -587,6 +609,9 @@ struct gk20a_platform gk20a_tegra_platform = { .unrailgate = gk20a_tegra_unrailgate, .is_railgated = gk20a_tegra_is_railgated, + .busy = gk20a_tegra_busy, + .idle = gk20a_tegra_idle, + /* frequency scaling configuration */ .prescale = gk20a_tegra_prescale, .postscale = gk20a_tegra_postscale, @@ -618,6 +643,9 @@ struct gk20a_platform gm20b_tegra_platform = { /* power management callbacks */ .suspend = gk20a_tegra_suspend, + .busy = gk20a_tegra_busy, + .idle = gk20a_tegra_idle, + /* frequency scaling configuration */ .prescale = gk20a_tegra_prescale, .postscale = gk20a_tegra_postscale,