diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 137 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 7 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/platform_gk20a_generic.c | 10 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c | 8 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/vgpu.c | 17 |
5 files changed, 157 insertions, 22 deletions
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) | |||
1134 | 1134 | ||
1135 | static int gk20a_pm_railgate(struct generic_pm_domain *domain) | 1135 | static int gk20a_pm_railgate(struct generic_pm_domain *domain) |
1136 | { | 1136 | { |
1137 | struct gk20a *g = container_of(domain, struct gk20a, pd); | 1137 | struct gk20a_domain_data *gk20a_domain = container_of(domain, |
1138 | struct gk20a_platform *platform = platform_get_drvdata(g->dev); | 1138 | struct gk20a_domain_data, gpd); |
1139 | struct gk20a *g = gk20a_domain->gk20a; | ||
1139 | 1140 | ||
1140 | return _gk20a_pm_railgate(platform->g->dev); | 1141 | return _gk20a_pm_railgate(g->dev); |
1141 | } | 1142 | } |
1142 | 1143 | ||
1143 | static int _gk20a_pm_unrailgate(struct platform_device *pdev) | 1144 | static int _gk20a_pm_unrailgate(struct platform_device *pdev) |
@@ -1156,12 +1157,12 @@ static int _gk20a_pm_unrailgate(struct platform_device *pdev) | |||
1156 | 1157 | ||
1157 | static int gk20a_pm_unrailgate(struct generic_pm_domain *domain) | 1158 | static int gk20a_pm_unrailgate(struct generic_pm_domain *domain) |
1158 | { | 1159 | { |
1159 | struct gk20a *g = container_of(domain, struct gk20a, pd); | 1160 | struct gk20a_domain_data *gk20a_domain = container_of(domain, |
1160 | struct gk20a_platform *platform = platform_get_drvdata(g->dev); | 1161 | struct gk20a_domain_data, gpd); |
1161 | 1162 | struct gk20a *g = gk20a_domain->gk20a; | |
1162 | trace_gk20a_pm_unrailgate(dev_name(&g->dev->dev)); | 1163 | trace_gk20a_pm_unrailgate(dev_name(&g->dev->dev)); |
1163 | 1164 | ||
1164 | return _gk20a_pm_unrailgate(platform->g->dev); | 1165 | return _gk20a_pm_unrailgate(g->dev); |
1165 | } | 1166 | } |
1166 | 1167 | ||
1167 | #if 0 | 1168 | #if 0 |
@@ -1191,12 +1192,41 @@ static int gk20a_pm_resume(struct device *dev) | |||
1191 | } | 1192 | } |
1192 | #endif | 1193 | #endif |
1193 | 1194 | ||
1195 | #ifdef CONFIG_PM_GENERIC_DOMAINS_OF | ||
1196 | static int gk20a_pm_initialise_domain(struct platform_device *pdev) | ||
1197 | { | ||
1198 | struct gk20a_platform *platform = platform_get_drvdata(pdev); | ||
1199 | struct dev_power_governor *pm_domain_gov = NULL; | ||
1200 | struct generic_pm_domain *domain = dev_to_genpd(&pdev->dev); | ||
1201 | |||
1202 | #ifdef CONFIG_PM_RUNTIME | ||
1203 | if (!platform->can_railgate) | ||
1204 | pm_domain_gov = &pm_domain_always_on_gov; | ||
1205 | #endif | ||
1206 | domain->gov = pm_domain_gov; | ||
1207 | |||
1208 | if (platform->railgate_delay) | ||
1209 | pm_genpd_set_poweroff_delay(domain, platform->railgate_delay); | ||
1210 | |||
1211 | device_set_wakeup_capable(&pdev->dev, 0); | ||
1212 | return 0; | ||
1213 | } | ||
1214 | |||
1215 | #else | ||
1194 | static int gk20a_pm_initialise_domain(struct platform_device *pdev) | 1216 | static int gk20a_pm_initialise_domain(struct platform_device *pdev) |
1195 | { | 1217 | { |
1196 | struct gk20a_platform *platform = platform_get_drvdata(pdev); | 1218 | struct gk20a_platform *platform = platform_get_drvdata(pdev); |
1197 | struct dev_power_governor *pm_domain_gov = NULL; | 1219 | struct dev_power_governor *pm_domain_gov = NULL; |
1198 | struct generic_pm_domain *domain = &platform->g->pd; | 1220 | struct generic_pm_domain *domain = NULL; |
1199 | int ret = 0; | 1221 | int ret = 0; |
1222 | struct gk20a_domain_data *gpu_gpd_data = (struct gk20a_domain_data *) | ||
1223 | kzalloc(sizeof(struct gk20a_domain_data), GFP_KERNEL); | ||
1224 | |||
1225 | if (!gpu_gpd_data) | ||
1226 | return -ENOMEM; | ||
1227 | |||
1228 | gpu_gpd_data->gk20a = platform->g; | ||
1229 | domain = &gpu_gpd_data->gpd; | ||
1200 | 1230 | ||
1201 | domain->name = "gpu"; | 1231 | domain->name = "gpu"; |
1202 | 1232 | ||
@@ -1227,6 +1257,7 @@ static int gk20a_pm_initialise_domain(struct platform_device *pdev) | |||
1227 | 1257 | ||
1228 | return ret; | 1258 | return ret; |
1229 | } | 1259 | } |
1260 | #endif | ||
1230 | 1261 | ||
1231 | static int gk20a_pm_init(struct platform_device *dev) | 1262 | static int gk20a_pm_init(struct platform_device *dev) |
1232 | { | 1263 | { |
@@ -1280,12 +1311,21 @@ static int gk20a_secure_page_alloc(struct platform_device *pdev) | |||
1280 | return err; | 1311 | return err; |
1281 | } | 1312 | } |
1282 | 1313 | ||
1314 | static struct of_device_id tegra_gpu_domain_match[] = { | ||
1315 | {.compatible = "nvidia,tegra210-gpu-pd"}, | ||
1316 | {}, | ||
1317 | }; | ||
1318 | |||
1283 | static int gk20a_probe(struct platform_device *dev) | 1319 | static int gk20a_probe(struct platform_device *dev) |
1284 | { | 1320 | { |
1285 | struct gk20a *gk20a; | 1321 | struct gk20a *gk20a; |
1286 | int err; | 1322 | int err; |
1287 | struct gk20a_platform *platform = NULL; | 1323 | struct gk20a_platform *platform = NULL; |
1288 | 1324 | ||
1325 | #ifdef CONFIG_PM_GENERIC_DOMAINS_OF | ||
1326 | struct gk20a_domain_data *gk20a_domain; | ||
1327 | #endif | ||
1328 | |||
1289 | if (dev->dev.of_node) { | 1329 | if (dev->dev.of_node) { |
1290 | const struct of_device_id *match; | 1330 | const struct of_device_id *match; |
1291 | 1331 | ||
@@ -1313,6 +1353,12 @@ static int gk20a_probe(struct platform_device *dev) | |||
1313 | return -ENOMEM; | 1353 | return -ENOMEM; |
1314 | } | 1354 | } |
1315 | 1355 | ||
1356 | #ifdef CONFIG_PM_GENERIC_DOMAINS_OF | ||
1357 | gk20a_domain = container_of(dev_to_genpd(&dev->dev), | ||
1358 | struct gk20a_domain_data, gpd); | ||
1359 | gk20a_domain->gk20a = gk20a; | ||
1360 | #endif | ||
1361 | |||
1316 | set_gk20a(dev, gk20a); | 1362 | set_gk20a(dev, gk20a); |
1317 | gk20a->dev = dev; | 1363 | gk20a->dev = dev; |
1318 | 1364 | ||
@@ -1451,6 +1497,7 @@ static int __exit gk20a_remove(struct platform_device *dev) | |||
1451 | { | 1497 | { |
1452 | struct gk20a *g = get_gk20a(dev); | 1498 | struct gk20a *g = get_gk20a(dev); |
1453 | struct gk20a_platform *platform = gk20a_get_platform(dev); | 1499 | struct gk20a_platform *platform = gk20a_get_platform(dev); |
1500 | struct gk20a_domain_data *gk20a_gpd; | ||
1454 | 1501 | ||
1455 | gk20a_dbg_fn(""); | 1502 | gk20a_dbg_fn(""); |
1456 | 1503 | ||
@@ -1481,6 +1528,10 @@ static int __exit gk20a_remove(struct platform_device *dev) | |||
1481 | platform->secure_buffer.destroy(dev, | 1528 | platform->secure_buffer.destroy(dev, |
1482 | &platform->secure_buffer); | 1529 | &platform->secure_buffer); |
1483 | 1530 | ||
1531 | gk20a_gpd = container_of(&g, struct gk20a_domain_data, gk20a); | ||
1532 | gk20a_gpd->gk20a = NULL; | ||
1533 | kfree(gk20a_gpd); | ||
1534 | |||
1484 | if (pm_runtime_enabled(&dev->dev)) | 1535 | if (pm_runtime_enabled(&dev->dev)) |
1485 | pm_runtime_disable(&dev->dev); | 1536 | pm_runtime_disable(&dev->dev); |
1486 | else | 1537 | else |
@@ -1513,8 +1564,78 @@ static struct platform_driver gk20a_driver = { | |||
1513 | } | 1564 | } |
1514 | }; | 1565 | }; |
1515 | 1566 | ||
1567 | #ifdef CONFIG_PM_GENERIC_DOMAINS_OF | ||
1568 | |||
1569 | |||
1570 | static int _gk20a_init_domain(struct device_node *np, | ||
1571 | struct generic_pm_domain *gpd) | ||
1572 | { | ||
1573 | bool is_off = false; | ||
1574 | |||
1575 | gpd->name = (char *)np->name; | ||
1576 | |||
1577 | if (of_property_read_bool(np, "is_off")) | ||
1578 | is_off = true; | ||
1579 | |||
1580 | pm_genpd_init(gpd, NULL, is_off); | ||
1581 | |||
1582 | gpd->power_on = gk20a_pm_unrailgate; | ||
1583 | gpd->power_off = gk20a_pm_railgate; | ||
1584 | gpd->dev_ops.start = gk20a_pm_enable_clk; | ||
1585 | gpd->dev_ops.stop = gk20a_pm_disable_clk; | ||
1586 | gpd->dev_ops.save_state = gk20a_pm_prepare_poweroff; | ||
1587 | gpd->dev_ops.restore_state = gk20a_pm_finalize_poweron; | ||
1588 | #warning domain suspend/resume ops have been removed upstream | ||
1589 | #if 0 | ||
1590 | gpd->dev_ops.suspend = gk20a_pm_suspend; | ||
1591 | gpd->dev_ops.resume = gk20a_pm_resume; | ||
1592 | #endif | ||
1593 | |||
1594 | of_genpd_add_provider_simple(np, gpd); | ||
1595 | gpd->of_node = of_node_get(np); | ||
1596 | |||
1597 | genpd_pm_subdomain_attach(gpd); | ||
1598 | return 0; | ||
1599 | } | ||
1600 | |||
1601 | static int gk20a_domain_init(struct of_device_id *matches) | ||
1602 | { | ||
1603 | int ret = 0; | ||
1604 | struct device_node *np; | ||
1605 | const struct of_device_id *match; | ||
1606 | struct gk20a_domain_data *gk20a_domain; | ||
1607 | |||
1608 | np = of_find_matching_node(NULL, matches); | ||
1609 | if (!np) | ||
1610 | return -ENOENT; | ||
1611 | |||
1612 | match = of_match_node(matches, np); | ||
1613 | gk20a_domain = (struct gk20a_domain_data *)kzalloc | ||
1614 | (sizeof(struct gk20a_domain_data), GFP_KERNEL); | ||
1615 | if (!gk20a_domain) | ||
1616 | return -ENOMEM; | ||
1617 | |||
1618 | ret = _gk20a_init_domain(np, &gk20a_domain->gpd); | ||
1619 | |||
1620 | return ret; | ||
1621 | } | ||
1622 | #else | ||
1623 | static int gk20a_domain_init(struct of_device_id *matches) | ||
1624 | { | ||
1625 | return 0; | ||
1626 | } | ||
1627 | #endif | ||
1628 | |||
1629 | |||
1516 | static int __init gk20a_init(void) | 1630 | static int __init gk20a_init(void) |
1517 | { | 1631 | { |
1632 | |||
1633 | int ret; | ||
1634 | |||
1635 | ret = gk20a_domain_init(tegra_gpu_domain_match); | ||
1636 | if (ret) | ||
1637 | return ret; | ||
1638 | |||
1518 | return platform_driver_register(&gk20a_driver); | 1639 | return platform_driver_register(&gk20a_driver); |
1519 | } | 1640 | } |
1520 | 1641 | ||
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 { | |||
504 | u32 max_ltc_count; | 504 | u32 max_ltc_count; |
505 | u32 ltc_count; | 505 | u32 ltc_count; |
506 | 506 | ||
507 | struct generic_pm_domain pd; | ||
508 | |||
509 | struct devfreq *devfreq; | 507 | struct devfreq *devfreq; |
510 | 508 | ||
511 | struct gk20a_scale_profile *scale_profile; | 509 | struct gk20a_scale_profile *scale_profile; |
@@ -556,6 +554,11 @@ struct gk20a_cyclestate_buffer_elem { | |||
556 | u64 data; | 554 | u64 data; |
557 | }; | 555 | }; |
558 | 556 | ||
557 | struct gk20a_domain_data { | ||
558 | struct generic_pm_domain gpd; | ||
559 | struct gk20a *gk20a; | ||
560 | }; | ||
561 | |||
559 | /* debug accessories */ | 562 | /* debug accessories */ |
560 | 563 | ||
561 | #ifdef CONFIG_DEBUG_FS | 564 | #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) | |||
112 | 112 | ||
113 | static int gk20a_generic_late_probe(struct platform_device *dev) | 113 | static int gk20a_generic_late_probe(struct platform_device *dev) |
114 | { | 114 | { |
115 | struct gk20a_platform *platform = gk20a_get_platform(dev); | 115 | struct generic_pm_domain *gpd = dev_to_genpd(&dev->dev); |
116 | 116 | ||
117 | /* Make gk20a power domain a subdomain of mc */ | 117 | /* Make gk20a power domain a subdomain of host1x */ |
118 | tegra_pd_add_sd(&platform->g->pd); | 118 | tegra_pd_add_sd(gpd); |
119 | 119 | ||
120 | return 0; | 120 | return 0; |
121 | } | 121 | } |
122 | 122 | ||
123 | static int gk20a_generic_remove(struct platform_device *dev) | 123 | static int gk20a_generic_remove(struct platform_device *dev) |
124 | { | 124 | { |
125 | struct gk20a_platform *platform = gk20a_get_platform(dev); | 125 | struct generic_pm_domain *gpd = dev_to_genpd(&dev->dev); |
126 | 126 | ||
127 | tegra_pd_remove_sd(&platform->g->pd); | 127 | tegra_pd_remove_sd(gpd); |
128 | 128 | ||
129 | return 0; | 129 | return 0; |
130 | } | 130 | } |
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) | |||
472 | 472 | ||
473 | static int gk20a_tegra_late_probe(struct platform_device *dev) | 473 | static int gk20a_tegra_late_probe(struct platform_device *dev) |
474 | { | 474 | { |
475 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
476 | |||
477 | /* Make gk20a power domain a subdomain of host1x */ | 475 | /* Make gk20a power domain a subdomain of host1x */ |
478 | nvhost_register_client_domain(&platform->g->pd); | 476 | nvhost_register_client_domain(dev_to_genpd(&dev->dev)); |
479 | 477 | ||
480 | /* Initialise tegra specific scaling quirks */ | 478 | /* Initialise tegra specific scaling quirks */ |
481 | gk20a_tegra_scale_init(dev); | 479 | gk20a_tegra_scale_init(dev); |
@@ -485,10 +483,8 @@ static int gk20a_tegra_late_probe(struct platform_device *dev) | |||
485 | 483 | ||
486 | static int gk20a_tegra_remove(struct platform_device *dev) | 484 | static int gk20a_tegra_remove(struct platform_device *dev) |
487 | { | 485 | { |
488 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
489 | |||
490 | /* remove gk20a power subdomain from host1x */ | 486 | /* remove gk20a power subdomain from host1x */ |
491 | nvhost_unregister_client_domain(&platform->g->pd); | 487 | nvhost_unregister_client_domain(dev_to_genpd(&dev->dev)); |
492 | 488 | ||
493 | /* deinitialise tegra specific scaling quirks */ | 489 | /* deinitialise tegra specific scaling quirks */ |
494 | gk20a_tegra_scale_exit(dev); | 490 | gk20a_tegra_scale_exit(dev); |
diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.c b/drivers/gpu/nvgpu/vgpu/vgpu.c index d3d793d1..c998b10b 100644 --- a/drivers/gpu/nvgpu/vgpu/vgpu.c +++ b/drivers/gpu/nvgpu/vgpu/vgpu.c | |||
@@ -311,7 +311,17 @@ static int vgpu_pm_initialise_domain(struct platform_device *pdev) | |||
311 | { | 311 | { |
312 | struct gk20a_platform *platform = platform_get_drvdata(pdev); | 312 | struct gk20a_platform *platform = platform_get_drvdata(pdev); |
313 | struct dev_power_governor *pm_domain_gov = NULL; | 313 | struct dev_power_governor *pm_domain_gov = NULL; |
314 | struct generic_pm_domain *domain = &platform->g->pd; | 314 | struct gk20a_domain_data *vgpu_pd_data; |
315 | struct generic_pm_domain *domain; | ||
316 | |||
317 | vgpu_pd_data = (struct gk20a_domain_data *)kzalloc | ||
318 | (sizeof(struct gk20a_domain_data), GFP_KERNEL); | ||
319 | |||
320 | if (!vgpu_pd_data) | ||
321 | return -ENOMEM; | ||
322 | |||
323 | domain = &vgpu_pd_data->gpd; | ||
324 | vgpu_pd_data->gk20a = platform->g; | ||
315 | 325 | ||
316 | domain->name = "gpu"; | 326 | domain->name = "gpu"; |
317 | 327 | ||
@@ -432,11 +442,16 @@ int vgpu_probe(struct platform_device *dev) | |||
432 | int vgpu_remove(struct platform_device *dev) | 442 | int vgpu_remove(struct platform_device *dev) |
433 | { | 443 | { |
434 | struct gk20a *g = get_gk20a(dev); | 444 | struct gk20a *g = get_gk20a(dev); |
445 | struct gk20a_domain_data *vgpu_gpd; | ||
435 | gk20a_dbg_fn(""); | 446 | gk20a_dbg_fn(""); |
436 | 447 | ||
437 | if (g->remove_support) | 448 | if (g->remove_support) |
438 | g->remove_support(dev); | 449 | g->remove_support(dev); |
439 | 450 | ||
451 | vgpu_gpd = container_of(&g, struct gk20a_domain_data, gk20a); | ||
452 | vgpu_gpd->gk20a = NULL; | ||
453 | kfree(vgpu_gpd); | ||
454 | |||
440 | vgpu_comm_deinit(); | 455 | vgpu_comm_deinit(); |
441 | gk20a_user_deinit(dev); | 456 | gk20a_user_deinit(dev); |
442 | gk20a_get_platform(dev)->g = NULL; | 457 | gk20a_get_platform(dev)->g = NULL; |