From 86637dcef9a978d21bae9978ce3f6863a45fc973 Mon Sep 17 00:00:00 2001 From: Sumit Singh Date: Sun, 4 Jan 2015 13:30:33 +0530 Subject: gpu: nvgpu: Add DT support for gpu power-domain First, defining a new structure to support gk20a power domain. Then making necessary modifications to add so as to add DT support for gpu power-domain. bug 200070810 Change-Id: I29e1c24b181e14743d3969103abfd1882d171f07 Signed-off-by: Sumit Singh Reviewed-on: http://git-master/r/668973 Reviewed-by: Bharat Nihalani --- drivers/gpu/nvgpu/gk20a/gk20a.c | 137 +++++++++++++++++++++-- drivers/gpu/nvgpu/gk20a/gk20a.h | 7 +- drivers/gpu/nvgpu/gk20a/platform_gk20a_generic.c | 10 +- drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c | 8 +- 4 files changed, 141 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a') diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index b7357c6b..67aa49c6 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -1134,10 +1134,11 @@ static int _gk20a_pm_railgate(struct platform_device *pdev) static int gk20a_pm_railgate(struct generic_pm_domain *domain) { - struct gk20a *g = container_of(domain, struct gk20a, pd); - struct gk20a_platform *platform = platform_get_drvdata(g->dev); + struct gk20a_domain_data *gk20a_domain = container_of(domain, + struct gk20a_domain_data, gpd); + struct gk20a *g = gk20a_domain->gk20a; - return _gk20a_pm_railgate(platform->g->dev); + return _gk20a_pm_railgate(g->dev); } static int _gk20a_pm_unrailgate(struct platform_device *pdev) @@ -1156,12 +1157,12 @@ static int _gk20a_pm_unrailgate(struct platform_device *pdev) static int gk20a_pm_unrailgate(struct generic_pm_domain *domain) { - struct gk20a *g = container_of(domain, struct gk20a, pd); - struct gk20a_platform *platform = platform_get_drvdata(g->dev); - + struct gk20a_domain_data *gk20a_domain = container_of(domain, + struct gk20a_domain_data, gpd); + struct gk20a *g = gk20a_domain->gk20a; trace_gk20a_pm_unrailgate(dev_name(&g->dev->dev)); - return _gk20a_pm_unrailgate(platform->g->dev); + return _gk20a_pm_unrailgate(g->dev); } #if 0 @@ -1191,12 +1192,41 @@ static int gk20a_pm_resume(struct device *dev) } #endif +#ifdef CONFIG_PM_GENERIC_DOMAINS_OF +static int gk20a_pm_initialise_domain(struct platform_device *pdev) +{ + struct gk20a_platform *platform = platform_get_drvdata(pdev); + struct dev_power_governor *pm_domain_gov = NULL; + struct generic_pm_domain *domain = dev_to_genpd(&pdev->dev); + +#ifdef CONFIG_PM_RUNTIME + if (!platform->can_railgate) + pm_domain_gov = &pm_domain_always_on_gov; +#endif + domain->gov = pm_domain_gov; + + if (platform->railgate_delay) + pm_genpd_set_poweroff_delay(domain, platform->railgate_delay); + + device_set_wakeup_capable(&pdev->dev, 0); + return 0; +} + +#else static int gk20a_pm_initialise_domain(struct platform_device *pdev) { struct gk20a_platform *platform = platform_get_drvdata(pdev); struct dev_power_governor *pm_domain_gov = NULL; - struct generic_pm_domain *domain = &platform->g->pd; + struct generic_pm_domain *domain = NULL; int ret = 0; + struct gk20a_domain_data *gpu_gpd_data = (struct gk20a_domain_data *) + kzalloc(sizeof(struct gk20a_domain_data), GFP_KERNEL); + + if (!gpu_gpd_data) + return -ENOMEM; + + gpu_gpd_data->gk20a = platform->g; + domain = &gpu_gpd_data->gpd; domain->name = "gpu"; @@ -1227,6 +1257,7 @@ static int gk20a_pm_initialise_domain(struct platform_device *pdev) return ret; } +#endif static int gk20a_pm_init(struct platform_device *dev) { @@ -1280,12 +1311,21 @@ static int gk20a_secure_page_alloc(struct platform_device *pdev) return err; } +static struct of_device_id tegra_gpu_domain_match[] = { + {.compatible = "nvidia,tegra210-gpu-pd"}, + {}, +}; + static int gk20a_probe(struct platform_device *dev) { struct gk20a *gk20a; int err; struct gk20a_platform *platform = NULL; +#ifdef CONFIG_PM_GENERIC_DOMAINS_OF + struct gk20a_domain_data *gk20a_domain; +#endif + if (dev->dev.of_node) { const struct of_device_id *match; @@ -1313,6 +1353,12 @@ static int gk20a_probe(struct platform_device *dev) return -ENOMEM; } +#ifdef CONFIG_PM_GENERIC_DOMAINS_OF + gk20a_domain = container_of(dev_to_genpd(&dev->dev), + struct gk20a_domain_data, gpd); + gk20a_domain->gk20a = gk20a; +#endif + set_gk20a(dev, gk20a); gk20a->dev = dev; @@ -1451,6 +1497,7 @@ static int __exit gk20a_remove(struct platform_device *dev) { struct gk20a *g = get_gk20a(dev); struct gk20a_platform *platform = gk20a_get_platform(dev); + struct gk20a_domain_data *gk20a_gpd; gk20a_dbg_fn(""); @@ -1481,6 +1528,10 @@ static int __exit gk20a_remove(struct platform_device *dev) platform->secure_buffer.destroy(dev, &platform->secure_buffer); + gk20a_gpd = container_of(&g, struct gk20a_domain_data, gk20a); + gk20a_gpd->gk20a = NULL; + kfree(gk20a_gpd); + if (pm_runtime_enabled(&dev->dev)) pm_runtime_disable(&dev->dev); else @@ -1513,8 +1564,78 @@ static struct platform_driver gk20a_driver = { } }; +#ifdef CONFIG_PM_GENERIC_DOMAINS_OF + + +static int _gk20a_init_domain(struct device_node *np, + struct generic_pm_domain *gpd) +{ + bool is_off = false; + + gpd->name = (char *)np->name; + + if (of_property_read_bool(np, "is_off")) + is_off = true; + + pm_genpd_init(gpd, NULL, is_off); + + gpd->power_on = gk20a_pm_unrailgate; + gpd->power_off = gk20a_pm_railgate; + gpd->dev_ops.start = gk20a_pm_enable_clk; + gpd->dev_ops.stop = gk20a_pm_disable_clk; + gpd->dev_ops.save_state = gk20a_pm_prepare_poweroff; + gpd->dev_ops.restore_state = gk20a_pm_finalize_poweron; +#warning domain suspend/resume ops have been removed upstream +#if 0 + gpd->dev_ops.suspend = gk20a_pm_suspend; + gpd->dev_ops.resume = gk20a_pm_resume; +#endif + + of_genpd_add_provider_simple(np, gpd); + gpd->of_node = of_node_get(np); + + genpd_pm_subdomain_attach(gpd); + return 0; +} + +static int gk20a_domain_init(struct of_device_id *matches) +{ + int ret = 0; + struct device_node *np; + const struct of_device_id *match; + struct gk20a_domain_data *gk20a_domain; + + np = of_find_matching_node(NULL, matches); + if (!np) + return -ENOENT; + + match = of_match_node(matches, np); + gk20a_domain = (struct gk20a_domain_data *)kzalloc + (sizeof(struct gk20a_domain_data), GFP_KERNEL); + if (!gk20a_domain) + return -ENOMEM; + + ret = _gk20a_init_domain(np, &gk20a_domain->gpd); + + return ret; +} +#else +static int gk20a_domain_init(struct of_device_id *matches) +{ + return 0; +} +#endif + + static int __init gk20a_init(void) { + + int ret; + + ret = gk20a_domain_init(tegra_gpu_domain_match); + if (ret) + return ret; + return platform_driver_register(&gk20a_driver); } diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 4fac3cc5..b9bdc6e6 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -504,8 +504,6 @@ struct gk20a { u32 max_ltc_count; u32 ltc_count; - struct generic_pm_domain pd; - struct devfreq *devfreq; struct gk20a_scale_profile *scale_profile; @@ -556,6 +554,11 @@ struct gk20a_cyclestate_buffer_elem { u64 data; }; +struct gk20a_domain_data { + struct generic_pm_domain gpd; + struct gk20a *gk20a; +}; + /* debug accessories */ #ifdef CONFIG_DEBUG_FS diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a_generic.c b/drivers/gpu/nvgpu/gk20a/platform_gk20a_generic.c index ee176b8b..78132320 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a_generic.c +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a_generic.c @@ -112,19 +112,19 @@ static int gk20a_generic_probe(struct platform_device *dev) static int gk20a_generic_late_probe(struct platform_device *dev) { - struct gk20a_platform *platform = gk20a_get_platform(dev); + struct generic_pm_domain *gpd = dev_to_genpd(&dev->dev); - /* Make gk20a power domain a subdomain of mc */ - tegra_pd_add_sd(&platform->g->pd); + /* Make gk20a power domain a subdomain of host1x */ + tegra_pd_add_sd(gpd); return 0; } static int gk20a_generic_remove(struct platform_device *dev) { - struct gk20a_platform *platform = gk20a_get_platform(dev); + struct generic_pm_domain *gpd = dev_to_genpd(&dev->dev); - tegra_pd_remove_sd(&platform->g->pd); + tegra_pd_remove_sd(gpd); return 0; } diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c index 313962a1..8609e3ae 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c @@ -472,10 +472,8 @@ static int gk20a_tegra_probe(struct platform_device *dev) static int gk20a_tegra_late_probe(struct platform_device *dev) { - struct gk20a_platform *platform = gk20a_get_platform(dev); - /* Make gk20a power domain a subdomain of host1x */ - nvhost_register_client_domain(&platform->g->pd); + nvhost_register_client_domain(dev_to_genpd(&dev->dev)); /* Initialise tegra specific scaling quirks */ gk20a_tegra_scale_init(dev); @@ -485,10 +483,8 @@ static int gk20a_tegra_late_probe(struct platform_device *dev) static int gk20a_tegra_remove(struct platform_device *dev) { - struct gk20a_platform *platform = gk20a_get_platform(dev); - /* remove gk20a power subdomain from host1x */ - nvhost_unregister_client_domain(&platform->g->pd); + nvhost_unregister_client_domain(dev_to_genpd(&dev->dev)); /* deinitialise tegra specific scaling quirks */ gk20a_tegra_scale_exit(dev); -- cgit v1.2.2