Merge remote-tracking branch 'moduleh/module.h-split'
[linux-2.6/next.git] / arch / arm / plat-s5p / include / plat / pll.h
blob3e21b9444cc5f130b600ea4474dd0f82fb108e45
1 /* arch/arm/plat-s5p/include/plat/pll.h
3 * Copyright (c) 2009 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
6 * S5P PLL code
8 * Based on arch/arm/plat-s3c64xx/include/plat/pll.h
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.
15 #include <asm/div64.h>
17 #define PLL35XX_MDIV_MASK (0x3FF)
18 #define PLL35XX_PDIV_MASK (0x3F)
19 #define PLL35XX_SDIV_MASK (0x7)
20 #define PLL35XX_MDIV_SHIFT (16)
21 #define PLL35XX_PDIV_SHIFT (8)
22 #define PLL35XX_SDIV_SHIFT (0)
24 static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con)
26 u32 mdiv, pdiv, sdiv;
27 u64 fvco = baseclk;
29 mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
30 pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
31 sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
33 fvco *= mdiv;
34 do_div(fvco, (pdiv << sdiv));
36 return (unsigned long)fvco;
39 #define PLL36XX_KDIV_MASK (0xFFFF)
40 #define PLL36XX_MDIV_MASK (0x1FF)
41 #define PLL36XX_PDIV_MASK (0x3F)
42 #define PLL36XX_SDIV_MASK (0x7)
43 #define PLL36XX_MDIV_SHIFT (16)
44 #define PLL36XX_PDIV_SHIFT (8)
45 #define PLL36XX_SDIV_SHIFT (0)
47 static inline unsigned long s5p_get_pll36xx(unsigned long baseclk,
48 u32 pll_con0, u32 pll_con1)
50 unsigned long result;
51 u32 mdiv, pdiv, sdiv, kdiv;
52 u64 tmp;
54 mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
55 pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
56 sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
57 kdiv = pll_con1 & PLL36XX_KDIV_MASK;
59 tmp = baseclk;
61 tmp *= (mdiv << 16) + kdiv;
62 do_div(tmp, (pdiv << sdiv));
63 result = tmp >> 16;
65 return result;
68 #define PLL45XX_MDIV_MASK (0x3FF)
69 #define PLL45XX_PDIV_MASK (0x3F)
70 #define PLL45XX_SDIV_MASK (0x7)
71 #define PLL45XX_MDIV_SHIFT (16)
72 #define PLL45XX_PDIV_SHIFT (8)
73 #define PLL45XX_SDIV_SHIFT (0)
75 enum pll45xx_type_t {
76 pll_4500,
77 pll_4502,
78 pll_4508
81 static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
82 enum pll45xx_type_t pll_type)
84 u32 mdiv, pdiv, sdiv;
85 u64 fvco = baseclk;
87 mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
88 pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
89 sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
91 if (pll_type == pll_4508)
92 sdiv = sdiv - 1;
94 fvco *= mdiv;
95 do_div(fvco, (pdiv << sdiv));
97 return (unsigned long)fvco;
100 #define PLL46XX_KDIV_MASK (0xFFFF)
101 #define PLL4650C_KDIV_MASK (0xFFF)
102 #define PLL46XX_MDIV_MASK (0x1FF)
103 #define PLL46XX_PDIV_MASK (0x3F)
104 #define PLL46XX_SDIV_MASK (0x7)
105 #define PLL46XX_MDIV_SHIFT (16)
106 #define PLL46XX_PDIV_SHIFT (8)
107 #define PLL46XX_SDIV_SHIFT (0)
109 enum pll46xx_type_t {
110 pll_4600,
111 pll_4650,
112 pll_4650c,
115 static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
116 u32 pll_con0, u32 pll_con1,
117 enum pll46xx_type_t pll_type)
119 unsigned long result;
120 u32 mdiv, pdiv, sdiv, kdiv;
121 u64 tmp;
123 mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
124 pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
125 sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
127 if (pll_type == pll_4650c)
128 kdiv = pll_con1 & PLL4650C_KDIV_MASK;
129 else
130 kdiv = pll_con1 & PLL46XX_KDIV_MASK;
132 tmp = baseclk;
134 if (pll_type == pll_4600) {
135 tmp *= (mdiv << 16) + kdiv;
136 do_div(tmp, (pdiv << sdiv));
137 result = tmp >> 16;
138 } else {
139 tmp *= (mdiv << 10) + kdiv;
140 do_div(tmp, (pdiv << sdiv));
141 result = tmp >> 10;
144 return result;
147 #define PLL90XX_MDIV_MASK (0xFF)
148 #define PLL90XX_PDIV_MASK (0x3F)
149 #define PLL90XX_SDIV_MASK (0x7)
150 #define PLL90XX_KDIV_MASK (0xffff)
151 #define PLL90XX_MDIV_SHIFT (16)
152 #define PLL90XX_PDIV_SHIFT (8)
153 #define PLL90XX_SDIV_SHIFT (0)
154 #define PLL90XX_KDIV_SHIFT (0)
156 static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
157 u32 pll_con, u32 pll_conk)
159 unsigned long result;
160 u32 mdiv, pdiv, sdiv, kdiv;
161 u64 tmp;
163 mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
164 pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
165 sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
166 kdiv = pll_conk & PLL90XX_KDIV_MASK;
168 /* We need to multiple baseclk by mdiv (the integer part) and kdiv
169 * which is in 2^16ths, so shift mdiv up (does not overflow) and
170 * add kdiv before multiplying. The use of tmp is to avoid any
171 * overflows before shifting bac down into result when multipling
172 * by the mdiv and kdiv pair.
175 tmp = baseclk;
176 tmp *= (mdiv << 16) + kdiv;
177 do_div(tmp, (pdiv << sdiv));
178 result = tmp >> 16;
180 return result;
183 #define PLL65XX_MDIV_MASK (0x3FF)
184 #define PLL65XX_PDIV_MASK (0x3F)
185 #define PLL65XX_SDIV_MASK (0x7)
186 #define PLL65XX_MDIV_SHIFT (16)
187 #define PLL65XX_PDIV_SHIFT (8)
188 #define PLL65XX_SDIV_SHIFT (0)
190 static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
192 u32 mdiv, pdiv, sdiv;
193 u64 fvco = baseclk;
195 mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
196 pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
197 sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
199 fvco *= mdiv;
200 do_div(fvco, (pdiv << sdiv));
202 return (unsigned long)fvco;