1
/* linux/arch/arm/plat-samsung/include/plat/pll.h
3
* Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
4
* http://www.samsung.com/
6
* Copyright 2008 Openmoko, Inc.
7
* Copyright 2008 Simtec Electronics
8
* Ben Dooks <ben@simtec.co.uk>
9
* http://armlinux.simtec.co.uk/
13
* This program is free software; you can redistribute it and/or modify
14
* it under the terms of the GNU General Public License version 2 as
15
* published by the Free Software Foundation.
18
#include <asm/div64.h>
20
#define S3C24XX_PLL_MDIV_MASK (0xFF)
21
#define S3C24XX_PLL_PDIV_MASK (0x1F)
22
#define S3C24XX_PLL_SDIV_MASK (0x3)
23
#define S3C24XX_PLL_MDIV_SHIFT (12)
24
#define S3C24XX_PLL_PDIV_SHIFT (4)
25
#define S3C24XX_PLL_SDIV_SHIFT (0)
27
static inline unsigned int s3c24xx_get_pll(unsigned int pllval,
30
unsigned int mdiv, pdiv, sdiv;
33
mdiv = (pllval >> S3C24XX_PLL_MDIV_SHIFT) & S3C24XX_PLL_MDIV_MASK;
34
pdiv = (pllval >> S3C24XX_PLL_PDIV_SHIFT) & S3C24XX_PLL_PDIV_MASK;
35
sdiv = (pllval >> S3C24XX_PLL_SDIV_SHIFT) & S3C24XX_PLL_SDIV_MASK;
37
fvco = (uint64_t)baseclk * (mdiv + 8);
38
do_div(fvco, (pdiv + 2) << sdiv);
40
return (unsigned int)fvco;
43
#define S3C2416_PLL_MDIV_MASK (0x3FF)
44
#define S3C2416_PLL_PDIV_MASK (0x3F)
45
#define S3C2416_PLL_SDIV_MASK (0x7)
46
#define S3C2416_PLL_MDIV_SHIFT (14)
47
#define S3C2416_PLL_PDIV_SHIFT (5)
48
#define S3C2416_PLL_SDIV_SHIFT (0)
50
static inline unsigned int s3c2416_get_pll(unsigned int pllval,
53
unsigned int mdiv, pdiv, sdiv;
56
mdiv = (pllval >> S3C2416_PLL_MDIV_SHIFT) & S3C2416_PLL_MDIV_MASK;
57
pdiv = (pllval >> S3C2416_PLL_PDIV_SHIFT) & S3C2416_PLL_PDIV_MASK;
58
sdiv = (pllval >> S3C2416_PLL_SDIV_SHIFT) & S3C2416_PLL_SDIV_MASK;
60
fvco = (uint64_t)baseclk * mdiv;
61
do_div(fvco, (pdiv << sdiv));
63
return (unsigned int)fvco;
66
#define S3C6400_PLL_MDIV_MASK (0x3FF)
67
#define S3C6400_PLL_PDIV_MASK (0x3F)
68
#define S3C6400_PLL_SDIV_MASK (0x7)
69
#define S3C6400_PLL_MDIV_SHIFT (16)
70
#define S3C6400_PLL_PDIV_SHIFT (8)
71
#define S3C6400_PLL_SDIV_SHIFT (0)
73
static inline unsigned long s3c6400_get_pll(unsigned long baseclk,
79
mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK;
80
pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK;
81
sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK;
84
do_div(fvco, (pdiv << sdiv));
86
return (unsigned long)fvco;
89
#define PLL6553X_MDIV_MASK (0x7F)
90
#define PLL6553X_PDIV_MASK (0x1F)
91
#define PLL6553X_SDIV_MASK (0x3)
92
#define PLL6553X_KDIV_MASK (0xFFFF)
93
#define PLL6553X_MDIV_SHIFT (16)
94
#define PLL6553X_PDIV_SHIFT (8)
95
#define PLL6553X_SDIV_SHIFT (0)
97
static inline unsigned long s3c_get_pll6553x(unsigned long baseclk,
98
u32 pll_con0, u32 pll_con1)
100
unsigned long result;
101
u32 mdiv, pdiv, sdiv, kdiv;
104
mdiv = (pll_con0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
105
pdiv = (pll_con0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
106
sdiv = (pll_con0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
107
kdiv = pll_con1 & PLL6553X_KDIV_MASK;
110
* We need to multiple baseclk by mdiv (the integer part) and kdiv
111
* which is in 2^16ths, so shift mdiv up (does not overflow) and
112
* add kdiv before multiplying. The use of tmp is to avoid any
113
* overflows before shifting bac down into result when multipling
114
* by the mdiv and kdiv pair.
118
tmp *= (mdiv << 16) + kdiv;
119
do_div(tmp, (pdiv << sdiv));
125
#define PLL35XX_MDIV_MASK (0x3FF)
126
#define PLL35XX_PDIV_MASK (0x3F)
127
#define PLL35XX_SDIV_MASK (0x7)
128
#define PLL35XX_MDIV_SHIFT (16)
129
#define PLL35XX_PDIV_SHIFT (8)
130
#define PLL35XX_SDIV_SHIFT (0)
132
static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con)
134
u32 mdiv, pdiv, sdiv;
137
mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
138
pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
139
sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
142
do_div(fvco, (pdiv << sdiv));
144
return (unsigned long)fvco;
147
#define PLL36XX_KDIV_MASK (0xFFFF)
148
#define PLL36XX_MDIV_MASK (0x1FF)
149
#define PLL36XX_PDIV_MASK (0x3F)
150
#define PLL36XX_SDIV_MASK (0x7)
151
#define PLL36XX_MDIV_SHIFT (16)
152
#define PLL36XX_PDIV_SHIFT (8)
153
#define PLL36XX_SDIV_SHIFT (0)
155
static inline unsigned long s5p_get_pll36xx(unsigned long baseclk,
156
u32 pll_con0, u32 pll_con1)
158
unsigned long result;
159
u32 mdiv, pdiv, sdiv, kdiv;
162
mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
163
pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
164
sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
165
kdiv = pll_con1 & PLL36XX_KDIV_MASK;
169
tmp *= (mdiv << 16) + kdiv;
170
do_div(tmp, (pdiv << sdiv));
176
#define PLL45XX_MDIV_MASK (0x3FF)
177
#define PLL45XX_PDIV_MASK (0x3F)
178
#define PLL45XX_SDIV_MASK (0x7)
179
#define PLL45XX_MDIV_SHIFT (16)
180
#define PLL45XX_PDIV_SHIFT (8)
181
#define PLL45XX_SDIV_SHIFT (0)
183
enum pll45xx_type_t {
189
static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
190
enum pll45xx_type_t pll_type)
192
u32 mdiv, pdiv, sdiv;
195
mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
196
pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
197
sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
199
if (pll_type == pll_4508)
203
do_div(fvco, (pdiv << sdiv));
205
return (unsigned long)fvco;
208
/* CON0 bit-fields */
209
#define PLL46XX_MDIV_MASK (0x1FF)
210
#define PLL46XX_PDIV_MASK (0x3F)
211
#define PLL46XX_SDIV_MASK (0x7)
212
#define PLL46XX_LOCKED_SHIFT (29)
213
#define PLL46XX_MDIV_SHIFT (16)
214
#define PLL46XX_PDIV_SHIFT (8)
215
#define PLL46XX_SDIV_SHIFT (0)
217
/* CON1 bit-fields */
218
#define PLL46XX_MRR_MASK (0x1F)
219
#define PLL46XX_MFR_MASK (0x3F)
220
#define PLL46XX_KDIV_MASK (0xFFFF)
221
#define PLL4650C_KDIV_MASK (0xFFF)
222
#define PLL46XX_MRR_SHIFT (24)
223
#define PLL46XX_MFR_SHIFT (16)
224
#define PLL46XX_KDIV_SHIFT (0)
226
enum pll46xx_type_t {
232
static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
233
u32 pll_con0, u32 pll_con1,
234
enum pll46xx_type_t pll_type)
236
unsigned long result;
237
u32 mdiv, pdiv, sdiv, kdiv;
240
mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
241
pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
242
sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
243
kdiv = pll_con1 & PLL46XX_KDIV_MASK;
245
if (pll_type == pll_4650c)
246
kdiv = pll_con1 & PLL4650C_KDIV_MASK;
248
kdiv = pll_con1 & PLL46XX_KDIV_MASK;
252
if (pll_type == pll_4600) {
253
tmp *= (mdiv << 16) + kdiv;
254
do_div(tmp, (pdiv << sdiv));
257
tmp *= (mdiv << 10) + kdiv;
258
do_div(tmp, (pdiv << sdiv));
265
#define PLL90XX_MDIV_MASK (0xFF)
266
#define PLL90XX_PDIV_MASK (0x3F)
267
#define PLL90XX_SDIV_MASK (0x7)
268
#define PLL90XX_KDIV_MASK (0xffff)
269
#define PLL90XX_LOCKED_SHIFT (29)
270
#define PLL90XX_MDIV_SHIFT (16)
271
#define PLL90XX_PDIV_SHIFT (8)
272
#define PLL90XX_SDIV_SHIFT (0)
273
#define PLL90XX_KDIV_SHIFT (0)
275
static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
276
u32 pll_con, u32 pll_conk)
278
unsigned long result;
279
u32 mdiv, pdiv, sdiv, kdiv;
282
mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
283
pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
284
sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
285
kdiv = pll_conk & PLL90XX_KDIV_MASK;
288
* We need to multiple baseclk by mdiv (the integer part) and kdiv
289
* which is in 2^16ths, so shift mdiv up (does not overflow) and
290
* add kdiv before multiplying. The use of tmp is to avoid any
291
* overflows before shifting bac down into result when multipling
292
* by the mdiv and kdiv pair.
296
tmp *= (mdiv << 16) + kdiv;
297
do_div(tmp, (pdiv << sdiv));
303
#define PLL65XX_MDIV_MASK (0x3FF)
304
#define PLL65XX_PDIV_MASK (0x3F)
305
#define PLL65XX_SDIV_MASK (0x7)
306
#define PLL65XX_MDIV_SHIFT (16)
307
#define PLL65XX_PDIV_SHIFT (8)
308
#define PLL65XX_SDIV_SHIFT (0)
310
static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
312
u32 mdiv, pdiv, sdiv;
315
mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
316
pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
317
sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
320
do_div(fvco, (pdiv << sdiv));
322
return (unsigned long)fvco;