Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
blackfin
mach-bf609
clock.c
Go to the documentation of this file.
1
#include <linux/module.h>
2
#include <linux/kernel.h>
3
#include <linux/list.h>
4
#include <linux/errno.h>
5
#include <
linux/err.h
>
6
#include <linux/string.h>
7
#include <
linux/clk.h
>
8
#include <
linux/mutex.h
>
9
#include <
linux/spinlock.h
>
10
#include <
linux/debugfs.h
>
11
#include <linux/device.h>
12
#include <
linux/init.h
>
13
#include <
linux/timer.h
>
14
#include <
linux/io.h
>
15
#include <
linux/seq_file.h
>
16
#include <
linux/clkdev.h
>
17
18
#include <
asm/clocks.h
>
19
20
#define CGU0_CTL_DF (1 << 0)
21
22
#define CGU0_CTL_MSEL_SHIFT 8
23
#define CGU0_CTL_MSEL_MASK (0x7f << 8)
24
25
#define CGU0_STAT_PLLEN (1 << 0)
26
#define CGU0_STAT_PLLBP (1 << 1)
27
#define CGU0_STAT_PLLLK (1 << 2)
28
#define CGU0_STAT_CLKSALGN (1 << 3)
29
#define CGU0_STAT_CCBF0 (1 << 4)
30
#define CGU0_STAT_CCBF1 (1 << 5)
31
#define CGU0_STAT_SCBF0 (1 << 6)
32
#define CGU0_STAT_SCBF1 (1 << 7)
33
#define CGU0_STAT_DCBF (1 << 8)
34
#define CGU0_STAT_OCBF (1 << 9)
35
#define CGU0_STAT_ADDRERR (1 << 16)
36
#define CGU0_STAT_LWERR (1 << 17)
37
#define CGU0_STAT_DIVERR (1 << 18)
38
#define CGU0_STAT_WDFMSERR (1 << 19)
39
#define CGU0_STAT_WDIVERR (1 << 20)
40
#define CGU0_STAT_PLOCKERR (1 << 21)
41
42
#define CGU0_DIV_CSEL_SHIFT 0
43
#define CGU0_DIV_CSEL_MASK 0x0000001F
44
#define CGU0_DIV_S0SEL_SHIFT 5
45
#define CGU0_DIV_S0SEL_MASK (0x3 << CGU0_DIV_S0SEL_SHIFT)
46
#define CGU0_DIV_SYSSEL_SHIFT 8
47
#define CGU0_DIV_SYSSEL_MASK (0x1f << CGU0_DIV_SYSSEL_SHIFT)
48
#define CGU0_DIV_S1SEL_SHIFT 13
49
#define CGU0_DIV_S1SEL_MASK (0x3 << CGU0_DIV_S1SEL_SHIFT)
50
#define CGU0_DIV_DSEL_SHIFT 16
51
#define CGU0_DIV_DSEL_MASK (0x1f << CGU0_DIV_DSEL_SHIFT)
52
#define CGU0_DIV_OSEL_SHIFT 22
53
#define CGU0_DIV_OSEL_MASK (0x7f << CGU0_DIV_OSEL_SHIFT)
54
55
#define CLK(_clk, _devname, _conname) \
56
{ \
57
.clk = &_clk, \
58
.dev_id = _devname, \
59
.con_id = _conname, \
60
}
61
62
#define NEEDS_INITIALIZATION 0x11
63
64
static
LIST_HEAD
(clk_list);
65
66
static
void
clk_reg_write_mask(
u32
reg
,
uint32_t
val
,
uint32_t
mask
)
67
{
68
u32
val2;
69
70
val2 =
bfin_read32
(reg);
71
val2 &= ~mask;
72
val2 |=
val
;
73
bfin_write32
(reg, val2);
74
}
75
76
static
void
clk_reg_set_bits(
u32
reg
,
uint32_t
mask
)
77
{
78
u32
val
;
79
80
val =
bfin_read32
(reg);
81
val |=
mask
;
82
bfin_write32
(reg, val);
83
}
84
85
static
void
clk_reg_clear_bits(
u32
reg
,
uint32_t
mask
)
86
{
87
u32
val
;
88
89
val =
bfin_read32
(reg);
90
val &= ~mask;
91
bfin_write32
(reg, val);
92
}
93
94
int
wait_for_pll_align
(
void
)
95
{
96
int
i
= 10000;
97
while
(i-- && (
bfin_read32
(
CGU0_STAT
) &
CGU0_STAT_CLKSALGN
));
98
99
if
(
bfin_read32
(
CGU0_STAT
) & CGU0_STAT_CLKSALGN) {
100
printk
(
KERN_CRIT
"fail to align clk\n"
);
101
return
-1;
102
}
103
104
return
0;
105
}
106
107
int
clk_enable
(
struct
clk
*
clk
)
108
{
109
int
ret
= -
EIO
;
110
if
(clk->
ops
&& clk->
ops
->enable)
111
ret = clk->
ops
->enable(clk);
112
return
ret
;
113
}
114
EXPORT_SYMBOL
(
clk_enable
);
115
116
void
clk_disable
(
struct
clk
*
clk
)
117
{
118
if
(clk->
ops
&& clk->
ops
->disable)
119
clk->
ops
->disable(clk);
120
}
121
EXPORT_SYMBOL
(
clk_disable
);
122
123
unsigned
long
clk_get_rate
(
struct
clk
*
clk
)
124
{
125
unsigned
long
ret
= 0;
126
if
(clk->
ops
&& clk->
ops
->get_rate)
127
ret = clk->
ops
->get_rate(clk);
128
return
ret
;
129
}
130
EXPORT_SYMBOL
(
clk_get_rate
);
131
132
long
clk_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
133
{
134
long
ret
= -
EIO
;
135
if
(clk->
ops
&& clk->
ops
->round_rate)
136
ret = clk->
ops
->round_rate(clk, rate);
137
return
ret
;
138
}
139
EXPORT_SYMBOL
(
clk_round_rate
);
140
141
int
clk_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
142
{
143
int
ret
= -
EIO
;
144
if
(clk->
ops
&& clk->
ops
->set_rate)
145
ret = clk->
ops
->set_rate(clk, rate);
146
return
ret
;
147
}
148
EXPORT_SYMBOL
(
clk_set_rate
);
149
150
unsigned
long
vco_get_rate
(
struct
clk
*
clk
)
151
{
152
return
clk->
rate
;
153
}
154
155
unsigned
long
pll_get_rate
(
struct
clk
*
clk
)
156
{
157
u32
df
;
158
u32
msel;
159
u32
ctl
=
bfin_read32
(
CGU0_CTL
);
160
u32
stat
=
bfin_read32
(
CGU0_STAT
);
161
if
(stat &
CGU0_STAT_PLLBP
)
162
return
0;
163
msel = (ctl &
CGU0_CTL_MSEL_MASK
) >>
CGU0_CTL_MSEL_SHIFT
;
164
df = (ctl &
CGU0_CTL_DF
);
165
clk->
parent
->rate =
clk_get_rate
(clk->
parent
);
166
return
clk->
parent
->rate / (df + 1) * msel * 2;
167
}
168
169
unsigned
long
pll_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
170
{
171
u32
div
;
172
div = rate / clk->
parent
->rate;
173
return
clk->
parent
->rate *
div
;
174
}
175
176
int
pll_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
177
{
178
u32
msel;
179
u32
stat
=
bfin_read32
(
CGU0_STAT
);
180
if
(!(stat &
CGU0_STAT_PLLEN
))
181
return
-
EBUSY
;
182
if
(!(stat &
CGU0_STAT_PLLLK
))
183
return
-
EBUSY
;
184
if
(
wait_for_pll_align
())
185
return
-
EBUSY
;
186
msel = rate / clk->
parent
->rate / 2;
187
clk_reg_write_mask(
CGU0_CTL
, msel <<
CGU0_CTL_MSEL_SHIFT
,
188
CGU0_CTL_MSEL_MASK
);
189
clk->
rate
=
rate
;
190
return
0;
191
}
192
193
unsigned
long
cclk_get_rate
(
struct
clk
*
clk
)
194
{
195
if
(clk->
parent
)
196
return
clk->
parent
->rate;
197
else
198
return
0;
199
}
200
201
unsigned
long
sys_clk_get_rate
(
struct
clk
*
clk
)
202
{
203
unsigned
long
drate
;
204
u32
msel;
205
u32
df
;
206
u32
ctl
=
bfin_read32
(
CGU0_CTL
);
207
u32
div
=
bfin_read32
(
CGU0_DIV
);
208
div = (div & clk->
mask
) >> clk->
shift
;
209
msel = (ctl &
CGU0_CTL_MSEL_MASK
) >>
CGU0_CTL_MSEL_SHIFT
;
210
df = (ctl &
CGU0_CTL_DF
);
211
212
if
(!
strcmp
(clk->
parent
->name,
"SYS_CLKIN"
)) {
213
drate = clk->
parent
->rate / (df + 1);
214
drate *= msel;
215
drate /=
div
;
216
return
drate
;
217
}
else
{
218
clk->
parent
->rate =
clk_get_rate
(clk->
parent
);
219
return
clk->
parent
->rate /
div
;
220
}
221
}
222
223
unsigned
long
sys_clk_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
224
{
225
unsigned
long
max_rate;
226
unsigned
long
drate
;
227
int
i
;
228
u32
msel;
229
u32
df
;
230
u32
ctl
=
bfin_read32
(
CGU0_CTL
);
231
232
msel = (ctl &
CGU0_CTL_MSEL_MASK
) >>
CGU0_CTL_MSEL_SHIFT
;
233
df = (ctl &
CGU0_CTL_DF
);
234
max_rate = clk->
parent
->rate / (df + 1) * msel;
235
236
if
(rate > max_rate)
237
return
0;
238
239
for
(i = 1; i < clk->
mask
; i++) {
240
drate = max_rate /
i
;
241
if
(rate >= drate)
242
return
drate
;
243
}
244
return
0;
245
}
246
247
int
sys_clk_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
248
{
249
u32
div
=
bfin_read32
(
CGU0_DIV
);
250
div = (div & clk->
mask
) >> clk->
shift
;
251
252
rate =
clk_round_rate
(clk, rate);
253
254
if
(!rate)
255
return
-
EINVAL
;
256
257
div = (
clk_get_rate
(clk) *
div
) / rate;
258
259
if
(
wait_for_pll_align
())
260
return
-
EBUSY
;
261
clk_reg_write_mask(
CGU0_DIV
, div << clk->
shift
,
262
clk->
mask
);
263
clk->
rate
=
rate
;
264
return
0;
265
}
266
267
static
struct
clk_ops
vco_ops = {
268
.get_rate =
vco_get_rate
,
269
};
270
271
static
struct
clk_ops
pll_ops = {
272
.get_rate =
pll_get_rate
,
273
.set_rate =
pll_set_rate
,
274
};
275
276
static
struct
clk_ops
cclk_ops = {
277
.get_rate =
cclk_get_rate
,
278
};
279
280
static
struct
clk_ops
sys_clk_ops = {
281
.get_rate =
sys_clk_get_rate
,
282
.set_rate =
sys_clk_set_rate
,
283
.round_rate =
sys_clk_round_rate
,
284
};
285
286
static
struct
clk
sys_clkin = {
287
.name =
"SYS_CLKIN"
,
288
.rate = CONFIG_CLKIN_HZ,
289
.ops = &vco_ops,
290
};
291
292
static
struct
clk
pll_clk = {
293
.name =
"PLLCLK"
,
294
.rate = 500000000,
295
.parent = &sys_clkin,
296
.
ops
= &pll_ops,
297
.flags =
NEEDS_INITIALIZATION
,
298
};
299
300
static
struct
clk
cclk = {
301
.name =
"CCLK"
,
302
.rate = 500000000,
303
.mask =
CGU0_DIV_CSEL_MASK
,
304
.shift =
CGU0_DIV_CSEL_SHIFT
,
305
.parent = &sys_clkin,
306
.
ops
= &sys_clk_ops,
307
.flags =
NEEDS_INITIALIZATION
,
308
};
309
310
static
struct
clk
cclk0 = {
311
.name =
"CCLK0"
,
312
.parent = &cclk,
313
.
ops
= &cclk_ops,
314
};
315
316
static
struct
clk
cclk1 = {
317
.name =
"CCLK1"
,
318
.parent = &cclk,
319
.
ops
= &cclk_ops,
320
};
321
322
static
struct
clk
sysclk = {
323
.name =
"SYSCLK"
,
324
.rate = 500000000,
325
.mask =
CGU0_DIV_SYSSEL_MASK
,
326
.shift =
CGU0_DIV_SYSSEL_SHIFT
,
327
.parent = &sys_clkin,
328
.
ops
= &sys_clk_ops,
329
.flags =
NEEDS_INITIALIZATION
,
330
};
331
332
static
struct
clk
sclk0 = {
333
.name =
"SCLK0"
,
334
.rate = 500000000,
335
.mask =
CGU0_DIV_S0SEL_MASK
,
336
.shift =
CGU0_DIV_S0SEL_SHIFT
,
337
.parent = &sysclk,
338
.
ops
= &sys_clk_ops,
339
};
340
341
static
struct
clk
sclk1 = {
342
.name =
"SCLK1"
,
343
.rate = 500000000,
344
.mask =
CGU0_DIV_S1SEL_MASK
,
345
.shift =
CGU0_DIV_S1SEL_SHIFT
,
346
.parent = &sysclk,
347
.
ops
= &sys_clk_ops,
348
};
349
350
static
struct
clk
dclk
= {
351
.name =
"DCLK"
,
352
.rate = 500000000,
353
.mask =
CGU0_DIV_DSEL_MASK
,
354
.shift =
CGU0_DIV_DSEL_SHIFT
,
355
.parent = &sys_clkin,
356
.
ops
= &sys_clk_ops,
357
};
358
359
static
struct
clk
oclk = {
360
.name =
"OCLK"
,
361
.rate = 500000000,
362
.mask =
CGU0_DIV_OSEL_MASK
,
363
.shift =
CGU0_DIV_OSEL_SHIFT
,
364
.parent = &pll_clk,
365
};
366
367
static
struct
clk_lookup
bf609_clks[] = {
368
CLK
(sys_clkin,
NULL
,
"SYS_CLKIN"
),
369
CLK
(pll_clk,
NULL
,
"PLLCLK"
),
370
CLK
(cclk,
NULL
,
"CCLK"
),
371
CLK
(cclk0,
NULL
,
"CCLK0"
),
372
CLK
(cclk1,
NULL
,
"CCLK1"
),
373
CLK
(sysclk,
NULL
,
"SYSCLK"
),
374
CLK
(sclk0,
NULL
,
"SCLK0"
),
375
CLK
(sclk1,
NULL
,
"SCLK1"
),
376
CLK
(dclk,
NULL
,
"DCLK"
),
377
CLK
(oclk,
NULL
,
"OCLK"
),
378
};
379
380
int
__init
clk_init
(
void
)
381
{
382
int
i
;
383
struct
clk
*clkp;
384
for
(i = 0; i <
ARRAY_SIZE
(bf609_clks); i++) {
385
clkp = bf609_clks[
i
].
clk
;
386
if
(clkp->
flags
&
NEEDS_INITIALIZATION
)
387
clk_get_rate
(clkp);
388
}
389
clkdev_add_table
(bf609_clks,
ARRAY_SIZE
(bf609_clks));
390
return
0;
391
}
Generated on Thu Jan 10 2013 12:56:40 for Linux Kernel by
1.8.2