| 
					
				 | 
			
			
				@@ -121,3 +121,136 @@ static unsigned long pll_get_rate(struct clk *clk, unsigned long control) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	rate = clk->parent->get_rate(clk->parent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	rate = (rate + div / 2) / div; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	rate *= mul; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return rate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static long pll_set_rate(struct clk *clk, unsigned long rate, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 u32 *pll_ctrl) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long mul; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long mul_best_fit = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long div; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long div_min; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long div_max; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long div_best_fit = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long base; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long pll_in; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long actual = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long rate_error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long rate_error_prev = ~0UL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 ctrl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Rate must be between 80 MHz and 200 Mhz. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (rate < 80000000UL || rate > 200000000UL) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -EINVAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ctrl = PM_BF(PLLOPT, 4); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	base = clk->parent->get_rate(clk->parent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* PLL input frequency must be between 6 MHz and 32 MHz. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	div_min = DIV_ROUND_UP(base, 32000000UL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	div_max = base / 6000000UL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (div_max < div_min) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -EINVAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for (div = div_min; div <= div_max; div++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pll_in = (base + div / 2) / div; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		mul = (rate + pll_in / 2) / pll_in; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (mul == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		actual = pll_in * mul; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		rate_error = abs(actual - rate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (rate_error < rate_error_prev) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			mul_best_fit = mul; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			div_best_fit = div; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			rate_error_prev = rate_error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (rate_error == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (div_best_fit == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -EINVAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ctrl |= PM_BF(PLLMUL, mul_best_fit - 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ctrl |= PM_BF(PLLDIV, div_best_fit - 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ctrl |= PM_BF(PLLCOUNT, 16); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (clk->parent == &osc1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		ctrl |= PM_BIT(PLLOSC); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	*pll_ctrl = ctrl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return actual; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static unsigned long pll0_get_rate(struct clk *clk) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 control; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	control = pm_readl(PLL0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return pll_get_rate(clk, control); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void pll1_mode(struct clk *clk, int enabled) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long timeout; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 ctrl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ctrl = pm_readl(PLL1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (enabled) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (!PM_BFEXT(PLLMUL, ctrl) && !PM_BFEXT(PLLDIV, ctrl)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			pr_debug("clk %s: failed to enable, rate not set\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					clk->name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		ctrl |= PM_BIT(PLLEN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pm_writel(PLL1, ctrl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/* Wait for PLL lock. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for (timeout = 10000; timeout; timeout--) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			status = pm_readl(ISR); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (status & PM_BIT(LOCK1)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			udelay(10); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (!(status & PM_BIT(LOCK1))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			printk(KERN_ERR "clk %s: timeout waiting for lock\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					clk->name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		ctrl &= ~PM_BIT(PLLEN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pm_writel(PLL1, ctrl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static unsigned long pll1_get_rate(struct clk *clk) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 control; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	control = pm_readl(PLL1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return pll_get_rate(clk, control); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static long pll1_set_rate(struct clk *clk, unsigned long rate, int apply) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 ctrl = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long actual_rate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	actual_rate = pll_set_rate(clk, rate, &ctrl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (apply) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (actual_rate != rate) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return -EINVAL; 
			 |