summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c
index a5b4fddc..b36beb52 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.c
@@ -42,6 +42,7 @@
42#include <linux/spinlock.h> 42#include <linux/spinlock.h>
43#include <linux/tegra-powergate.h> 43#include <linux/tegra-powergate.h>
44#include <linux/tegra_pm_domains.h> 44#include <linux/tegra_pm_domains.h>
45#include <linux/clk/tegra.h>
45 46
46#include <linux/sched.h> 47#include <linux/sched.h>
47#include <linux/input-cfboost.h> 48#include <linux/input-cfboost.h>
@@ -1610,6 +1611,79 @@ void gk20a_reset(struct gk20a *g, u32 units)
1610 gk20a_enable(g, units); 1611 gk20a_enable(g, units);
1611} 1612}
1612 1613
1614/**
1615 * gk20a_do_idle() - force the GPU to idle and railgate
1616 *
1617 * In success, this call MUST be balanced by caller with gk20a_do_unidle()
1618 */
1619int gk20a_do_idle(void)
1620{
1621 struct platform_device *pdev = to_platform_device(
1622 bus_find_device_by_name(&platform_bus_type,
1623 NULL, "gk20a.0"));
1624 struct gk20a *g = get_gk20a(pdev);
1625 struct gk20a_platform *platform = dev_get_drvdata(&pdev->dev);
1626 struct fifo_gk20a *f = &g->fifo;
1627 unsigned long timeout = jiffies + msecs_to_jiffies(200);
1628 int chid, ref_cnt;
1629
1630 if (!platform->can_railgate)
1631 return -ENOSYS;
1632
1633 /* acquire busy lock to block other busy() calls */
1634 down_write(&g->busy_lock);
1635
1636 /* prevent suspend by incrementing usage counter */
1637 pm_runtime_get_noresume(&pdev->dev);
1638
1639 /* check and wait until GPU is idle (with a timeout) */
1640 pm_runtime_barrier(&pdev->dev);
1641
1642 for (chid = 0; chid < f->num_channels; chid++)
1643 if (gk20a_wait_channel_idle(&f->channel[chid]))
1644 goto fail;
1645
1646 do {
1647 mdelay(1);
1648 ref_cnt = atomic_read(&pdev->dev.power.usage_count);
1649 } while (ref_cnt != 1 && time_before(jiffies, timeout));
1650
1651 if (ref_cnt != 1)
1652 goto fail;
1653
1654 /*
1655 * if GPU is now idle, we will have only one ref count
1656 * drop this ref which will rail gate the GPU
1657 */
1658 pm_runtime_put_sync(&pdev->dev);
1659
1660 /* add sufficient delay to allow GPU to rail gate */
1661 mdelay(platform->railgate_delay + 100);
1662
1663 return 0;
1664
1665fail:
1666 pm_runtime_put_noidle(&pdev->dev);
1667 up_write(&g->busy_lock);
1668 return -EBUSY;
1669}
1670
1671/**
1672 * gk20a_do_unidle() - unblock all the tasks blocked by gk20a_do_idle()
1673 */
1674int gk20a_do_unidle(void)
1675{
1676 struct platform_device *pdev = to_platform_device(
1677 bus_find_device_by_name(&platform_bus_type,
1678 NULL, "gk20a.0"));
1679 struct gk20a *g = get_gk20a(pdev);
1680
1681 /* release the lock and open up all other busy() calls */
1682 up_write(&g->busy_lock);
1683
1684 return 0;
1685}
1686
1613int gk20a_init_gpu_characteristics(struct gk20a *g) 1687int gk20a_init_gpu_characteristics(struct gk20a *g)
1614{ 1688{
1615 struct nvhost_gpu_characteristics *gpu = &g->gpu_characteristics; 1689 struct nvhost_gpu_characteristics *gpu = &g->gpu_characteristics;