blob: df6cd68171ba75e10d6ef0d1f41d238459c72596 [file] [log] [blame]
Sonic Zhang79f2b392013-02-05 19:10:34 +08001
2/*
3 * Copyright (C) 2012 Analog Devices Inc.
4 * Licensed under the GPL-2 or later.
5 */
6
7#ifndef __CLOCK_H__
8#define __CLOCK_H__
9
10#include <asm/blackfin.h>
11#ifdef PLL_CTL
12#include <asm/mach-common/bits/pll.h>
13# define pll_is_bypassed() (bfin_read_PLL_STAT() & DF)
14#else
15#include <asm/mach-common/bits/cgu.h>
16# define pll_is_bypassed() (bfin_read_CGU_STAT() & PLLBP)
17# define bfin_read_PLL_CTL() bfin_read_CGU_CTL()
18# define bfin_read_PLL_DIV() bfin_read_CGU_DIV()
19# define SSEL SYSSEL
20# define SSEL_P SYSSEL_P
21#endif
22
23__attribute__((always_inline))
24static inline uint32_t early_division(uint32_t dividend, uint32_t divisor)
25{
26 uint32_t quotient;
27 uint32_t i, j;
28
29 for (quotient = 1, i = 1; dividend > divisor; ++i) {
30 j = divisor << i;
31 if (j > dividend || (j & 0x80000000)) {
32 --i;
33 quotient += (1 << i);
34 dividend -= (divisor << i);
35 i = 0;
36 }
37 }
38
39 return quotient;
40}
41
42__attribute__((always_inline))
43static inline uint32_t early_get_uart_clk(void)
44{
45 uint32_t msel, pll_ctl, vco;
46 uint32_t div, ssel, sclk, uclk;
47
48 pll_ctl = bfin_read_PLL_CTL();
49 msel = (pll_ctl & MSEL) >> MSEL_P;
50 if (msel == 0)
51 msel = (MSEL >> MSEL_P) + 1;
52
53 vco = (CONFIG_CLKIN_HZ >> (pll_ctl & DF)) * msel;
54 sclk = vco;
55 if (!pll_is_bypassed()) {
56 div = bfin_read_PLL_DIV();
57 ssel = (div & SSEL) >> SSEL_P;
58 sclk = early_division(vco, ssel);
59 }
60 uclk = sclk;
61#ifdef CGU_DIV
62 ssel = (div & S0SEL) >> S0SEL_P;
63 uclk = early_division(sclk, ssel);
64#endif
65 return uclk;
66}
67
68#ifdef CGU_DIV
69# define get_uart_clk get_sclk0
70#else
71# define get_uart_clk get_sclk
72#endif
73
74#endif