msm: kgsl: Add supporting code for 2d dcvs

2d dcvs will also need changes in TrustZone.  However
by adding this code first the TrustZone update can be
made later without breaking any functionality.  This
feature is disabled by default and should not be
enabled without the necessary TrustZone changes in
place.

Change-Id: Ifdd511a3f18ba90faee189393ffc231fbbc6e2cd
Signed-off-by: Lucille Sylvester <lsylvest@codeaurora.org>
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 8c251ba..172e124 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -2090,7 +2090,7 @@
 	},
 };
 
-static struct msm_bus_vectors grp2d0_max_vectors[] = {
+static struct msm_bus_vectors grp2d0_nominal_vectors[] = {
 	{
 		.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE0,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
@@ -2099,12 +2099,25 @@
 	},
 };
 
+static struct msm_bus_vectors grp2d0_max_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(2048),
+	},
+};
+
 static struct msm_bus_paths grp2d0_bus_scale_usecases[] = {
 	{
 		ARRAY_SIZE(grp2d0_init_vectors),
 		grp2d0_init_vectors,
 	},
 	{
+		ARRAY_SIZE(grp2d0_nominal_vectors),
+		grp2d0_nominal_vectors,
+	},
+	{
 		ARRAY_SIZE(grp2d0_max_vectors),
 		grp2d0_max_vectors,
 	},
@@ -2125,7 +2138,7 @@
 	},
 };
 
-static struct msm_bus_vectors grp2d1_max_vectors[] = {
+static struct msm_bus_vectors grp2d1_nominal_vectors[] = {
 	{
 		.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE1,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
@@ -2134,12 +2147,25 @@
 	},
 };
 
+static struct msm_bus_vectors grp2d1_max_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE1,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(2048),
+	},
+};
+
 static struct msm_bus_paths grp2d1_bus_scale_usecases[] = {
 	{
 		ARRAY_SIZE(grp2d1_init_vectors),
 		grp2d1_init_vectors,
 	},
 	{
+		ARRAY_SIZE(grp2d1_nominal_vectors),
+		grp2d1_nominal_vectors,
+	},
+	{
 		ARRAY_SIZE(grp2d1_max_vectors),
 		grp2d1_max_vectors,
 	},
@@ -2236,17 +2262,21 @@
 	.pwrlevel = {
 		{
 			.gpu_freq = 200000000,
+			.bus_freq = 2,
+		},
+		{
+			.gpu_freq = 96000000,
 			.bus_freq = 1,
 		},
 		{
-			.gpu_freq = 200000000,
+			.gpu_freq = 27000000,
 			.bus_freq = 0,
 		},
 	},
 	.init_level = 0,
-	.num_levels = 2,
+	.num_levels = 3,
 	.set_grp_async = NULL,
-	.idle_timeout = HZ/10,
+	.idle_timeout = HZ/5,
 	.nap_allowed = true,
 	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE,
 #ifdef CONFIG_MSM_BUS_SCALING
@@ -2285,17 +2315,21 @@
 	.pwrlevel = {
 		{
 			.gpu_freq = 200000000,
+			.bus_freq = 2,
+		},
+		{
+			.gpu_freq = 96000000,
 			.bus_freq = 1,
 		},
 		{
-			.gpu_freq = 200000000,
+			.gpu_freq = 27000000,
 			.bus_freq = 0,
 		},
 	},
 	.init_level = 0,
-	.num_levels = 2,
+	.num_levels = 3,
 	.set_grp_async = NULL,
-	.idle_timeout = HZ/10,
+	.idle_timeout = HZ/5,
 	.nap_allowed = true,
 	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE,
 #ifdef CONFIG_MSM_BUS_SCALING
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 3ef11ce..b301743 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -175,6 +175,7 @@
 	struct kobject pwrscale_kobj;
 	struct work_struct ts_expired_ws;
 	struct list_head events;
+	s64 on_time;
 };
 
 struct kgsl_context {
diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
index f3e84e4..eeade17 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/spinlock.h>
 #include <mach/socinfo.h>
 #include <mach/scm.h>
 
@@ -29,6 +30,7 @@
 	unsigned int no_switch_cnt;
 	unsigned int skip_cnt;
 };
+spinlock_t tz_lock;
 
 #define SWITCH_OFF		200
 #define SWITCH_OFF_RESET_TH	40
@@ -38,13 +40,17 @@
 
 #ifdef CONFIG_MSM_SCM
 /* Trap into the TrustZone, and call funcs there. */
