# Base git commit: 523d939ef98f
# (Linux 4.7)
# 
# Author:    Russell King (Thu 17 Mar 19:17:16 GMT 2016)
# Committer: Russell King (Mon  8 Aug 11:03:33 BST 2016)
# 
#   drm: etnaviv: try harder to reset the GPU at probe time
# 
#   Try harder to reset the GPU at probe time by allowing the GPU to enter
#   runtime PM even if it indicates that it is busy.  Where platforms
#   implement PM domains, this allows the GPU domain to be power cycled,
#   which can recover a hung GPU.
# 
#   This can't be done in normal operation as we need to drop the mutex,
#   and dropping the mutex will permit GPU submissions which will keep the
#   GPU from idling.
# 
#   Signed-off-by: Russell King
# 
#   b20b8d4bc709977bf6c66fd08f3539535eaaf182
#    drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 22 ++++++++++++++++++++--
#    drivers/gpu/drm/etnaviv/etnaviv_gpu.h |  1 +
#    2 files changed, 21 insertions(+), 2 deletions(-)
# 
# Author:    Russell King (Fri 31 Jul 14:24:55 BST 2015)
# Committer: Russell King (Mon  8 Aug 11:03:33 BST 2016)
# 
#   drm: etnaviv: initial suspend/resume support
# 
#   Signed-off-by: Russell King
# 
#   a09a4e88711b1a8bb8cb1bb825cb85a1941795c2
#    drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 65 +++++++++++++++++++++++++++++------
#    1 file changed, 55 insertions(+), 10 deletions(-)
# 
# Author:    Russell King (Tue 26 May 09:40:33 BST 2015)
# Committer: Russell King (Mon  8 Aug 11:03:33 BST 2016)
# 
#   drm: etnaviv: add device property to control parsing of command buffers
# 
#   Parsing the command buffer is an expensive operation, as the command
#   buffer is uncached.  Work-around this by providing a control to allow
#   the command buffer parsing to be skipped.
# 
#   A better solution would be to move to cached buffers between userspace
#   and kernelspace, and copying the data in kernel space to the final
#   command buffer.
# 
#   Signed-off-by: Russell King
# 
#   a0fb5e7bff0aea17038553daec796881e3872fd7
#    drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c |  3 ++-
#    drivers/gpu/drm/etnaviv/etnaviv_gpu.c        | 27 +++++++++++++++++++++++++++
#    drivers/gpu/drm/etnaviv/etnaviv_gpu.h        |  1 +
#    3 files changed, 30 insertions(+), 1 deletion(-)
# 
# Author:    Russell King (Sun 13 Dec 19:56:12 GMT 2015)
# Committer: Russell King (Mon  8 Aug 11:03:33 BST 2016)
# 
#   drm: etnaviv: enable GPU module level clock gating support
# 
#   Enable GPU module level hardware clock gating, using the conditions
#   found in the galcore v5 driver.
# 
#   Signed-off-by: Russell King
# 
#   02ef32fdb338cc843498c74566f794a9a973b8f3
#    drivers/gpu/drm/etnaviv/etnaviv_gpu.c  | 44 ++++++++++++++++++++++++++++++++++
#    drivers/gpu/drm/etnaviv/state_hi.xml.h |  7 ++++++
#    2 files changed, 51 insertions(+)
# 
# Author:    Russell King (Mon 18 Jan 11:38:06 GMT 2016)
# Committer: Russell King (Mon  8 Aug 11:03:33 BST 2016)
# 
#   drm/etnaviv: re-allow get_param as per "staging: etnaviv: allow get_param without auth"
# 
#   A previous commit was dropped which allows unprivileged userspace to
#   query the capabilities of the GPU (eg, the viv_info tool.):
# 
#       staging: etnaviv: allow get_param without auth
# 
#       There is no need to restrict access to the get_param ioctl; this is
#       used to obtain information about the device and has no side effects.
# 
#       Signed-off-by: Russell King
# 
#   Signed-off-by: Russell King
# 
#   2ad16c21d10217a6563c16386c267f6000b15975
#    drivers/gpu/drm/etnaviv/etnaviv_drv.c | 2 +-
#    1 file changed, 1 insertion(+), 1 deletion(-)
# 
# Author:    Russell King (Sat 30 Jul 18:48:22 BST 2016)
# Committer: Russell King (Mon  8 Aug 11:00:52 BST 2016)
# 
#   drm/etnaviv: add etnaviv cooling device
# 
#   Each Vivante GPU contains a clock divider which can divide the GPU clock
#   by 2^n, which can lower the power dissipation from the GPU.  It has been
#   suggested that the GC600 on Dove can be responsible for 20-30% of the
#   power dissipation from the SoC.
# 
#   Signed-off-by: Russell King
# 
#   7d16c08ab6cd8de9c13ce5ce13b5d66a6feebca6
#    drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 85 ++++++++++++++++++++++++++++-------
#    drivers/gpu/drm/etnaviv/etnaviv_gpu.h |  2 +
#    2 files changed, 72 insertions(+), 15 deletions(-)
# 
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 3d4f56df8359..0c4d63150c31 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -458,7 +458,7 @@ static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data,
 static const struct drm_ioctl_desc etnaviv_ioctls[] = {
 #define ETNA_IOCTL(n, func, flags) \
 	DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags)
