|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern u_long get_vco(void);
|
|
|
|
extern u_long get_cclk(void);
|
|
|
|
extern u_long get_sclk(void);
|
|
|
|
|
|
|
|
#ifdef CGU_DIV
|
|
|
|
extern u_long get_sclk0(void);
|
|
|
|
extern u_long get_sclk1(void);
|
|
|
|
extern u_long get_dclk(void);
|
|
|
|
# define get_uart_clk get_sclk0
|
|
|
|
# define get_i2c_clk get_sclk0
|
|
|
|
# define get_spi_clk get_sclk0
|
|
|
|
#else
|
|
|
|
# define get_uart_clk get_sclk
|
|
|
|
# define get_i2c_clk get_sclk
|
|
|
|
# define get_spi_clk get_sclk
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|