-static int __secure_tz_entry(u32 cmd, u32 val)
+static int __secure_tz_entry(u32 cmd, u32 val, u32 id)
 {
+	int ret;
+	spin_lock(&tz_lock);
 	__iowmb();
-	return scm_call_atomic1(SCM_SVC_IO, cmd, val);
+	ret = scm_call_atomic2(SCM_SVC_IO, cmd, val, id);
+	spin_unlock(&tz_lock);
+	return ret;
 }
 #else
-static int __secure_tz_entry(u32 cmd, u32 val)
+static int __secure_tz_entry(u32 cmd, u32 val, u32 id)
 {
 	return 0;
 }
@@ -117,7 +123,7 @@
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 	struct tz_priv *priv = pwrscale->priv;
 	struct kgsl_power_stats stats;
-	int val;
+	int val, idle;
 
 	/* In "performance" mode the clock speed always stays
 	   the same */
@@ -145,19 +151,26 @@
 		priv->no_switch_cnt = 0;
 	}
 
-	val = __secure_tz_entry(TZ_UPDATE_ID,
-				stats.total_time - stats.busy_time);
+	idle = stats.total_time - stats.busy_time;
+	idle = (idle > 0) ? idle : 0;
+	val = __secure_tz_entry(TZ_UPDATE_ID, idle, device->id);
 	if (val)
 		kgsl_pwrctrl_pwrlevel_change(device,
 					     pwr->active_pwrlevel + val);
 }
 
+static void tz_busy(struct kgsl_device *device,
+	struct kgsl_pwrscale *pwrscale)
+{
+	device->on_time = ktime_to_us(ktime_get());
+}
+
 static void tz_sleep(struct kgsl_device *device,
 	struct kgsl_pwrscale *pwrscale)
 {
 	struct tz_priv *priv = pwrscale->priv;
 
-	__secure_tz_entry(TZ_RESET_ID, 0);
+	__secure_tz_entry(TZ_RESET_ID, 0, device->id);
 	priv->no_switch_cnt = 0;
 }
 
@@ -174,6 +187,7 @@
 		return -ENOMEM;
 
 	priv->governor = TZ_GOVERNOR_ONDEMAND;
+	spin_lock_init(&tz_lock);
 	kgsl_pwrscale_policy_add_files(device, pwrscale, &tz_attr_group);
 
 	return 0;
@@ -189,6 +203,7 @@
 struct kgsl_pwrscale_policy kgsl_pwrscale_policy_tz = {
 	.name = "trustzone",
 	.init = tz_init,
+	.busy = tz_busy,
 	.idle = tz_idle,
 	.sleep = tz_sleep,
 	.wake = tz_wake,
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index cf74e64..c64d6ff 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -460,6 +460,7 @@
 	z180_dev->ringbuffer.prevctx = context->id;
 
 	addcmd(&z180_dev->ringbuffer, index, cmd + ofs, cnt);
+	kgsl_pwrscale_busy(device);
 
 	/* Make sure the next ringbuffer entry has a marker */
 	addmarker(&z180_dev->ringbuffer, nextindex);
@@ -523,6 +524,7 @@
 		goto error_close_ringbuffer;
 
 	kgsl_pwrscale_init(device);
+	kgsl_pwrscale_attach_policy(device, Z180_DEFAULT_PWRSCALE_POLICY);
 
 	return status;
 
@@ -861,17 +863,17 @@
 			    struct kgsl_power_stats *stats)
 {
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+	s64 tmp = ktime_to_us(ktime_get());
 
 	if (pwr->time == 0) {
-		pwr->time = ktime_to_us(ktime_get());
+		pwr->time = tmp;
 		stats->total_time = 0;
 		stats->busy_time = 0;
 	} else {
-		s64 tmp;
-		tmp = ktime_to_us(ktime_get());
 		stats->total_time = tmp - pwr->time;
-		stats->busy_time = tmp - pwr->time;
 		pwr->time = tmp;
+		stats->busy_time = tmp - device->on_time;
+		device->on_time = tmp;
 	}
 }
 
diff --git a/drivers/gpu/msm/z180.h b/drivers/gpu/msm/z180.h
index 28b1cc6..e5c5ef3 100644
--- a/drivers/gpu/msm/z180.h
+++ b/drivers/gpu/msm/z180.h
@@ -19,6 +19,8 @@
 #define DEVICE_2D0_NAME "kgsl-2d0"
 #define DEVICE_2D1_NAME "kgsl-2d1"
 
+#define Z180_DEFAULT_PWRSCALE_POLICY  NULL
+
 struct z180_ringbuffer {
 	unsigned int prevctx;
 	struct kgsl_memdesc      cmdbufdesc;