-	ETNA_IOCTL(GET_PARAM,    get_param,    DRM_AUTH|DRM_RENDER_ALLOW),
+	ETNA_IOCTL(GET_PARAM,    get_param,    DRM_RENDER_ALLOW),
 	ETNA_IOCTL(GEM_NEW,      gem_new,      DRM_AUTH|DRM_RENDER_ALLOW),
 	ETNA_IOCTL(GEM_INFO,     gem_info,     DRM_AUTH|DRM_RENDER_ALLOW),
 	ETNA_IOCTL(GEM_CPU_PREP, gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
index afdd55ddf821..7bae554d6315 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -377,7 +377,8 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
 	if (ret)
 		goto err_submit_objects;
 
-	if (!etnaviv_cmd_validate_one(gpu, stream, args->stream_size / 4,
+	if (gpu->validate_cmdbuf &&
+	    !etnaviv_cmd_validate_one(gpu, stream, args->stream_size / 4,
 				      relocs, args->nr_relocs)) {
 		ret = -EINVAL;
 		goto err_submit_objects;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index ff6aa5dfb2d7..57aa177ac348 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -18,6 +18,8 @@
 #include <linux/fence.h>
 #include <linux/moduleparam.h>
 #include <linux/of_device.h>
+#include <linux/thermal.h>
+
 #include "etnaviv_dump.h"
 #include "etnaviv_gpu.h"
 #include "etnaviv_gem.h"
@@ -397,6 +399,17 @@ static void etnaviv_gpu_load_clock(struct etnaviv_gpu *gpu, u32 clock)
 	gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
 }
 
+static void etnaviv_gpu_update_clock(struct etnaviv_gpu *gpu)
+{
+	unsigned int fscale = 1 << (6 - gpu->freq_scale);
+	u32 clock;
+
+	clock = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
+		VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(fscale);
+
+	etnaviv_gpu_load_clock(gpu, clock);
+}
+
 static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
 {
 	u32 control, idle;
@@ -414,11 +427,10 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
 	timeout = jiffies + msecs_to_jiffies(1000);
 
 	while (time_is_after_jiffies(timeout)) {
-		control = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
-			  VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
-
 		/* enable clock */
-		etnaviv_gpu_load_clock(gpu, control);
+		etnaviv_gpu_update_clock(gpu);
+
+		control = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
 
 		/* Wait for stable clock.  Vivante's code waited for 1ms */
 		usleep_range(1000, 10000);
@@ -478,15 +490,52 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
 	}
 
 	/* We rely on the GPU running, so program the clock */
-	control = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
-		  VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
-
-	/* enable clock */
-	etnaviv_gpu_load_clock(gpu, control);
+	etnaviv_gpu_update_clock(gpu);
 
 	return 0;
 }
 
+static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu)
+{
+	u32 pmc, ppc;
+
+	/* enable clock gating */
+	ppc = gpu_read(gpu, VIVS_PM_POWER_CONTROLS);
+	ppc |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
+
+	/* Disable stall module clock gating for 4.3.0.1 and 4.3.0.2 revs */
+	if (gpu->identity.revision == 0x4301 ||
+	    gpu->identity.revision == 0x4302)
+		ppc |= VIVS_PM_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING;
+
+	gpu_write(gpu, VIVS_PM_POWER_CONTROLS, ppc);
+
+	pmc = gpu_read(gpu, VIVS_PM_MODULE_CONTROLS);
+
+	/* Disable PA clock gating for GC400+ except for GC420 */
+	if (gpu->identity.model >= chipModel_GC400 &&
+	    gpu->identity.model != chipModel_GC420)
+		pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_PA;
+
+	/*
+	 * Disable PE clock gating on revs < 5.0.0.0 when HZ is
+	 * present without a bug fix.
+	 */
+	if (gpu->identity.revision < 0x5000 &&
+	    gpu->identity.minor_features0 & chipMinorFeatures0_HZ &&
+	    !(gpu->identity.minor_features1 &
+	      chipMinorFeatures1_DISABLE_PE_GATING))
+		pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_PE;
+
+	if (gpu->identity.revision < 0x5422)
+		pmc |= BIT(15); /* Unknown bit */
+
+	pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_HZ;
+	pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_EZ;
+
+	gpu_write(gpu, VIVS_PM_MODULE_CONTROLS, pmc);
+}
+
 static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
 {
 	u16 prefetch;
@@ -506,6 +555,9 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
 		gpu_write(gpu, VIVS_MC_DEBUG_MEMORY, mc_memory_debug);
 	}
 
+	/* enable module-level clock gating */
+	etnaviv_gpu_enable_mlcg(gpu);
+
 	/*
 	 * Update GPU AXI cache atttribute to "cacheable, no allocate".
 	 * This is necessary to prevent the iMX6 SoC locking up.
@@ -547,7 +599,7 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
 
 int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
 {
-	int ret, i;
+	int ret, i, try;
 	struct iommu_domain *iommu;
 	enum etnaviv_iommu_version version;
 	bool mmuv2;
@@ -590,7 +642,20 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
 			gpu->memory_base = dma_mask - SZ_2G + 1;
 	}
 
-	ret = etnaviv_hw_reset(gpu);
+	for (try = 0; try < 2; try++) {
+		ret = etnaviv_hw_reset(gpu);
+		if (ret == 0)
+			break;
+
+		dev_warn(gpu->dev, "GPU failed to reset, trying to power cycle\n");
+		gpu->force_rpm_idle = true;
+		pm_runtime_put_sync(gpu->dev);
+		msleep(100);
+		ret = pm_runtime_get_sync(gpu->dev);
+		gpu->force_rpm_idle = false;
+		if (ret)
+			break;
+	}
 	if (ret)
 		goto fail;
 
@@ -1478,20 +1543,15 @@ static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)
 	return etnaviv_gpu_clk_disable(gpu);
 }
 
-#ifdef CONFIG_PM
 static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu)
 {
-	u32 clock;
 	int ret;
 
 	ret = mutex_lock_killable(&gpu->lock);
 	if (ret)
 		return ret;
 
-	clock = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
-		VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
-
-	etnaviv_gpu_load_clock(gpu, clock);
+	etnaviv_gpu_update_clock(gpu);
 	etnaviv_gpu_hw_init(gpu);
 
 	gpu->switch_context = true;
@@ -1501,7 +1561,47 @@ static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu)
 
 	return 0;
 }
-#endif
+
+static int
+etnaviv_gpu_cooling_get_max_state(struct thermal_cooling_device *cdev,
+				  unsigned long *state)
+{
+	*state = 6;
+
+	return 0;
+}
+
+static int
+etnaviv_gpu_cooling_get_cur_state(struct thermal_cooling_device *cdev,
+				  unsigned long *state)
+{
+	struct etnaviv_gpu *gpu = cdev->devdata;
+
+	*state = gpu->freq_scale;
+
+	return 0;
+}
+
+static int
+etnaviv_gpu_cooling_set_cur_state(struct thermal_cooling_device *cdev,
+				  unsigned long state)
+{
+	struct etnaviv_gpu *gpu = cdev->devdata;
+
+	mutex_lock(&gpu->lock);
+	gpu->freq_scale = state;
+	if (!pm_runtime_suspended(gpu->dev))
+		etnaviv_gpu_update_clock(gpu);
+	mutex_unlock(&gpu->lock);
+
+	return 0;
+}
+
+static struct thermal_cooling_device_ops cooling_ops = {
+	.get_max_state = etnaviv_gpu_cooling_get_max_state,
+	.get_cur_state = etnaviv_gpu_cooling_get_cur_state,
+	.set_cur_state = etnaviv_gpu_cooling_set_cur_state,
+};
 
 static int etnaviv_gpu_bind(struct device *dev, struct device *master,
 	void *data)
@@ -1511,13 +1611,20 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
 	struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
 	int ret;
 
+	gpu->cooling = thermal_of_cooling_device_register(dev->of_node,
+				(char *)dev_name(dev), gpu, &cooling_ops);
+	if (IS_ERR(gpu->cooling))
+		return PTR_ERR(gpu->cooling);
+
 #ifdef CONFIG_PM
 	ret = pm_runtime_get_sync(gpu->dev);
 #else
 	ret = etnaviv_gpu_clk_enable(gpu);
 #endif
-	if (ret < 0)
+	if (ret < 0) {
+		thermal_cooling_device_unregister(gpu->cooling);
 		return ret;
+	}
 
 	gpu->drm = drm;
 	gpu->fence_context = fence_context_alloc(1);
@@ -1566,6 +1673,9 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
 	}
 
 	gpu->drm = NULL;
+
+	thermal_cooling_device_unregister(gpu->cooling);
+	gpu->cooling = NULL;
 }
 
 static const struct component_ops gpu_ops = {
@@ -1580,6 +1690,27 @@ static const struct of_device_id etnaviv_gpu_match[] = {
 	{ /* sentinel */ }
 };
 
