Merge branch 'msm-core' of git://codeaurora.org/quic/kernel/dwalker/linux-msm
[pandora-kernel.git] / arch / arm / plat-s5p / include / plat / pll.h
1 /* arch/arm/plat-s5p/include/plat/pll.h
2  *
3  * Copyright (c) 2009 Samsung Electronics Co., Ltd.
4  *              http://www.samsung.com/
5  *
6  * S5P PLL code
7  *
8  * Based on arch/arm/plat-s3c64xx/include/plat/pll.h
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13 */
14
15 #define PLL45XX_MDIV_MASK       (0x3FF)
16 #define PLL45XX_PDIV_MASK       (0x3F)
17 #define PLL45XX_SDIV_MASK       (0x7)
18 #define PLL45XX_MDIV_SHIFT      (16)
19 #define PLL45XX_PDIV_SHIFT      (8)
20 #define PLL45XX_SDIV_SHIFT      (0)
21
22 #include <asm/div64.h>
23
24 enum pll45xx_type_t {
25         pll_4500,
26         pll_4502,
27         pll_4508
28 };
29
30 static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
31                                             enum pll45xx_type_t pll_type)
32 {
33         u32 mdiv, pdiv, sdiv;
34         u64 fvco = baseclk;
35
36         mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
37         pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
38         sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
39
40         if (pll_type == pll_4508)
41                 sdiv = sdiv - 1;
42
43         fvco *= mdiv;
44         do_div(fvco, (pdiv << sdiv));
45
46         return (unsigned long)fvco;
47 }
48
49 #define PLL90XX_MDIV_MASK       (0xFF)
50 #define PLL90XX_PDIV_MASK       (0x3F)
51 #define PLL90XX_SDIV_MASK       (0x7)
52 #define PLL90XX_KDIV_MASK       (0xffff)
53 #define PLL90XX_MDIV_SHIFT      (16)
54 #define PLL90XX_PDIV_SHIFT      (8)
55 #define PLL90XX_SDIV_SHIFT      (0)
56 #define PLL90XX_KDIV_SHIFT      (0)
57
58 static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
59                                             u32 pll_con, u32 pll_conk)
60 {
61         unsigned long result;
62         u32 mdiv, pdiv, sdiv, kdiv;
63         u64 tmp;
64
65         mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
66         pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
67         sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
68         kdiv = pll_conk & PLL90XX_KDIV_MASK;
69
70         /* We need to multiple baseclk by mdiv (the integer part) and kdiv
71          * which is in 2^16ths, so shift mdiv up (does not overflow) and
72          * add kdiv before multiplying. The use of tmp is to avoid any
73          * overflows before shifting bac down into result when multipling
74          * by the mdiv and kdiv pair.
75          */
76
77         tmp = baseclk;
78         tmp *= (mdiv << 16) + kdiv;
79         do_div(tmp, (pdiv << sdiv));
80         result = tmp >> 16;
81
82         return result;
83 }
84
85 #define PLL65XX_MDIV_MASK       (0x3FF)
86 #define PLL65XX_PDIV_MASK       (0x3F)
87 #define PLL65XX_SDIV_MASK       (0x7)
88 #define PLL65XX_MDIV_SHIFT      (16)
89 #define PLL65XX_PDIV_SHIFT      (8)
90 #define PLL65XX_SDIV_SHIFT      (0)
91
92 static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
93 {
94         u32 mdiv, pdiv, sdiv;
95         u64 fvco = baseclk;
96
97         mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
98         pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
99         sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
100
101         fvco *= mdiv;
102         do_div(fvco, (pdiv << sdiv));
103
104         return (unsigned long)fvco;
105 }