blob: f1fcd404993de3c70bef6d188a3fb91fc4909d73 [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>
Sonic Zhangab80b652012-11-30 17:39:32 +080013# define pll_is_bypassed() (bfin_read_PLL_CTL() & BYPASS)
Sonic Zhang79f2b392013-02-05 19:10:34 +080014#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;
Sonic Zhangab80b652012-11-30 17:39:32 +080058#if CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS
59 sclk = vco/ssel;
60#else
Sonic Zhang79f2b392013-02-05 19:10:34 +080061 sclk = early_division(vco, ssel);
Sonic Zhangab80b652012-11-30 17:39:32 +080062#endif
Sonic Zhang79f2b392013-02-05 19:10:34 +080063 }
64 uclk = sclk;
65#ifdef CGU_DIV
66 ssel = (div & S0SEL) >> S0SEL_P;
67 uclk = early_division(sclk, ssel);
68#endif
69 return uclk;
70}
71
72#ifdef CGU_DIV
73# define get_uart_clk get_sclk0
74#else
75# define get_uart_clk get_sclk
76#endif
77
78#endif