Merge branch 'next-samsung-devel' into next-samsung-devel-2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / arm / plat-s5p / include / plat / pll.h
blob002ec9f28f18b0c3e09ecee791d3e6891d92d08d
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 /* CON0 bit-fields */
101 #define PLL46XX_MDIV_MASK (0x1FF)
102 #define PLL46XX_PDIV_MASK (0x3F)
103 #define PLL46XX_SDIV_MASK (0x7)
104 #define PLL46XX_LOCKED_SHIFT (29)
105 #define PLL46XX_MDIV_SHIFT (16)
106 #define PLL46XX_PDIV_SHIFT (8)
107 #define PLL46XX_SDIV_SHIFT (0)
109 /* CON1 bit-fields */
110 #define PLL46XX_MRR_MASK (0x1F)
111 #define PLL46XX_MFR_MASK (0x3F)
112 #define PLL46XX_KDIV_MASK (0xFFFF)
113 #define PLL4650C_KDIV_MASK (0xFFF)
114 #define PLL46XX_MRR_SHIFT (24)
115 #define PLL46XX_MFR_SHIFT (16)
116 #define PLL46XX_KDIV_SHIFT (0)
118 enum pll46xx_type_t {
119 pll_4600,
120 pll_4650,
121 pll_4650c,
124 static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
125 u32 pll_con0, u32 pll_con1,
126 enum pll46xx_type_t pll_type)
128 unsigned long result;
129 u32 mdiv, pdiv, sdiv, kdiv;
130 u64 tmp;
132 mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
133 pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
134 sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
136 if (pll_type == pll_4650c)
137 kdiv = pll_con1 & PLL4650C_KDIV_MASK;
138 else
139 kdiv = pll_con1 & PLL46XX_KDIV_MASK;
141 tmp = baseclk;
143 if (pll_type == pll_4600) {
144 tmp *= (mdiv << 16) + kdiv;
145 do_div(tmp, (pdiv << sdiv));
146 result = tmp >> 16;
147 } else {
148 tmp *= (mdiv << 10) + kdiv;
149 do_div(tmp, (pdiv << sdiv));
150 result = tmp >> 10;
153 return result;
156 #define PLL90XX_MDIV_MASK (0xFF)
157 #define PLL90XX_PDIV_MASK (0x3F)
158 #define PLL90XX_SDIV_MASK (0x7)
159 #define PLL90XX_KDIV_MASK (0xffff)
160 #define PLL90XX_LOCKED_SHIFT (29)
161 #define PLL90XX_MDIV_SHIFT (16)
162 #define PLL90XX_PDIV_SHIFT (8)
163 #define PLL90XX_SDIV_SHIFT (0)
164 #define PLL90XX_KDIV_SHIFT (0)
166 static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
167 u32 pll_con, u32 pll_conk)
169 unsigned long result;
170 u32 mdiv, pdiv, sdiv, kdiv;
171 u64 tmp;
173 mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
174 pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
175 sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
176 kdiv = pll_conk & PLL90XX_KDIV_MASK;
178 /* We need to multiple baseclk by mdiv (the integer part) and kdiv
179 * which is in 2^16ths, so shift mdiv up (does not overflow) and
180 * add kdiv before multiplying. The use of tmp is to avoid any
181 * overflows before shifting bac down into result when multipling
182 * by the mdiv and kdiv pair.
185 tmp = baseclk;
186 tmp *= (mdiv << 16) + kdiv;
187 do_div(tmp, (pdiv << sdiv));
188 result = tmp >> 16;
190 return result;
193 #define PLL65XX_MDIV_MASK (0x3FF)
194 #define PLL65XX_PDIV_MASK (0x3F)
195 #define PLL65XX_SDIV_MASK (0x7)
196 #define PLL65XX_MDIV_SHIFT (16)
197 #define PLL65XX_PDIV_SHIFT (8)
198 #define PLL65XX_SDIV_SHIFT (0)
200 static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
202 u32 mdiv, pdiv, sdiv;
203 u64 fvco = baseclk;
205 mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
206 pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
207 sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
209 fvco *= mdiv;
210 do_div(fvco, (pdiv << sdiv));
212 return (unsigned long)fvco;