From: xxx <xxx@rock-chips.com>
Date: Fri, 6 Apr 2012 11:28:05 +0000 (-0700)
Subject: insure a clk rate not overflow,when change the clk parent
X-Git-Tag: firefly_0821_release~9458
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=9a2f6fdad48c76daa0743718be8c589a83ee3e75;p=firefly-linux-kernel-4.4.55.git

insure a clk rate not overflow,when change the clk parent
---

diff --git a/arch/arm/mach-rk30/clock_data.c b/arch/arm/mach-rk30/clock_data.c
index ac076f100159..c16e111971a0 100755
--- a/arch/arm/mach-rk30/clock_data.c
+++ b/arch/arm/mach-rk30/clock_data.c
@@ -178,7 +178,7 @@ void rk30_clkdev_add(struct clk_lookup *cl);
 
 
 #define PLLS_IN_NORM(pll_id) (((cru_readl(CRU_MODE_CON)&PLL_MODE_MSK(pll_id))==(PLL_MODE_NORM(pll_id)&PLL_MODE_MSK(pll_id)))\
-	&&!(PLL_CONS(pll_id,3)&PLL_BYPASS))
+	&&!(cru_readl(PLL_CONS(pll_id,3))&PLL_BYPASS))
 
 
 
@@ -294,7 +294,7 @@ struct clk *get_freediv_parents_div(struct clk *clk,unsigned long rate,u32 *div_
 	u32 i;
 	
 	if(clk->rate==rate)
-		return 0;
+		return clk->parent;
 	for(i=0;i<2;i++)
 	{
 		div[i]=clk_get_freediv(rate,clk->parents[i]->rate,clk->div_max);
@@ -316,16 +316,24 @@ struct clk *get_freediv_parents_div(struct clk *clk,unsigned long rate,u32 *div_
 static int clkset_rate_freediv_autosel_parents(struct clk *clk, unsigned long rate)
 {
 	struct clk *p_clk;
-	u32 div;
+	u32 div,old_div;
 	int ret=0;
+	if(clk->rate==rate)
+		return 0;
 	p_clk=get_freediv_parents_div(clk,rate,&div);
 	
-	CRU_PRINTK_ERR("%s %lu,form %s\n",clk->name,rate,p_clk->name);
 	if(!p_clk)
 		return -ENOENT;
 	
+	CRU_PRINTK_ERR("%s %lu,form %s\n",clk->name,rate,p_clk->name);
 	if (clk->parent != p_clk)
 	{
+		old_div=CRU_GET_REG_BIYS_VAL(cru_readl(clk->clksel_con),clk->div_shift,clk->div_mask)+1;
+
+		if(div>old_div)
+		{
+			set_cru_bits_w_msk(div-1,clk->div_mask,clk->div_shift,clk->clksel_con);
+		}
 		ret=clk_set_parent_nolock(clk,p_clk);
 		if(ret)
 		{
@@ -342,7 +350,8 @@ static int clkset_rate_freediv_autosel_parents(struct clk *clk, unsigned long ra
 static int clk_freediv_autosel_parents_set_fixed_rate(struct clk *clk, unsigned long rate)
 {
 	struct clk *p_clk;
-	u32 div;
+	u32 div,old_div;
+	int ret;
 	p_clk=get_freediv_parents_div(clk,rate,&div);
 
 	if(!p_clk)
@@ -352,7 +361,20 @@ static int clk_freediv_autosel_parents_set_fixed_rate(struct clk *clk, unsigned
 	return -ENOENT;
 	
 	if (clk->parent != p_clk)
-	return clk_set_parent_nolock(clk,p_clk);
+	{
+		old_div=CRU_GET_REG_BIYS_VAL(cru_readl(clk->clksel_con),
+									clk->div_shift,clk->div_mask)+1;
+		if(div>old_div)
+		{
+			set_cru_bits_w_msk(div-1,clk->div_mask,clk->div_shift,clk->clksel_con);
+		}
+		ret=clk_set_parent_nolock(clk,p_clk);
+		if (ret)
+		{
+			CRU_PRINTK_DBG("%s can't get rate%lu,reparent err\n",clk->name,rate);
+			return ret;
+		}
+	}
 	//set div
 	set_cru_bits_w_msk(div-1,clk->div_mask,clk->div_shift,clk->clksel_con);
 	return 0;	
@@ -1279,6 +1301,16 @@ static int i2s_set_rate(struct clk *clk, unsigned long rate)
 	CRU_PRINTK_DBG(" %s set rate=%lu parent %s(old %s)\n",
 		clk->name,rate,parent->name,clk->parent->name);
 
+	if(parent!=clk->parents[I2S_SRC_12M])
+	{
+		ret = clk_set_rate_nolock(parent,rate);//div 1:1
+		if (ret)
+		{
+			CRU_PRINTK_DBG("%s set rate%lu err\n",clk->name,rate);
+			return ret;
+		}
+	}
+
 	if (clk->parent != parent)
 	{
 		ret = clk_set_parent_nolock(clk, parent);
@@ -1288,11 +1320,7 @@ static int i2s_set_rate(struct clk *clk, unsigned long rate)
 			return ret;
 		}
 	}
-	if(parent!=clk->parents[I2S_SRC_12M])
-	{
-		ret = clk_set_rate_nolock(parent,rate);//div 1:1
-	}
-	
+
 	return ret;
 };
 
@@ -1599,6 +1627,16 @@ static int clk_uart_set_rate(struct clk *clk, unsigned long rate)
 		clk->name,rate,parent->name,clk->parent->name);
 
 	
+	if(parent!=clk->parents[UART_SRC_24M])
+	{
+		ret = clk_set_rate_nolock(parent,rate);	
+		if (ret)
+		{
+			CRU_PRINTK_DBG("%s set rate%lu err\n",clk->name,rate);
+			return ret;
+		}
+	}
+	
 	if (clk->parent != parent)
 	{
 		ret = clk_set_parent_nolock(clk, parent);
@@ -1609,10 +1647,6 @@ static int clk_uart_set_rate(struct clk *clk, unsigned long rate)
 		}
 	}
 	
-	if(parent!=clk->parents[UART_SRC_24M])
-	{
-		ret = clk_set_rate_nolock(parent,rate);	
-	}
 
 	return ret;
 }
@@ -1832,7 +1866,13 @@ static int clk_hsadc_set_rate(struct clk *clk, unsigned long rate)
 
 	CRU_PRINTK_DBG(" %s set rate=%lu parent %s(old %s)\n",
 		clk->name,rate,parent->name,clk->parent->name);
-	
+
+	ret = clk_set_rate_nolock(parent,rate);
+	if (ret)
+	{
+		CRU_PRINTK_ERR("%s set rate%lu err\n",clk->name,rate);
+		return ret;
+	}
 	if (clk->parent != parent)
 	{
 		ret = clk_set_parent_nolock(clk, parent);
@@ -1842,7 +1882,6 @@ static int clk_hsadc_set_rate(struct clk *clk, unsigned long rate)
 			return ret;
 		}
 	}
-	ret = clk_set_rate_nolock(parent,rate);
 	return ret;
 }
 
@@ -1908,6 +1947,15 @@ static int dclk_lcdc_set_rate(struct clk *clk, unsigned long rate)
 	CRU_PRINTK_DBG(" %s set rate=%lu parent %s(old %s)\n",
 			clk->name,rate,parent->name,clk->parent->name);
 
+	if(parent!=clk->parents[1])
+	{
+		ret = clk_set_rate_nolock(parent,rate);//div 1:1
+		if (ret)
+		{
+			CRU_PRINTK_DBG("%s set rate=%lu err\n",clk->name,rate);
+			return ret;
+		}
+	}
 	if (clk->parent != parent)
 	{
 		ret = clk_set_parent_nolock(clk, parent);
@@ -1917,10 +1965,6 @@ static int dclk_lcdc_set_rate(struct clk *clk, unsigned long rate)
 			return ret;
 		}
 	}
-	if(parent!=clk->parents[1])
-	{
-		ret = clk_set_rate_nolock(parent,rate);//div 1:1
-	}
 	return ret;
 }
 
diff --git a/arch/arm/mach-rk30/include/mach/cru.h b/arch/arm/mach-rk30/include/mach/cru.h
index 5c462369e220..c0e809c69036 100755
--- a/arch/arm/mach-rk30/include/mach/cru.h
+++ b/arch/arm/mach-rk30/include/mach/cru.h
@@ -33,7 +33,7 @@ enum rk_plls_id {
 #define CRU_GLB_CNT_TH		(0x140)
 
 /********************************************************************/
-
+#define CRU_GET_REG_BIYS_VAL(reg,bits_shift, msk)	(((reg) >> (bits_shift))&(msk))
 #define CRU_W_MSK(bits_shift, msk)	((msk) << ((bits_shift) + 16))
 #define CRU_SET_BITS(val,bits_shift, msk)	(((val)&(msk)) << (bits_shift))