+static ssize_t etnaviv_gpu_check_cmdbuf_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", gpu->validate_cmdbuf);
+}
+
+static ssize_t etnaviv_gpu_check_cmdbuf_store(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
+
+	if (strtobool(buf, &gpu->validate_cmdbuf))
+		return -EINVAL;
+
+	return count;
+}
+
+static DEVICE_ATTR(check_cmdbuf, 0600, etnaviv_gpu_check_cmdbuf_show, etnaviv_gpu_check_cmdbuf_store);
+
 static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -1632,6 +1763,8 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
 	/* TODO: figure out max mapped size */
 	dev_set_drvdata(dev, gpu);
 
+	gpu->validate_cmdbuf = true;
+
 	/*
 	 * We treat the device as initially suspended.  The runtime PM
 	 * autosuspend delay is rather arbitary: no measurements have
@@ -1641,9 +1774,12 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
 	pm_runtime_set_autosuspend_delay(gpu->dev, 200);
 	pm_runtime_enable(gpu->dev);
 
+	device_create_file(gpu->dev, &dev_attr_check_cmdbuf);
+
 	err = component_add(&pdev->dev, &gpu_ops);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register component: %d\n", err);
+		device_remove_file(gpu->dev, &dev_attr_check_cmdbuf);
 		goto fail;
 	}
 
@@ -1657,29 +1793,41 @@ static int etnaviv_gpu_platform_remove(struct platform_device *pdev)
 {
 	component_del(&pdev->dev, &gpu_ops);
 	pm_runtime_disable(&pdev->dev);
+	device_remove_file(&pdev->dev, &dev_attr_check_cmdbuf);
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int etnaviv_gpu_rpm_suspend(struct device *dev)
+static bool etnaviv_gpu_is_idle(struct etnaviv_gpu *gpu, u32 mask)
+{
+	u32 idle;
+
+	mask = mask & gpu->idle_mask;
+	idle = gpu_read(gpu, VIVS_HI_IDLE_STATE) & mask;
+
+	return idle == mask;
+}
+
+static int __maybe_unused etnaviv_gpu_rpm_suspend(struct device *dev)
 {
 	struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
-	u32 idle, mask;
+
+	if (gpu->force_rpm_idle) {
+		etnaviv_gpu_clk_disable(gpu);
+		return 0;
+	}
 
 	/* If we have outstanding fences, we're not idle */
 	if (gpu->completed_fence != gpu->active_fence)
 		return -EBUSY;
 
 	/* Check whether the hardware (except FE) is idle */
