MMP3: QSEVEN adding qos and inactivity timer for GC

   port from Q7 BetaRC patch 5997
   Signed-off-by: dipen <dpatel@marvell.com>
   Signed-off-by: frankf <frankf@marvell.com>
(cherry picked from commit accc5f8da4cd6f5c8da6791f650635719ad6e128)

Signed-off-by: Wen-chien Jesse Sung <jesse.sung@canonical.com>
diff --git a/arch/arm/mach-mmp/clock-mmp3.c b/arch/arm/mach-mmp/clock-mmp3.c
index 67db843..14af35a 100644
--- a/arch/arm/mach-mmp/clock-mmp3.c
+++ b/arch/arm/mach-mmp/clock-mmp3.c
@@ -30,6 +30,7 @@
 #include <plat/devfreq.h>
 #include <linux/reboot.h>
 #include "common.h"
+#include <linux/pm_qos_params.h>
 
 #define CORE_NUM			3
 #define PMUA_CC				APMU_REG(0x4)
@@ -1153,6 +1154,15 @@
 	__raw_writel(tmp, clk->clk_rst);\
 }
 
+struct pm_qos_request_list gc_qos_ddrfreq_min;
+static struct timer_list gc_idle_timer;
+static bool gc_force_high_rate = false;
+static void gc_set_constraint(unsigned long data)
+{
+       gc_force_high_rate = true;
+       pm_qos_update_request(&gc_qos_ddrfreq_min, PM_QOS_DEFAULT_VALUE);
+}
+
 static void gc_clk_init(struct clk *clk)
 {
 	clk->rate = clk_get_rate(&mmp3_clk_pll1_clkoutp) / 2;
@@ -1160,8 +1170,67 @@
 	clk->div = 2;
 	clk->mul = 1;
 	clk_reparent(clk, &mmp3_clk_pll1_clkoutp);
+	init_timer(&gc_idle_timer);
+	gc_idle_timer.function = gc_set_constraint;
+	gc_idle_timer.data = 1;
+	gc_idle_timer.expires = 1000 + jiffies;
+	gc_force_high_rate = true;
+	pm_qos_add_request(&gc_qos_ddrfreq_min, PM_QOS_DDR_DEVFREQ_MIN,
+	PM_QOS_DEFAULT_VALUE);
 }
 
+static int gc_clk_setrate(struct clk *clk, unsigned long rate)
+{
+	unsigned long rate1 = rate;
+	if (gc_force_high_rate == true)
+		rate1 = 533333333;
+
+	clk->mul = 1;
+	if (rate1 == clk_get_rate(&mmp3_clk_pll1)/8) {
+		clk->enable_val = PLL1D6;
+		clk->div = 8;
+		clk_reparent(clk, &mmp3_clk_pll1);
+	} else if (rate1 == clk_get_rate(&mmp3_clk_pll1)/4) {
+		clk->enable_val = PLL1D4;
+		clk->div = 4;
+		clk_reparent(clk, &mmp3_clk_pll1);
+	} else if (rate1 == clk_get_rate(&mmp3_clk_pll1_clkoutp)/3) {
+		clk->enable_val = PLL1D2;
+		clk->div = 3;
+		clk_reparent(clk, &mmp3_clk_pll1_clkoutp);
+	} else if (rate1 == clk_get_rate(&mmp3_clk_pll1)/2) {
+		clk->enable_val = PLL1D2;
+		clk->div = 2;
+		clk_reparent(clk, &mmp3_clk_pll1);
+	} else if (rate1 == clk_get_rate(&mmp3_clk_pll2_clkoutp)/2) {
+		clk->enable_val = PLL1D2;
+		clk->div = 2;
+		clk_reparent(clk, &mmp3_clk_pll2_clkoutp);
+	} else if (rate1 == clk_get_rate(&mmp3_clk_pll1_clkoutp)/2) {
+		clk->enable_val = PLL1D2;
+		clk->div = 2;
+		clk_reparent(clk, &mmp3_clk_pll1_clkoutp);
+	} else if (rate1 == clk_get_rate(&mmp3_clk_pll2)/2) {
+		clk->enable_val = PLL2D2;
+		clk->div = 2;
+		clk_reparent(clk, &mmp3_clk_pll2);
+	} else if (rate1 == clk_get_rate(&mmp3_clk_pll1)) {
+		clk->enable_val = PLL1D2;
+		clk->div = 1;
+		clk_reparent(clk, &mmp3_clk_pll1);
+	} else {
+		pr_err("%s: unexpected gc clock rate %ld\n", __func__, rate1);
+		BUG();
+	}
+
+	return 0;
+}
+
+
+
+
+
+
 static int gc_clk_enable(struct clk *clk)
 {
 	unsigned long gc_rate_cfg;
@@ -1171,6 +1240,13 @@
 	 * different gc clock rate.
 	 */
 
+	pm_qos_update_request(&gc_qos_ddrfreq_min, DDR_CONSTRAINT_LVL1);
+
+	if (gc_force_high_rate == true)
+		gc_clk_setrate(clk, 533333333);
+	del_timer(&gc_idle_timer);
+	gc_force_high_rate = false;
+
 	i = 0;
 	while ((clk->inputs[i].input != clk->parent) && clk->inputs[i].input)
 		i++;
@@ -1195,6 +1271,13 @@
 {
 	GC_SET_BITS(0, GC2D_AXICLK_EN | GC3D_AXICLK_EN | GC2D3D_CLK_EN\
 			| GC2D_CLK_EN);
+	gc_idle_timer.expires = 1000 + jiffies;
+	add_timer(&gc_idle_timer);
+/*
++       GC_SET_BITS(0,GC2D3D_CLK_EN | GC2D_CLK_EN);
++       GC_SET_BITS(0, GC2D_AXICLK_EN | GC3D_AXICLK_EN);
+*/
+
 }
 
 static long gc_clk_round_rate(struct clk *clk, unsigned long rate)
@@ -1217,6 +1300,8 @@
 		return clk_get_rate(&mmp3_clk_pll1); /* 800M */
 }
 
+
+/*
 static int gc_clk_setrate(struct clk *clk, unsigned long rate)
 {
 	clk->mul = 1;
@@ -1259,6 +1344,7 @@
 
 	return 0;
 }
+*/
 
 int get_gcu_freqs_table(unsigned long *gcu_freqs_table, unsigned int *item_counts,
 		unsigned int max_item_counts)