mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 10:34:43 +03:00
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 <sumsingh@nvidia.com> Reviewed-on: http://git-master/r/668973 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
This commit is contained in:
committed by
Dan Willemsen
parent
182730599e
commit
86637dcef9
@@ -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 = &platform->g->pd;
|
||||
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 = 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -311,7 +311,17 @@ static int vgpu_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 gk20a_domain_data *vgpu_pd_data;
|
||||
struct generic_pm_domain *domain;
|
||||
|
||||
vgpu_pd_data = (struct gk20a_domain_data *)kzalloc
|
||||
(sizeof(struct gk20a_domain_data), GFP_KERNEL);
|
||||
|
||||
if (!vgpu_pd_data)
|
||||
return -ENOMEM;
|
||||
|
||||
domain = &vgpu_pd_data->gpd;
|
||||
vgpu_pd_data->gk20a = platform->g;
|
||||
|
||||
domain->name = "gpu";
|
||||
|
||||
@@ -432,11 +442,16 @@ int vgpu_probe(struct platform_device *dev)
|
||||
int vgpu_remove(struct platform_device *dev)
|
||||
{
|
||||
struct gk20a *g = get_gk20a(dev);
|
||||
struct gk20a_domain_data *vgpu_gpd;
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
if (g->remove_support)
|
||||
g->remove_support(dev);
|
||||
|
||||
vgpu_gpd = container_of(&g, struct gk20a_domain_data, gk20a);
|
||||
vgpu_gpd->gk20a = NULL;
|
||||
kfree(vgpu_gpd);
|
||||
|
||||
vgpu_comm_deinit();
|
||||
gk20a_user_deinit(dev);
|
||||
gk20a_get_platform(dev)->g = NULL;
|
||||
|
||||
Reference in New Issue
Block a user