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
sh
kernel
cpu
sh4a
clock-sh7722.c
Go to the documentation of this file.
1
/*
2
* arch/sh/kernel/cpu/sh4a/clock-sh7722.c
3
*
4
* SH7722 clock framework support
5
*
6
* Copyright (C) 2009 Magnus Damm
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License
11
*
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
*/
21
#include <
linux/init.h
>
22
#include <linux/kernel.h>
23
#include <
linux/io.h
>
24
#include <
linux/clkdev.h
>
25
#include <
linux/sh_clk.h
>
26
#include <asm/clock.h>
27
#include <
cpu/sh7722.h
>
28
29
/* SH7722 registers */
30
#define FRQCR 0xa4150000
31
#define VCLKCR 0xa4150004
32
#define SCLKACR 0xa4150008
33
#define SCLKBCR 0xa415000c
34
#define IRDACLKCR 0xa4150018
35
#define PLLCR 0xa4150024
36
#define MSTPCR0 0xa4150030
37
#define MSTPCR1 0xa4150034
38
#define MSTPCR2 0xa4150038
39
#define DLLFRQ 0xa4150050
40
41
/* Fixed 32 KHz root clock for RTC and Power Management purposes */
42
static
struct
clk
r_clk = {
43
.rate = 32768,
44
};
45
46
/*
47
* Default rate for the root input clock, reset this with clk_set_rate()
48
* from the platform code.
49
*/
50
struct
clk
extal_clk
= {
51
.rate = 33333333,
52
};
53
54
/* The dll block multiplies the 32khz r_clk, may be used instead of extal */
55
static
unsigned
long
dll_recalc(
struct
clk
*
clk
)
56
{
57
unsigned
long
mult
;
58
59
if
(
__raw_readl
(
PLLCR
) & 0x1000)
60
mult =
__raw_readl
(
DLLFRQ
);
61
else
62
mult = 0;
63
64
return
clk->
parent
->rate *
mult
;
65
}
66
67
static
struct
sh_clk_ops
dll_clk_ops = {
68
.recalc = dll_recalc,
69
};
70
71
static
struct
clk dll_clk = {
72
.ops = &dll_clk_ops,
73
.parent = &r_clk,
74
.
flags
=
CLK_ENABLE_ON_INIT
,
75
};
76
77
static
unsigned
long
pll_recalc(
struct
clk *clk)
78
{
79
unsigned
long
mult = 1;
80
unsigned
long
div
= 1;
81
82
if
(
__raw_readl
(
PLLCR
) & 0x4000)
83
mult = (((
__raw_readl
(
FRQCR
) >> 24) & 0x1f) + 1);
84
else
85
div = 2;
86
87
return
(clk->
parent
->rate * mult) /
div
;
88
}
89
90
static
struct
sh_clk_ops
pll_clk_ops = {
91
.recalc = pll_recalc,
92
};
93
94
static
struct
clk pll_clk = {
95
.ops = &pll_clk_ops,
96
.flags =
CLK_ENABLE_ON_INIT
,
97
};
98
99
struct
clk *
main_clks
[] = {
100
&r_clk,
101
&extal_clk,
102
&dll_clk,
103
&pll_clk,
104
};
105
106
static
int
multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
107
static
int
divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
108
109
static
struct
clk_div_mult_table
div4_div_mult_table = {
110
.divisors =
divisors
,
111
.nr_divisors =
ARRAY_SIZE
(divisors),
112
.multipliers =
multipliers
,
113
.nr_multipliers =
ARRAY_SIZE
(multipliers),
114
};
115
116
static
struct
clk_div4_table
div4_table = {
117
.div_mult_table = &div4_div_mult_table,
118
};
119
120
#define DIV4(_reg, _bit, _mask, _flags) \
121
SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
122
123
enum
{
DIV4_I
,
DIV4_U
,
DIV4_SH
,
DIV4_B
,
DIV4_B3
,
DIV4_P
,
DIV4_NR
};
124
125
struct
clk
div4_clks
[
DIV4_NR
] = {
126
[
DIV4_I
] =
DIV4
(
FRQCR
, 20, 0x1fef,
CLK_ENABLE_ON_INIT
),
127
[
DIV4_U
] =
DIV4
(
FRQCR
, 16, 0x1fff,
CLK_ENABLE_ON_INIT
),
128
[
DIV4_SH
] =
DIV4
(
FRQCR
, 12, 0x1fff,
CLK_ENABLE_ON_INIT
),
129
[
DIV4_B
] =
DIV4
(
FRQCR
, 8, 0x1fff,
CLK_ENABLE_ON_INIT
),
130
[
DIV4_B3
] =
DIV4
(
FRQCR
, 4, 0x1fff,
CLK_ENABLE_ON_INIT
),
131
[
DIV4_P
] =
DIV4
(
FRQCR
, 0, 0x1fff, 0),
132
};
133
134
enum
{
DIV4_IRDA
,
DIV4_ENABLE_NR
};
135
136
struct
clk
div4_enable_clks
[
DIV4_ENABLE_NR
] = {
137
[
DIV4_IRDA
] =
DIV4
(
IRDACLKCR
, 0, 0x1fff, 0),
138
};
139
140
enum
{
DIV4_SIUA
,
DIV4_SIUB
,
DIV4_REPARENT_NR
};
141
142
struct
clk
div4_reparent_clks
[
DIV4_REPARENT_NR
] = {
143
[
DIV4_SIUA
] =
DIV4
(
SCLKACR
, 0, 0x1fff, 0),
144
[
DIV4_SIUB
] =
DIV4
(
SCLKBCR
, 0, 0x1fff, 0),
145
};
146
147
enum
{
DIV6_V
,
DIV6_NR
};
148
149
struct
clk
div6_clks
[
DIV6_NR
] = {
150
[
DIV6_V
] =
SH_CLK_DIV6
(&pll_clk,
VCLKCR
, 0),
151
};
152
153
static
struct
clk mstp_clks[
HWBLK_NR
] = {
154
[
HWBLK_URAM
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_U
],
MSTPCR0
, 28,
CLK_ENABLE_ON_INIT
),
155
[
HWBLK_XYMEM
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_B
],
MSTPCR0
, 26,
CLK_ENABLE_ON_INIT
),
156
[
HWBLK_TMU
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_P
],
MSTPCR0
, 15, 0),
157
[
HWBLK_CMT
] =
SH_CLK_MSTP32
(&r_clk,
MSTPCR0
, 14, 0),
158
[
HWBLK_RWDT
] =
SH_CLK_MSTP32
(&r_clk,
MSTPCR0
, 13, 0),
159
[
HWBLK_FLCTL
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_P
],
MSTPCR0
, 10, 0),
160
[
HWBLK_SCIF0
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_P
],
MSTPCR0
, 7, 0),
161
[
HWBLK_SCIF1
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_P
],
MSTPCR0
, 6, 0),
162
[
HWBLK_SCIF2
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_P
],
MSTPCR0
, 5, 0),
163
164
[
HWBLK_IIC
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_P
],
MSTPCR1
, 9, 0),
165
[
HWBLK_RTC
] =
SH_CLK_MSTP32
(&r_clk,
MSTPCR1
, 8, 0),
166
167
[
HWBLK_SDHI
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_P
],
MSTPCR2
, 18, 0),
168
[
HWBLK_KEYSC
] =
SH_CLK_MSTP32
(&r_clk,
MSTPCR2
, 14, 0),
169
[
HWBLK_USBF
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_P
],
MSTPCR2
, 11, 0),
170
[
HWBLK_2DG
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_B
],
MSTPCR2
, 9, 0),
171
[
HWBLK_SIU
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_B
],
MSTPCR2
, 8, 0),
172
[
HWBLK_JPU
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_B
],
MSTPCR2
, 6, 0),
173
[
HWBLK_VOU
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_B
],
MSTPCR2
, 5, 0),
174
[
HWBLK_BEU
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_B
],
MSTPCR2
, 4, 0),
175
[
HWBLK_CEU
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_B
],
MSTPCR2
, 3, 0),
176
[
HWBLK_VEU
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_B
],
MSTPCR2
, 2, 0),
177
[
HWBLK_VPU
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_B
],
MSTPCR2
, 1, 0),
178
[
HWBLK_LCDC
] =
SH_CLK_MSTP32
(&div4_clks[
DIV4_P
],
MSTPCR2
, 0, 0),
179
};
180
181
static
struct
clk_lookup
lookups[] = {
182
/* main clocks */
183
CLKDEV_CON_ID
(
"rclk"
, &r_clk),
184
CLKDEV_CON_ID
(
"extal"
, &extal_clk),
185
CLKDEV_CON_ID
(
"dll_clk"
, &dll_clk),
186
CLKDEV_CON_ID
(
"pll_clk"
, &pll_clk),
187
188
/* DIV4 clocks */
189
CLKDEV_CON_ID
(
"cpu_clk"
, &div4_clks[
DIV4_I
]),
190
CLKDEV_CON_ID
(
"umem_clk"
, &div4_clks[
DIV4_U
]),
191
CLKDEV_CON_ID
(
"shyway_clk"
, &div4_clks[
DIV4_SH
]),
192
CLKDEV_CON_ID
(
"bus_clk"
, &div4_clks[
DIV4_B
]),
193
CLKDEV_CON_ID
(
"b3_clk"
, &div4_clks[
DIV4_B3
]),
194
CLKDEV_CON_ID
(
"peripheral_clk"
, &div4_clks[
DIV4_P
]),
195
CLKDEV_CON_ID
(
"irda_clk"
, &div4_enable_clks[
DIV4_IRDA
]),
196
CLKDEV_CON_ID
(
"siua_clk"
, &div4_reparent_clks[
DIV4_SIUA
]),
197
CLKDEV_CON_ID
(
"siub_clk"
, &div4_reparent_clks[
DIV4_SIUB
]),
198
199
/* DIV6 clocks */
200
CLKDEV_CON_ID
(
"video_clk"
, &div6_clks[
DIV6_V
]),
201
202
/* MSTP clocks */
203
CLKDEV_CON_ID
(
"uram0"
, &mstp_clks[
HWBLK_URAM
]),
204
CLKDEV_CON_ID
(
"xymem0"
, &mstp_clks[
HWBLK_XYMEM
]),
205
206
CLKDEV_ICK_ID
(
"tmu_fck"
,
"sh_tmu.0"
, &mstp_clks[
HWBLK_TMU
]),
207
CLKDEV_ICK_ID
(
"tmu_fck"
,
"sh_tmu.1"
, &mstp_clks[
HWBLK_TMU
]),
208
CLKDEV_ICK_ID
(
"tmu_fck"
,
"sh_tmu.2"
, &mstp_clks[
HWBLK_TMU
]),
209
210
CLKDEV_CON_ID
(
"cmt_fck"
, &mstp_clks[
HWBLK_CMT
]),
211
CLKDEV_DEV_ID
(
"sh-wdt.0"
, &mstp_clks[
HWBLK_RWDT
]),
212
CLKDEV_CON_ID
(
"flctl0"
, &mstp_clks[
HWBLK_FLCTL
]),
213
214
CLKDEV_DEV_ID
(
"sh-sci.0"
, &mstp_clks[
HWBLK_SCIF0
]),
215
CLKDEV_DEV_ID
(
"sh-sci.1"
, &mstp_clks[
HWBLK_SCIF1
]),
216
CLKDEV_DEV_ID
(
"sh-sci.2"
, &mstp_clks[
HWBLK_SCIF2
]),
217
218
CLKDEV_DEV_ID
(
"i2c-sh_mobile.0"
, &mstp_clks[
HWBLK_IIC
]),
219
CLKDEV_CON_ID
(
"rtc0"
, &mstp_clks[
HWBLK_RTC
]),
220
CLKDEV_DEV_ID
(
"sh_mobile_sdhi.0"
, &mstp_clks[
HWBLK_SDHI
]),
221
CLKDEV_DEV_ID
(
"sh_keysc.0"
, &mstp_clks[
HWBLK_KEYSC
]),
222
CLKDEV_CON_ID
(
"usbf0"
, &mstp_clks[
HWBLK_USBF
]),
223
CLKDEV_CON_ID
(
"2dg0"
, &mstp_clks[
HWBLK_2DG
]),
224
CLKDEV_DEV_ID
(
"siu-pcm-audio"
, &mstp_clks[
HWBLK_SIU
]),
225
CLKDEV_DEV_ID
(
"sh-vou.0"
, &mstp_clks[
HWBLK_VOU
]),
226
CLKDEV_CON_ID
(
"jpu0"
, &mstp_clks[
HWBLK_JPU
]),
227
CLKDEV_CON_ID
(
"beu0"
, &mstp_clks[
HWBLK_BEU
]),
228
CLKDEV_DEV_ID
(
"sh_mobile_ceu.0"
, &mstp_clks[
HWBLK_CEU
]),
229
CLKDEV_CON_ID
(
"veu0"
, &mstp_clks[
HWBLK_VEU
]),
230
CLKDEV_CON_ID
(
"vpu0"
, &mstp_clks[
HWBLK_VPU
]),
231
CLKDEV_DEV_ID
(
"sh_mobile_lcdc_fb.0"
, &mstp_clks[
HWBLK_LCDC
]),
232
};
233
234
int
__init
arch_clk_init
(
void
)
235
{
236
int
k
,
ret
= 0;
237
238
/* autodetect extal or dll configuration */
239
if
(
__raw_readl
(
PLLCR
) & 0x1000)
240
pll_clk.
parent
= &dll_clk;
241
else
242
pll_clk.
parent
= &extal_clk;
243
244
for
(k = 0; !ret && (k <
ARRAY_SIZE
(main_clks)); k++)
245
ret =
clk_register
(main_clks[k]);
246
247
clkdev_add_table
(lookups,
ARRAY_SIZE
(lookups));
248
249
if
(!ret)
250
ret =
sh_clk_div4_register
(div4_clks,
DIV4_NR
, &div4_table);
251
252
if
(!ret)
253
ret =
sh_clk_div4_enable_register
(div4_enable_clks,
254
DIV4_ENABLE_NR
, &div4_table);
255
256
if
(!ret)
257
ret =
sh_clk_div4_reparent_register
(div4_reparent_clks,
258
DIV4_REPARENT_NR
, &div4_table);
259
260
if
(!ret)
261
ret =
sh_clk_div6_register
(div6_clks,
DIV6_NR
);
262
263
if
(!ret)
264
ret =
sh_clk_mstp_register
(mstp_clks,
HWBLK_NR
);
265
266
return
ret
;
267
}
Generated on Thu Jan 10 2013 13:17:39 for Linux Kernel by
1.8.2