-	mask = gpu->idle_mask & ~VIVS_HI_IDLE_STATE_FE;
-	idle = gpu_read(gpu, VIVS_HI_IDLE_STATE) & mask;
-	if (idle != mask)
+	if (!etnaviv_gpu_is_idle(gpu, ~VIVS_HI_IDLE_STATE_FE))
 		return -EBUSY;
 
 	return etnaviv_gpu_hw_suspend(gpu);
 }
 
-static int etnaviv_gpu_rpm_resume(struct device *dev)
+static int __maybe_unused etnaviv_gpu_rpm_resume(struct device *dev)
 {
 	struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
 	int ret;
@@ -1699,11 +1847,52 @@ static int etnaviv_gpu_rpm_resume(struct device *dev)
 
 	return 0;
 }
-#endif
+
+static int __maybe_unused etnaviv_gpu_suspend(struct device *dev)
+{
+	struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (!pm_runtime_suspended(dev) && gpu->drm) {
+		/*
+		 * Wait for the GPU to finish processing any commands
+		 * userspace has submitted before trying to suspend it; we
+		 * can't suspend the GPU with an incomplete command stream.
+		 * Note that this does not wait for the fences to be retired.
+		 */
+		ret = wait_event_timeout(gpu->fence_event,
+				 gpu->completed_fence == gpu->active_fence,
+				 msecs_to_jiffies(5000));
+		if (ret == 0) {
+			dev_crit(dev,
+				 "timeout while waiting for GPU to idle - rendering operations will be lost, suspending anyway\n");
+		} else {
+			/* Check whether the hardware (except FE) is idle */
+			if (!etnaviv_gpu_is_idle(gpu, ~VIVS_HI_IDLE_STATE_FE))
+				dev_crit(dev,
+					 "GPU is not idle - rendering operations will be lost, suspending anyway");
+		}
+
+		ret = etnaviv_gpu_hw_suspend(gpu);
+	}
+	return ret;
+}
+
+static int __maybe_unused etnaviv_gpu_resume(struct device *dev)
+{
+	struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (!pm_runtime_suspended(dev) && gpu->drm)
+		ret = etnaviv_gpu_rpm_resume(dev);
+
+	return ret;
+}
 
 static const struct dev_pm_ops etnaviv_gpu_pm_ops = {
 	SET_RUNTIME_PM_OPS(etnaviv_gpu_rpm_suspend, etnaviv_gpu_rpm_resume,
 			   NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(etnaviv_gpu_suspend, etnaviv_gpu_resume)
 };
 
 struct platform_driver etnaviv_gpu_driver = {
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
index f5321e2f25ff..f36c75ed3470 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -96,10 +96,12 @@ struct etnaviv_cmdbuf;
 
 struct etnaviv_gpu {
 	struct drm_device *drm;
+	struct thermal_cooling_device *cooling;
 	struct device *dev;
 	struct mutex lock;
 	struct etnaviv_chip_identity identity;
 	struct etnaviv_file_private *lastctx;
+	bool force_rpm_idle;
 	bool switch_context;
 
 	/* 'ring'-buffer: */
@@ -148,6 +150,8 @@ struct etnaviv_gpu {
 	u32 hangcheck_fence;
 	u32 hangcheck_dma_addr;
 	struct work_struct recover_work;
+	unsigned int freq_scale;
+	bool validate_cmdbuf;
 };
 
 struct etnaviv_cmdbuf {
diff --git a/drivers/gpu/drm/etnaviv/state_hi.xml.h b/drivers/gpu/drm/etnaviv/state_hi.xml.h
index 6a7de5f1454a..807a3d9e0dd5 100644
--- a/drivers/gpu/drm/etnaviv/state_hi.xml.h
+++ b/drivers/gpu/drm/etnaviv/state_hi.xml.h
@@ -218,6 +218,13 @@ Copyright (C) 2015
 #define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_FE	0x00000001
 #define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_DE	0x00000002
 #define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_PE	0x00000004
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_SH	0x00000008
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_PA	0x00000010
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_SE	0x00000020
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA	0x00000040
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX	0x00000080
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_EZ	0x00010000
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_HZ	0x00020000
 
 #define VIVS_PM_MODULE_STATUS					0x00000108
 #define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_FE		0x00000001
