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
arm
plat-s3c24xx
s3c2410-clock.c
Go to the documentation of this file.
1
/* linux/arch/arm/mach-s3c2410/clock.c
2
*
3
* Copyright (c) 2006 Simtec Electronics
4
* Ben Dooks <
[email protected]
>
5
*
6
* S3C2410,S3C2440,S3C2442 Clock control support
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, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
*/
22
23
#include <
linux/init.h
>
24
#include <linux/module.h>
25
#include <linux/kernel.h>
26
#include <linux/list.h>
27
#include <linux/errno.h>
28
#include <
linux/err.h
>
29
#include <linux/device.h>
30
#include <
linux/clk.h
>
31
#include <
linux/mutex.h
>
32
#include <
linux/delay.h
>
33
#include <linux/serial_core.h>
34
#include <
linux/io.h
>
35
36
#include <
asm/mach/map.h
>
37
38
#include <mach/hardware.h>
39
40
#include <
plat/regs-serial.h
>
41
#include <mach/regs-clock.h>
42
#include <mach/regs-gpio.h>
43
44
#include <
plat/s3c2410.h
>
45
#include <plat/clock.h>
46
#include <plat/cpu.h>
47
48
int
s3c2410_clkcon_enable
(
struct
clk
*
clk
,
int
enable
)
49
{
50
unsigned
int
clocks = clk->
ctrlbit
;
51
unsigned
long
clkcon;
52
53
clkcon =
__raw_readl
(
S3C2410_CLKCON
);
54
55
if
(enable)
56
clkcon |= clocks;
57
else
58
clkcon &= ~clocks;
59
60
/* ensure none of the special function bits set */
61
clkcon &= ~(
S3C2410_CLKCON_IDLE
|
S3C2410_CLKCON_POWER
);
62
63
__raw_writel
(clkcon,
S3C2410_CLKCON
);
64
65
return
0;
66
}
67
68
static
int
s3c2410_upll_enable(
struct
clk
*
clk
,
int
enable
)
69
{
70
unsigned
long
clkslow =
__raw_readl
(
S3C2410_CLKSLOW
);
71
unsigned
long
orig = clkslow;
72
73
if
(enable)
74
clkslow &= ~
S3C2410_CLKSLOW_UCLK_OFF
;
75
else
76
clkslow |=
S3C2410_CLKSLOW_UCLK_OFF
;
77
78
__raw_writel
(clkslow,
S3C2410_CLKSLOW
);
79
80
/* if we started the UPLL, then allow to settle */
81
82
if
(enable && (orig &
S3C2410_CLKSLOW_UCLK_OFF
))
83
udelay
(200);
84
85
return
0;
86
}
87
88
/* standard clock definitions */
89
90
static
struct
clk init_clocks_off[] = {
91
{
92
.name =
"nand"
,
93
.parent = &
clk_h
,
94
.enable =
s3c2410_clkcon_enable
,
95
.ctrlbit =
S3C2410_CLKCON_NAND
,
96
}, {
97
.name =
"sdi"
,
98
.parent = &
clk_p
,
99
.enable =
s3c2410_clkcon_enable
,
100
.ctrlbit =
S3C2410_CLKCON_SDI
,
101
}, {
102
.name =
"adc"
,
103
.parent = &
clk_p
,
104
.enable =
s3c2410_clkcon_enable
,
105
.ctrlbit =
S3C2410_CLKCON_ADC
,
106
}, {
107
.name =
"i2c"
,
108
.parent = &
clk_p
,
109
.enable =
s3c2410_clkcon_enable
,
110
.ctrlbit =
S3C2410_CLKCON_IIC
,
111
}, {
112
.name =
"iis"
,
113
.parent = &
clk_p
,
114
.enable =
s3c2410_clkcon_enable
,
115
.ctrlbit =
S3C2410_CLKCON_IIS
,
116
}, {
117
.name =
"spi"
,
118
.parent = &
clk_p
,
119
.enable =
s3c2410_clkcon_enable
,
120
.ctrlbit =
S3C2410_CLKCON_SPI
,
121
}
122
};
123
124
static
struct
clk init_clocks[] = {
125
{
126
.name =
"lcd"
,
127
.parent = &
clk_h
,
128
.enable =
s3c2410_clkcon_enable
,
129
.ctrlbit =
S3C2410_CLKCON_LCDC
,
130
}, {
131
.name =
"gpio"
,
132
.parent = &
clk_p
,
133
.enable =
s3c2410_clkcon_enable
,
134
.ctrlbit =
S3C2410_CLKCON_GPIO
,
135
}, {
136
.name =
"usb-host"
,
137
.parent = &
clk_h
,
138
.enable =
s3c2410_clkcon_enable
,
139
.ctrlbit =
S3C2410_CLKCON_USBH
,
140
}, {
141
.name =
"usb-device"
,
142
.parent = &
clk_h
,
143
.enable =
s3c2410_clkcon_enable
,
144
.ctrlbit =
S3C2410_CLKCON_USBD
,
145
}, {
146
.name =
"timers"
,
147
.parent = &
clk_p
,
148
.enable =
s3c2410_clkcon_enable
,
149
.ctrlbit =
S3C2410_CLKCON_PWMT
,
150
}, {
151
.name =
"uart"
,
152
.devname =
"s3c2410-uart.0"
,
153
.parent = &
clk_p
,
154
.enable =
s3c2410_clkcon_enable
,
155
.ctrlbit =
S3C2410_CLKCON_UART0
,
156
}, {
157
.name =
"uart"
,
158
.devname =
"s3c2410-uart.1"
,
159
.parent = &
clk_p
,
160
.enable =
s3c2410_clkcon_enable
,
161
.ctrlbit =
S3C2410_CLKCON_UART1
,
162
}, {
163
.name =
"uart"
,
164
.devname =
"s3c2410-uart.2"
,
165
.parent = &
clk_p
,
166
.enable =
s3c2410_clkcon_enable
,
167
.ctrlbit =
S3C2410_CLKCON_UART2
,
168
}, {
169
.name =
"rtc"
,
170
.parent = &
clk_p
,
171
.enable =
s3c2410_clkcon_enable
,
172
.ctrlbit =
S3C2410_CLKCON_RTC
,
173
}, {
174
.name =
"watchdog"
,
175
.parent = &
clk_p
,
176
.ctrlbit = 0,
177
}, {
178
.name =
"usb-bus-host"
,
179
.parent = &
clk_usb_bus
,
180
}, {
181
.name =
"usb-bus-gadget"
,
182
.parent = &
clk_usb_bus
,
183
},
184
};
185
186
/* s3c2410_baseclk_add()
187
*
188
* Add all the clocks used by the s3c2410 or compatible CPUs
189
* such as the S3C2440 and S3C2442.
190
*
191
* We cannot use a system device as we are needed before any
192
* of the init-calls that initialise the devices are actually
193
* done.
194
*/
195
196
int
__init
s3c2410_baseclk_add
(
void
)
197
{
198
unsigned
long
clkslow =
__raw_readl
(
S3C2410_CLKSLOW
);
199
unsigned
long
clkcon =
__raw_readl
(
S3C2410_CLKCON
);
200
struct
clk *clkp;
201
struct
clk *
xtal
;
202
int
ret
;
203
int
ptr
;
204
205
clk_upll
.enable = s3c2410_upll_enable;
206
207
if
(
s3c24xx_register_clock
(&
clk_usb_bus
) < 0)
208
printk
(
KERN_ERR
"failed to register usb bus clock\n"
);
209
210
/* register clocks from clock array */
211
212
clkp = init_clocks;
213
for
(ptr = 0; ptr <
ARRAY_SIZE
(init_clocks); ptr++, clkp++) {
214
/* ensure that we note the clock state */
215
216
clkp->
usage
= clkcon & clkp->
ctrlbit
? 1 : 0;
217
218
ret =
s3c24xx_register_clock
(clkp);
219
if
(ret < 0) {
220
printk
(
KERN_ERR
"Failed to register clock %s (%d)\n"
,
221
clkp->
name
, ret);
222
}
223
}
224
225
/* We must be careful disabling the clocks we are not intending to
226
* be using at boot time, as subsystems such as the LCD which do
227
* their own DMA requests to the bus can cause the system to lockup
228
* if they where in the middle of requesting bus access.
229
*
230
* Disabling the LCD clock if the LCD is active is very dangerous,
231
* and therefore the bootloader should be careful to not enable
232
* the LCD clock if it is not needed.
233
*/
234
235
/* install (and disable) the clocks we do not need immediately */
236
237
s3c_register_clocks
(init_clocks_off,
ARRAY_SIZE
(init_clocks_off));
238
s3c_disable_clocks
(init_clocks_off,
ARRAY_SIZE
(init_clocks_off));
239
240
/* show the clock-slow value */
241
242
xtal =
clk_get
(
NULL
,
"xtal"
);
243
244
printk
(
"CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n"
,
245
print_mhz
(
clk_get_rate
(xtal) /
246
( 2 *
S3C2410_CLKSLOW_GET_SLOWVAL
(clkslow))),
247
(clkslow &
S3C2410_CLKSLOW_SLOW
) ?
"slow"
:
"fast"
,
248
(clkslow &
S3C2410_CLKSLOW_MPLL_OFF
) ?
"off"
:
"on"
,
249
(clkslow &
S3C2410_CLKSLOW_UCLK_OFF
) ?
"off"
:
"on"
);
250
251
s3c_pwmclk_init
();
252
return
0;
253
}
Generated on Thu Jan 10 2013 13:03:20 for Linux Kernel by
1.8.2