commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=b1f4b27439cd9bd8001d41d9f18d3541fb4e56f0
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

Signed-off-by: Steven Miao <[email protected]>
Signed-off-by: Bob Liu <[email protected]>
---
 arch/blackfin/mach-bf609/clock.c |   83 ++++++++++++++++++++++++++-----------
 1 files changed, 58 insertions(+), 25 deletions(-)

diff --git a/arch/blackfin/mach-bf609/clock.c b/arch/blackfin/mach-bf609/clock.c
index 0fe385f..b50412c 100644
--- a/arch/blackfin/mach-bf609/clock.c
+++ b/arch/blackfin/mach-bf609/clock.c
@@ -60,7 +60,6 @@
 	}
 
 #define NEEDS_INITIALIZATION 0x11
-#define PLL_BYPASS	     0x2
 
 static LIST_HEAD(clk_list);
 
@@ -71,7 +70,7 @@ static void clk_reg_write_mask(u32 reg, uint32_t val, uint32_t mask)
 	val2 = bfin_read32(reg);
 	val2 &= ~mask;
 	val2 |= val;
-	bfin_write32(val2, reg);
+	bfin_write32(reg, val2);
 }
 
 static void clk_reg_set_bits(u32 reg, uint32_t mask)
@@ -80,7 +79,7 @@ static void clk_reg_set_bits(u32 reg, uint32_t mask)
 
 	val = bfin_read32(reg);
 	val |= mask;
-	bfin_write32(val, reg);
+	bfin_write32(reg, val);
 }
 
 static void clk_reg_clear_bits(u32 reg, uint32_t mask)
@@ -89,7 +88,7 @@ static void clk_reg_clear_bits(u32 reg, uint32_t mask)
 
 	val = bfin_read32(reg);
 	val &= ~mask;
-	bfin_write32(val, reg);
+	bfin_write32(reg, val);
 }
 
 int wait_for_pll_align(void)
@@ -101,6 +100,7 @@ int wait_for_pll_align(void)
 		printk(KERN_DEBUG "fail to align clk\n");
 		return -1;
 	}
+	return 0;
 }
 
 int clk_enable(struct clk *clk)
@@ -148,8 +148,6 @@ EXPORT_SYMBOL(clk_set_rate);
 
 unsigned long vco_get_rate(struct clk *clk)
 {
-	u32 df;
-	u32 msel;
 	return clk->rate;
 }
 
@@ -158,6 +156,9 @@ unsigned long pll_get_rate(struct clk *clk)
 	u32 df;
 	u32 msel;
 	u32 ctl = bfin_read32(CGU0_CTL);
+	u32 stat = bfin_read32(CGU0_STAT);
+	if (stat & CGU0_STAT_PLLBP)
+		return 0;
 	msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
 	df = (ctl &  CGU0_CTL_DF);
 	clk->parent->rate = clk_get_rate(clk->parent);
@@ -173,16 +174,14 @@ unsigned long pll_round_rate(struct clk *clk, unsigned long rate)
 
 int pll_set_rate(struct clk *clk, unsigned long rate)
 {
-	u32 df = 0;
 	u32 msel;
-	u32 ctl = bfin_read32(CGU0_CTL);
 	u32 stat = bfin_read32(CGU0_STAT);
 	if (!(stat & CGU0_STAT_PLLEN))
-		return -1;
+		return -EBUSY;
 	if (!(stat & CGU0_STAT_PLLLK))
-		return -1;
+		return -EBUSY;
 	if (wait_for_pll_align())
-		return -1;
+		return -EBUSY;
 	msel = rate / clk->parent->rate / 2;
 	clk_reg_write_mask(CGU0_CTL, msel << CGU0_CTL_MSEL_SHIFT,
 		CGU0_CTL_MSEL_MASK);
@@ -198,18 +197,19 @@ unsigned long cclk_get_rate(struct clk *clk)
 		return 0;
 }
 
