79 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			79 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			C
		
	
	
	
 | 
						|
/*
 | 
						|
 * Copyright (C) 2012 Analog Devices Inc.
 | 
						|
 * Licensed under the GPL-2 or later.
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef __CLOCK_H__
 | 
						|
#define __CLOCK_H__
 | 
						|
 | 
						|
#include <asm/blackfin.h>
 | 
						|
#ifdef PLL_CTL
 | 
						|
#include <asm/mach-common/bits/pll.h>
 | 
						|
# define pll_is_bypassed() (bfin_read_PLL_CTL() & BYPASS)
 | 
						|
#else
 | 
						|
#include <asm/mach-common/bits/cgu.h>
 | 
						|
# define pll_is_bypassed() (bfin_read_CGU_STAT() & PLLBP)
 | 
						|
# define bfin_read_PLL_CTL() bfin_read_CGU_CTL()
 | 
						|
# define bfin_read_PLL_DIV() bfin_read_CGU_DIV()
 | 
						|
# define SSEL SYSSEL
 | 
						|
# define SSEL_P SYSSEL_P
 | 
						|
#endif
 | 
						|
 | 
						|
__attribute__((always_inline))
 | 
						|
static inline uint32_t early_division(uint32_t dividend, uint32_t divisor)
 | 
						|
{
 | 
						|
	uint32_t quotient;
 | 
						|
	uint32_t i, j;
 | 
						|
 | 
						|
	for (quotient = 1, i = 1; dividend > divisor; ++i) {
 | 
						|
		j = divisor << i;
 | 
						|
		if (j > dividend || (j & 0x80000000)) {
 | 
						|
			--i;
 | 
						|
			quotient += (1 << i);
 | 
						|
			dividend -= (divisor << i);
 | 
						|
			i = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return quotient;
 | 
						|
}
 | 
						|
 | 
						|
__attribute__((always_inline))
 | 
						|
static inline uint32_t early_get_uart_clk(void)
 | 
						|
{
 | 
						|
	uint32_t msel, pll_ctl, vco;
 | 
						|
	uint32_t div, ssel, sclk, uclk;
 | 
						|
 | 
						|
	pll_ctl = bfin_read_PLL_CTL();
 | 
						|
	msel = (pll_ctl & MSEL) >> MSEL_P;
 | 
						|
	if (msel == 0)
 | 
						|
		msel = (MSEL >> MSEL_P) + 1;
 | 
						|
 | 
						|
	vco = (CONFIG_CLKIN_HZ >> (pll_ctl & DF)) * msel;
 | 
						|
	sclk = vco;
 | 
						|
	if (!pll_is_bypassed()) {
 | 
						|
		div = bfin_read_PLL_DIV();
 | 
						|
		ssel = (div & SSEL) >> SSEL_P;
 | 
						|
#if CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS
 | 
						|
		sclk = vco/ssel;
 | 
						|
#else
 | 
						|
		sclk = early_division(vco, ssel);
 | 
						|
#endif
 | 
						|
	}
 | 
						|
	uclk = sclk;
 | 
						|
#ifdef CGU_DIV
 | 
						|
	ssel = (div & S0SEL) >> S0SEL_P;
 | 
						|
	uclk = early_division(sclk, ssel);
 | 
						|
#endif
 | 
						|
	return uclk;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef CGU_DIV
 | 
						|
# define get_uart_clk get_sclk0
 | 
						|
#else
 | 
						|
# define get_uart_clk get_sclk
 | 
						|
#endif
 | 
						|
 | 
						|
#endif
 |