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