-unsigned long drate;
 unsigned long sys_clk_get_rate(struct clk *clk)
 {
+	unsigned long drate;
 	u32 msel;
 	u32 df;
 	u32 ctl = bfin_read32(CGU0_CTL);
 	u32 div = bfin_read32(CGU0_DIV);
+	div = (div & clk->mask) >> clk->shift;
 	msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
 	df = (ctl &  CGU0_CTL_DF);
-	div = (div & clk->mask) >> clk->shift;
-	if (clk->parent->flags & PLL_BYPASS) {
-		drate = CONFIG_CLKIN_HZ / (df + 1);
+
+	if (!strcmp(clk->parent->name, "SYS_CLKIN")) {
+		drate = clk->parent->rate / (df + 1);
 		drate *=  msel;
 		drate /= div;
 		return drate;
@@ -219,12 +219,44 @@ unsigned long sys_clk_get_rate(struct clk *clk)
 	}
 }
 
+unsigned long sys_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long max_rate;
+	unsigned long drate;
+	int i;
+	u32 msel;
+	u32 df;
+	u32 ctl = bfin_read32(CGU0_CTL);
+
+	msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
+	df = (ctl &  CGU0_CTL_DF);
+	max_rate = clk->parent->rate / (df + 1) * msel;
+
+	if (rate > max_rate)
+		return 0;
+
+	for (i = 1; i < clk->mask; i++) {
+		drate = max_rate / i;
+		if (rate >= drate)
+			return drate;
+	}
+	return 0;
+}
+
 int sys_clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	u32 div;
-	div = clk->parent->rate / rate;
+	u32 div = bfin_read32(CGU0_DIV);
+	div = (div & clk->mask) >> clk->shift;
+
+	rate = clk_round_rate(clk, rate);
+
+	if (!rate)
+		return -EINVAL;
+
+	div = (clk_get_rate(clk) * div) / rate;
+
 	if (wait_for_pll_align())
-		return -1;
+		return -EBUSY;
 	clk_reg_write_mask(CGU0_DIV, div << clk->shift,
 			clk->mask);
 	clk->rate = rate;
@@ -247,6 +279,7 @@ static struct clk_ops cclk_ops = {
 static struct clk_ops sys_clk_ops = {
 	.get_rate = sys_clk_get_rate,
 	.set_rate = sys_clk_set_rate,
+	.round_rate = sys_clk_round_rate,
 };
 
 static struct clk sys_clkin = {
@@ -257,11 +290,10 @@ static struct clk sys_clkin = {
 
 static struct clk pll_clk = {
 	.name       = "PLLCLK",
-	.rate       = 1000000000,
+	.rate       = 500000000,
 	.parent     = &sys_clkin,
 	.ops = &pll_ops,
-/*	.flags = NEEDS_INITIALIZATION, */
-	.flags = PLL_BYPASS,
+	.flags = NEEDS_INITIALIZATION,
 };
 
 static struct clk cclk = {
@@ -269,9 +301,9 @@ static struct clk cclk = {
 	.rate       = 500000000,
 	.mask       = CGU0_DIV_CSEL_MASK,
 	.shift      = CGU0_DIV_CSEL_SHIFT,
-	.parent     = &pll_clk,
+	.parent     = &sys_clkin,
 	.ops	    = &sys_clk_ops,
-	.flags = PLL_BYPASS,
+	.flags = NEEDS_INITIALIZATION,
 };
 
 static struct clk cclk0 = {
@@ -291,8 +323,9 @@ static struct clk sysclk = {
 	.rate       = 500000000,
 	.mask       = CGU0_DIV_SYSSEL_MASK,
 	.shift      = CGU0_DIV_SYSSEL_SHIFT,
-	.parent     = &pll_clk,
+	.parent     = &sys_clkin,
 	.ops	    = &sys_clk_ops,
+	.flags = NEEDS_INITIALIZATION,
 };
 
 static struct clk sclk0 = {
@@ -350,7 +383,7 @@ int __init clk_init(void)
 	for (i = 0; i < ARRAY_SIZE(bf609_clks); i++) {
 		clkp = bf609_clks[i].clk;
 		if (clkp->flags & NEEDS_INITIALIZATION)
-			clk_set_rate(clkp, clkp->rate);
+			clk_get_rate(clkp);
 	}
 	clkdev_add_table(bf609_clks, ARRAY_SIZE(bf609_clks));
 	return 0;
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to