aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-s3c24xx/Kconfig11
-rw-r--r--arch/arm/mach-s3c24xx/Makefile2
-rw-r--r--arch/arm/mach-s3c24xx/clock-dclk.c195
-rw-r--r--arch/arm/mach-s3c24xx/clock-s3c2410.c284
-rw-r--r--arch/arm/mach-s3c24xx/clock-s3c2440.c217
-rw-r--r--arch/arm/mach-s3c24xx/clock-s3c244x.c141
-rw-r--r--arch/arm/mach-s3c24xx/common.h2
-rw-r--r--arch/arm/mach-s3c24xx/include/mach/regs-clock.h18
-rw-r--r--arch/arm/mach-s3c24xx/include/mach/regs-gpio.h3
-rw-r--r--arch/arm/mach-s3c24xx/pm.c12
-rw-r--r--arch/arm/mach-s3c24xx/s3c2410.c62
-rw-r--r--arch/arm/mach-s3c24xx/s3c2442.c112
-rw-r--r--arch/arm/mach-s3c24xx/s3c244x.c63
13 files changed, 0 insertions, 1122 deletions
diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig
index 23968c661415..f9bb1ea14fe4 100644
--- a/arch/arm/mach-s3c24xx/Kconfig
+++ b/arch/arm/mach-s3c24xx/Kconfig
@@ -110,17 +110,6 @@ config CPU_S3C2443
110 110
111# common code 111# common code
112 112
113config S3C2410_CLOCK
114 bool
115 help
116 Clock code for the S3C2410, and similar processors which
117 is currently includes the S3C2410, S3C2440, S3C2442.
118
119config S3C24XX_DCLK
120 bool
121 help
122 Clock code for supporting DCLK/CLKOUT on S3C24XX architectures
123
124config S3C24XX_SMDK 113config S3C24XX_SMDK
125 bool 114 bool
126 help 115 help
diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile
index 9010ebaafff6..2235d0d3b38d 100644
--- a/arch/arm/mach-s3c24xx/Makefile
+++ b/arch/arm/mach-s3c24xx/Makefile
@@ -44,10 +44,8 @@ obj-$(CONFIG_PM) += pm.o irq-pm.o sleep.o
44 44
45# common code 45# common code
46 46
47obj-$(CONFIG_S3C24XX_DCLK) += clock-dclk.o
48obj-$(CONFIG_S3C24XX_DMA) += dma.o 47obj-$(CONFIG_S3C24XX_DMA) += dma.o
49 48
50obj-$(CONFIG_S3C2410_CLOCK) += clock-s3c2410.o
51obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += cpufreq-utils.o 49obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += cpufreq-utils.o
52 50
53obj-$(CONFIG_S3C2410_IOTIMING) += iotiming-s3c2410.o 51obj-$(CONFIG_S3C2410_IOTIMING) += iotiming-s3c2410.o
diff --git a/arch/arm/mach-s3c24xx/clock-dclk.c b/arch/arm/mach-s3c24xx/clock-dclk.c
deleted file mode 100644
index 1edd9b2369c5..000000000000
--- a/arch/arm/mach-s3c24xx/clock-dclk.c
+++ /dev/null
@@ -1,195 +0,0 @@
1/*
2 * Copyright (c) 2004-2008 Simtec Electronics
3 * Ben Dooks <ben@simtec.co.uk>
4 * http://armlinux.simtec.co.uk/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * S3C24XX - definitions for DCLK and CLKOUT registers
11 */
12
13#include <linux/kernel.h>
14#include <linux/errno.h>
15#include <linux/clk.h>
16#include <linux/io.h>
17
18#include <mach/regs-clock.h>
19#include <mach/regs-gpio.h>
20
21#include <plat/clock.h>
22#include <plat/cpu.h>
23
24/* clocks that could be registered by external code */
25
26static int s3c24xx_dclk_enable(struct clk *clk, int enable)
27{
28 unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
29
30 if (enable)
31 dclkcon |= clk->ctrlbit;
32 else
33 dclkcon &= ~clk->ctrlbit;
34
35 __raw_writel(dclkcon, S3C24XX_DCLKCON);
36
37 return 0;
38}
39
40static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
41{
42 unsigned long dclkcon;
43 unsigned int uclk;
44
45 if (parent == &clk_upll)
46 uclk = 1;
47 else if (parent == &clk_p)
48 uclk = 0;
49 else
50 return -EINVAL;
51
52 clk->parent = parent;
53
54 dclkcon = __raw_readl(S3C24XX_DCLKCON);
55
56 if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
57 if (uclk)
58 dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK;
59 else
60 dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK;
61 } else {
62 if (uclk)
63 dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK;
64 else
65 dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
66 }
67
68 __raw_writel(dclkcon, S3C24XX_DCLKCON);
69
70 return 0;
71}
72static unsigned long s3c24xx_calc_div(struct clk *clk, unsigned long rate)
73{
74 unsigned long div;
75
76 if ((rate == 0) || !clk->parent)
77 return 0;
78
79 div = clk_get_rate(clk->parent) / rate;
80 if (div < 2)
81 div = 2;
82 else if (div > 16)
83 div = 16;
84
85 return div;
86}
87
88static unsigned long s3c24xx_round_dclk_rate(struct clk *clk,
89 unsigned long rate)
90{
91 unsigned long div = s3c24xx_calc_div(clk, rate);
92
93 if (div == 0)
94 return 0;
95
96 return clk_get_rate(clk->parent) / div;
97}
98
99static int s3c24xx_set_dclk_rate(struct clk *clk, unsigned long rate)
100{
101 unsigned long mask, data, div = s3c24xx_calc_div(clk, rate);
102
103 if (div == 0)
104 return -EINVAL;
105
106 if (clk == &s3c24xx_dclk0) {
107 mask = S3C2410_DCLKCON_DCLK0_DIV_MASK |
108 S3C2410_DCLKCON_DCLK0_CMP_MASK;
109 data = S3C2410_DCLKCON_DCLK0_DIV(div) |
110 S3C2410_DCLKCON_DCLK0_CMP((div + 1) / 2);
111 } else if (clk == &s3c24xx_dclk1) {
112 mask = S3C2410_DCLKCON_DCLK1_DIV_MASK |
113 S3C2410_DCLKCON_DCLK1_CMP_MASK;
114 data = S3C2410_DCLKCON_DCLK1_DIV(div) |
115 S3C2410_DCLKCON_DCLK1_CMP((div + 1) / 2);
116 } else
117 return -EINVAL;
118
119 clk->rate = clk_get_rate(clk->parent) / div;
120 __raw_writel(((__raw_readl(S3C24XX_DCLKCON) & ~mask) | data),
121 S3C24XX_DCLKCON);
122 return clk->rate;
123}
124static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
125{
126 unsigned long mask;
127 unsigned long source;
128
129 /* calculate the MISCCR setting for the clock */
130
131 if (parent == &clk_mpll)
132 source = S3C2410_MISCCR_CLK0_MPLL;
133 else if (parent == &clk_upll)
134 source = S3C2410_MISCCR_CLK0_UPLL;
135 else if (parent == &clk_f)
136 source = S3C2410_MISCCR_CLK0_FCLK;
137 else if (parent == &clk_h)
138 source = S3C2410_MISCCR_CLK0_HCLK;
139 else if (parent == &clk_p)
140 source = S3C2410_MISCCR_CLK0_PCLK;
141 else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0)
142 source = S3C2410_MISCCR_CLK0_DCLK0;
143 else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1)
144 source = S3C2410_MISCCR_CLK0_DCLK0;
145 else
146 return -EINVAL;
147
148 clk->parent = parent;
149
150 if (clk == &s3c24xx_clkout0)
151 mask = S3C2410_MISCCR_CLK0_MASK;
152 else {
153 source <<= 4;
154 mask = S3C2410_MISCCR_CLK1_MASK;
155 }
156
157 s3c2410_modify_misccr(mask, source);
158 return 0;
159}
160
161/* external clock definitions */
162
163static struct clk_ops dclk_ops = {
164 .set_parent = s3c24xx_dclk_setparent,
165 .set_rate = s3c24xx_set_dclk_rate,
166 .round_rate = s3c24xx_round_dclk_rate,
167};
168
169struct clk s3c24xx_dclk0 = {
170 .name = "dclk0",
171 .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
172 .enable = s3c24xx_dclk_enable,
173 .ops = &dclk_ops,
174};
175
176struct clk s3c24xx_dclk1 = {
177 .name = "dclk1",
178 .ctrlbit = S3C2410_DCLKCON_DCLK1EN,
179 .enable = s3c24xx_dclk_enable,
180 .ops = &dclk_ops,
181};
182
183static struct clk_ops clkout_ops = {
184 .set_parent = s3c24xx_clkout_setparent,
185};
186
187struct clk s3c24xx_clkout0 = {
188 .name = "clkout0",
189 .ops = &clkout_ops,
190};
191
192struct clk s3c24xx_clkout1 = {
193 .name = "clkout1",
194 .ops = &clkout_ops,
195};
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2410.c b/arch/arm/mach-s3c24xx/clock-s3c2410.c
deleted file mode 100644
index d1afcf9252d1..000000000000
--- a/arch/arm/mach-s3c24xx/clock-s3c2410.c
+++ /dev/null
@@ -1,284 +0,0 @@
1/*
2 * Copyright (c) 2006 Simtec Electronics
3 * Ben Dooks <ben@simtec.co.uk>
4 *
5 * S3C2410,S3C2440,S3C2442 Clock control support
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
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
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/kernel.h>
25#include <linux/list.h>
26#include <linux/errno.h>
27#include <linux/err.h>
28#include <linux/device.h>
29#include <linux/clk.h>
30#include <linux/mutex.h>
31#include <linux/delay.h>
32#include <linux/serial_core.h>
33#include <linux/serial_s3c.h>
34#include <linux/io.h>
35
36#include <asm/mach/map.h>
37
38#include <mach/hardware.h>
39#include <mach/regs-clock.h>
40#include <mach/regs-gpio.h>
41
42#include <plat/clock.h>
43#include <plat/cpu.h>
44
45int s3c2410_clkcon_enable(struct clk *clk, int enable)
46{
47 unsigned int clocks = clk->ctrlbit;
48 unsigned long clkcon;
49
50 clkcon = __raw_readl(S3C2410_CLKCON);
51
52 if (enable)
53 clkcon |= clocks;
54 else
55 clkcon &= ~clocks;
56
57 /* ensure none of the special function bits set */
58 clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
59
60 __raw_writel(clkcon, S3C2410_CLKCON);
61
62 return 0;
63}
64
65static int s3c2410_upll_enable(struct clk *clk, int enable)
66{
67 unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
68 unsigned long orig = clkslow;
69
70 if (enable)
71 clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
72 else
73 clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
74
75 __raw_writel(clkslow, S3C2410_CLKSLOW);
76
77 /* if we started the UPLL, then allow to settle */
78
79 if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
80 udelay(200);
81
82 return 0;
83}
84
85/* standard clock definitions */
86
87static struct clk init_clocks_off[] = {
88 {
89 .name = "nand",
90 .parent = &clk_h,
91 .enable = s3c2410_clkcon_enable,
92 .ctrlbit = S3C2410_CLKCON_NAND,
93 }, {
94 .name = "sdi",
95 .parent = &clk_p,
96 .enable = s3c2410_clkcon_enable,
97 .ctrlbit = S3C2410_CLKCON_SDI,
98 }, {
99 .name = "adc",
100 .parent = &clk_p,
101 .enable = s3c2410_clkcon_enable,
102 .ctrlbit = S3C2410_CLKCON_ADC,
103 }, {
104 .name = "i2c",
105 .parent = &clk_p,
106 .enable = s3c2410_clkcon_enable,
107 .ctrlbit = S3C2410_CLKCON_IIC,
108 }, {
109 .name = "iis",
110 .parent = &clk_p,
111 .enable = s3c2410_clkcon_enable,
112 .ctrlbit = S3C2410_CLKCON_IIS,
113 }, {
114 .name = "spi",
115 .parent = &clk_p,
116 .enable = s3c2410_clkcon_enable,
117 .ctrlbit = S3C2410_CLKCON_SPI,
118 }
119};
120
121static struct clk clk_lcd = {
122 .name = "lcd",
123 .parent = &clk_h,
124 .enable = s3c2410_clkcon_enable,
125 .ctrlbit = S3C2410_CLKCON_LCDC,
126};
127
128static struct clk clk_gpio = {
129 .name = "gpio",
130 .parent = &clk_p,
131 .enable = s3c2410_clkcon_enable,
132 .ctrlbit = S3C2410_CLKCON_GPIO,
133};
134
135static struct clk clk_usb_host = {
136 .name = "usb-host",
137 .parent = &clk_h,
138 .enable = s3c2410_clkcon_enable,
139 .ctrlbit = S3C2410_CLKCON_USBH,
140};
141
142static struct clk clk_usb_device = {
143 .name = "usb-device",
144 .parent = &clk_h,
145 .enable = s3c2410_clkcon_enable,
146 .ctrlbit = S3C2410_CLKCON_USBD,
147};
148
149static struct clk clk_timers = {
150 .name = "timers",
151 .parent = &clk_p,
152 .enable = s3c2410_clkcon_enable,
153 .ctrlbit = S3C2410_CLKCON_PWMT,
154};
155
156struct clk s3c24xx_clk_uart0 = {
157 .name = "uart",
158 .devname = "s3c2410-uart.0",
159 .parent = &clk_p,
160 .enable = s3c2410_clkcon_enable,
161 .ctrlbit = S3C2410_CLKCON_UART0,
162};
163
164struct clk s3c24xx_clk_uart1 = {
165 .name = "uart",
166 .devname = "s3c2410-uart.1",
167 .parent = &clk_p,
168 .enable = s3c2410_clkcon_enable,
169 .ctrlbit = S3C2410_CLKCON_UART1,
170};
171
172struct clk s3c24xx_clk_uart2 = {
173 .name = "uart",
174 .devname = "s3c2410-uart.2",
175 .parent = &clk_p,
176 .enable = s3c2410_clkcon_enable,
177 .ctrlbit = S3C2410_CLKCON_UART2,
178};
179
180static struct clk clk_rtc = {
181 .name = "rtc",
182 .parent = &clk_p,
183 .enable = s3c2410_clkcon_enable,
184 .ctrlbit = S3C2410_CLKCON_RTC,
185};
186
187static struct clk clk_watchdog = {
188 .name = "watchdog",
189 .parent = &clk_p,
190 .ctrlbit = 0,
191};
192
193static struct clk clk_usb_bus_host = {
194 .name = "usb-bus-host",
195 .parent = &clk_usb_bus,
196};
197
198static struct clk clk_usb_bus_gadget = {
199 .name = "usb-bus-gadget",
200 .parent = &clk_usb_bus,
201};
202
203static struct clk *init_clocks[] = {
204 &clk_lcd,
205 &clk_gpio,
206 &clk_usb_host,
207 &clk_usb_device,
208 &clk_timers,
209 &s3c24xx_clk_uart0,
210 &s3c24xx_clk_uart1,
211 &s3c24xx_clk_uart2,
212 &clk_rtc,
213 &clk_watchdog,
214 &clk_usb_bus_host,
215 &clk_usb_bus_gadget,
216};
217
218/* s3c2410_baseclk_add()
219 *
220 * Add all the clocks used by the s3c2410 or compatible CPUs
221 * such as the S3C2440 and S3C2442.
222 *
223 * We cannot use a system device as we are needed before any
224 * of the init-calls that initialise the devices are actually
225 * done.
226*/
227
228int __init s3c2410_baseclk_add(void)
229{
230 unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
231 unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
232 struct clk *xtal;
233 int ret;
234 int ptr;
235
236 clk_upll.enable = s3c2410_upll_enable;
237
238 if (s3c24xx_register_clock(&clk_usb_bus) < 0)
239 printk(KERN_ERR "failed to register usb bus clock\n");
240
241 /* register clocks from clock array */
242
243 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++) {
244 struct clk *clkp = init_clocks[ptr];
245
246 /* ensure that we note the clock state */
247
248 clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
249
250 ret = s3c24xx_register_clock(clkp);
251 if (ret < 0) {
252 printk(KERN_ERR "Failed to register clock %s (%d)\n",
253 clkp->name, ret);
254 }
255 }
256
257 /* We must be careful disabling the clocks we are not intending to
258 * be using at boot time, as subsystems such as the LCD which do
259 * their own DMA requests to the bus can cause the system to lockup
260 * if they where in the middle of requesting bus access.
261 *
262 * Disabling the LCD clock if the LCD is active is very dangerous,
263 * and therefore the bootloader should be careful to not enable
264 * the LCD clock if it is not needed.
265 */
266
267 /* install (and disable) the clocks we do not need immediately */
268
269 s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
270 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
271
272 /* show the clock-slow value */
273
274 xtal = clk_get(NULL, "xtal");
275
276 printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
277 print_mhz(clk_get_rate(xtal) /
278 ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
279 (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
280 (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
281 (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
282
283 return 0;
284}
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2440.c b/arch/arm/mach-s3c24xx/clock-s3c2440.c
deleted file mode 100644
index 5527226fd61f..000000000000
--- a/arch/arm/mach-s3c24xx/clock-s3c2440.c
+++ /dev/null
@@ -1,217 +0,0 @@
1/* linux/arch/arm/mach-s3c2440/clock.c
2 *
3 * Copyright (c) 2004-2005 Simtec Electronics
4 * http://armlinux.simtec.co.uk/
5 * Ben Dooks <ben@simtec.co.uk>
6 *
7 * S3C2440 Clock support
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22*/
23
24#include <linux/init.h>
25#include <linux/module.h>
26#include <linux/kernel.h>
27#include <linux/list.h>
28#include <linux/errno.h>
29#include <linux/err.h>
30#include <linux/device.h>
31#include <linux/interrupt.h>
32#include <linux/ioport.h>
33#include <linux/mutex.h>
34#include <linux/clk.h>
35#include <linux/io.h>
36#include <linux/serial_core.h>
37#include <linux/serial_s3c.h>
38
39#include <mach/hardware.h>
40#include <linux/atomic.h>
41#include <asm/irq.h>
42
43#include <mach/regs-clock.h>
44
45#include <plat/clock.h>
46#include <plat/cpu.h>
47
48/* S3C2440 extended clock support */
49
50static unsigned long s3c2440_camif_upll_round(struct clk *clk,
51 unsigned long rate)
52{
53 unsigned long parent_rate = clk_get_rate(clk->parent);
54 int div;
55
56 if (rate > parent_rate)
57 return parent_rate;
58
59 /* note, we remove the +/- 1 calculations for the divisor */
60
61 div = (parent_rate / rate) / 2;
62
63 if (div < 1)
64 div = 1;
65 else if (div > 16)
66 div = 16;
67
68 return parent_rate / (div * 2);
69}
70
71static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate)
72{
73 unsigned long parent_rate = clk_get_rate(clk->parent);
74 unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
75
76 rate = s3c2440_camif_upll_round(clk, rate);
77
78 camdivn &= ~(S3C2440_CAMDIVN_CAMCLK_SEL | S3C2440_CAMDIVN_CAMCLK_MASK);
79
80 if (rate != parent_rate) {
81 camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
82 camdivn |= (((parent_rate / rate) / 2) - 1);
83 }
84
85 __raw_writel(camdivn, S3C2440_CAMDIVN);
86
87 return 0;
88}
89
90static unsigned long s3c2440_camif_upll_getrate(struct clk *clk)
91{
92 unsigned long parent_rate = clk_get_rate(clk->parent);
93 unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
94
95 if (!(camdivn & S3C2440_CAMDIVN_CAMCLK_SEL))
96 return parent_rate;
97
98 camdivn &= S3C2440_CAMDIVN_CAMCLK_MASK;
99
100 return parent_rate / (camdivn + 1) / 2;
101}
102
103/* Extra S3C2440 clocks */
104
105static struct clk s3c2440_clk_cam = {
106 .name = "camif",
107 .enable = s3c2410_clkcon_enable,
108 .ctrlbit = S3C2440_CLKCON_CAMERA,
109};
110
111static struct clk s3c2440_clk_cam_upll = {
112 .name = "camif-upll",
113 .ops = &(struct clk_ops) {
114 .set_rate = s3c2440_camif_upll_setrate,
115 .get_rate = s3c2440_camif_upll_getrate,
116 .round_rate = s3c2440_camif_upll_round,
117 },
118};
119
120static struct clk s3c2440_clk_ac97 = {
121 .name = "ac97",
122 .enable = s3c2410_clkcon_enable,
123 .ctrlbit = S3C2440_CLKCON_AC97,
124};
125
126#define S3C24XX_VA_UART0 (S3C_VA_UART)
127#define S3C24XX_VA_UART1 (S3C_VA_UART + 0x4000 )
128#define S3C24XX_VA_UART2 (S3C_VA_UART + 0x8000 )
129#define S3C24XX_VA_UART3 (S3C_VA_UART + 0xC000 )
130
131static unsigned long s3c2440_fclk_n_getrate(struct clk *clk)
132{
133 unsigned long ucon0, ucon1, ucon2, divisor;
134
135 /* the fun of calculating the uart divisors on the s3c2440 */
136 ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
137 ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
138 ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
139
140 ucon0 &= S3C2440_UCON0_DIVMASK;
141 ucon1 &= S3C2440_UCON1_DIVMASK;
142 ucon2 &= S3C2440_UCON2_DIVMASK;
143
144 if (ucon0 != 0)
145 divisor = (ucon0 >> S3C2440_UCON_DIVSHIFT) + 6;
146 else if (ucon1 != 0)
147 divisor = (ucon1 >> S3C2440_UCON_DIVSHIFT) + 21;
148 else if (ucon2 != 0)
149 divisor = (ucon2 >> S3C2440_UCON_DIVSHIFT) + 36;
150 else
151 /* manual calims 44, seems to be 9 */
152 divisor = 9;
153
154 return clk_get_rate(clk->parent) / divisor;
155}
156
157static struct clk s3c2440_clk_fclk_n = {
158 .name = "fclk_n",
159 .parent = &clk_f,
160 .ops = &(struct clk_ops) {
161 .get_rate = s3c2440_fclk_n_getrate,
162 },
163};
164
165static struct clk_lookup s3c2440_clk_lookup[] = {
166 CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
167 CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
168 CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n),
169 CLKDEV_INIT("s3c2440-uart.0", "uart", &s3c24xx_clk_uart0),
170 CLKDEV_INIT("s3c2440-uart.1", "uart", &s3c24xx_clk_uart1),
171 CLKDEV_INIT("s3c2440-uart.2", "uart", &s3c24xx_clk_uart2),
172 CLKDEV_INIT("s3c2440-camif", "camera", &s3c2440_clk_cam_upll),
173};
174
175static int __init_refok s3c2440_clk_add(struct device *dev, struct subsys_interface *sif)
176{
177 struct clk *clock_upll;
178 struct clk *clock_h;
179 struct clk *clock_p;
180
181 clock_p = clk_get(NULL, "pclk");
182 clock_h = clk_get(NULL, "hclk");
183 clock_upll = clk_get(NULL, "upll");
184
185 if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
186 printk(KERN_ERR "S3C2440: Failed to get parent clocks\n");
187 return -EINVAL;
188 }
189
190 s3c2440_clk_cam.parent = clock_h;
191 s3c2440_clk_ac97.parent = clock_p;
192 s3c2440_clk_cam_upll.parent = clock_upll;
193 s3c24xx_register_clock(&s3c2440_clk_fclk_n);
194
195 s3c24xx_register_clock(&s3c2440_clk_ac97);
196 s3c24xx_register_clock(&s3c2440_clk_cam);
197 s3c24xx_register_clock(&s3c2440_clk_cam_upll);
198 clkdev_add_table(s3c2440_clk_lookup, ARRAY_SIZE(s3c2440_clk_lookup));
199
200 clk_disable(&s3c2440_clk_ac97);
201 clk_disable(&s3c2440_clk_cam);
202
203 return 0;
204}
205
206static struct subsys_interface s3c2440_clk_interface = {
207 .name = "s3c2440_clk",
208 .subsys = &s3c2440_subsys,
209 .add_dev = s3c2440_clk_add,
210};
211
212static __init int s3c24xx_clk_init(void)
213{
214 return subsys_interface_register(&s3c2440_clk_interface);
215}
216
217arch_initcall(s3c24xx_clk_init);
diff --git a/arch/arm/mach-s3c24xx/clock-s3c244x.c b/arch/arm/mach-s3c24xx/clock-s3c244x.c
deleted file mode 100644
index 6d9b688c442b..000000000000
--- a/arch/arm/mach-s3c24xx/clock-s3c244x.c
+++ /dev/null
@@ -1,141 +0,0 @@
1/* linux/arch/arm/plat-s3c24xx/s3c24xx-clock.c
2 *
3 * Copyright (c) 2004-2008 Simtec Electronics
4 * http://armlinux.simtec.co.uk/
5 * Ben Dooks <ben@simtec.co.uk>
6 *
7 * S3C2440/S3C2442 Common clock support
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22*/
23
24#include <linux/init.h>
25#include <linux/module.h>
26#include <linux/kernel.h>
27#include <linux/list.h>
28#include <linux/errno.h>
29#include <linux/err.h>
30#include <linux/device.h>
31#include <linux/interrupt.h>
32#include <linux/ioport.h>
33#include <linux/clk.h>
34#include <linux/io.h>
35
36#include <mach/hardware.h>
37#include <linux/atomic.h>
38#include <asm/irq.h>
39
40#include <mach/regs-clock.h>
41
42#include <plat/clock.h>
43#include <plat/cpu.h>
44
45static int s3c2440_setparent_armclk(struct clk *clk, struct clk *parent)
46{
47 unsigned long camdivn;
48 unsigned long dvs;
49
50 if (parent == &clk_f)
51 dvs = 0;
52 else if (parent == &clk_h)
53 dvs = S3C2440_CAMDIVN_DVSEN;
54 else
55 return -EINVAL;
56
57 clk->parent = parent;
58
59 camdivn = __raw_readl(S3C2440_CAMDIVN);
60 camdivn &= ~S3C2440_CAMDIVN_DVSEN;
61 camdivn |= dvs;
62 __raw_writel(camdivn, S3C2440_CAMDIVN);
63
64 return 0;
65}
66
67static struct clk clk_arm = {
68 .name = "armclk",
69 .id = -1,
70 .ops = &(struct clk_ops) {
71 .set_parent = s3c2440_setparent_armclk,
72 },
73};
74
75static int s3c244x_clk_add(struct device *dev, struct subsys_interface *sif)
76{
77 unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
78 unsigned long clkdivn;
79 struct clk *clock_upll;
80 int ret;
81
82 printk("S3C244X: Clock Support, DVS %s\n",
83 (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
84
85 clk_arm.parent = (camdivn & S3C2440_CAMDIVN_DVSEN) ? &clk_h : &clk_f;
86
87 ret = s3c24xx_register_clock(&clk_arm);
88 if (ret < 0) {
89 printk(KERN_ERR "S3C24XX: Failed to add armclk (%d)\n", ret);
90 return ret;
91 }
92
93 clock_upll = clk_get(NULL, "upll");
94 if (IS_ERR(clock_upll)) {
95 printk(KERN_ERR "S3C244X: Failed to get upll clock\n");
96 return -ENOENT;
97 }
98
99 /* check rate of UPLL, and if it is near 96MHz, then change
100 * to using half the UPLL rate for the system */
101
102 if (clk_get_rate(clock_upll) > (94 * MHZ)) {
103 clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
104
105 spin_lock(&clocks_lock);
106
107 clkdivn = __raw_readl(S3C2410_CLKDIVN);
108 clkdivn |= S3C2440_CLKDIVN_UCLK;
109 __raw_writel(clkdivn, S3C2410_CLKDIVN);
110
111 spin_unlock(&clocks_lock);
112 }
113
114 return 0;
115}
116
117static struct subsys_interface s3c2440_clk_interface = {
118 .name = "s3c2440_clk",
119 .subsys = &s3c2440_subsys,
120 .add_dev = s3c244x_clk_add,
121};
122
123static int s3c2440_clk_init(void)
124{
125 return subsys_interface_register(&s3c2440_clk_interface);
126}
127
128arch_initcall(s3c2440_clk_init);
129
130static struct subsys_interface s3c2442_clk_interface = {
131 .name = "s3c2442_clk",
132 .subsys = &s3c2442_subsys,
133 .add_dev = s3c244x_clk_add,
134};
135
136static int s3c2442_clk_init(void)
137{
138 return subsys_interface_register(&s3c2442_clk_interface);
139}
140
141arch_initcall(s3c2442_clk_init);
diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h
index 2d6554140161..ac3ff12a0601 100644
--- a/arch/arm/mach-s3c24xx/common.h
+++ b/arch/arm/mach-s3c24xx/common.h
@@ -67,10 +67,8 @@ extern struct syscore_ops s3c2416_irq_syscore_ops;
67#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) 67#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
68extern void s3c244x_map_io(void); 68extern void s3c244x_map_io(void);
69extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no); 69extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
70extern void s3c244x_init_clocks(int xtal);
71extern void s3c244x_restart(enum reboot_mode mode, const char *cmd); 70extern void s3c244x_restart(enum reboot_mode mode, const char *cmd);
72#else 71#else
73#define s3c244x_init_clocks NULL
74#define s3c244x_init_uarts NULL 72#define s3c244x_init_uarts NULL
75#endif 73#endif
76 74
diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-clock.h b/arch/arm/mach-s3c24xx/include/mach/regs-clock.h
index 3415b60082d7..3db6c10de023 100644
--- a/arch/arm/mach-s3c24xx/include/mach/regs-clock.h
+++ b/arch/arm/mach-s3c24xx/include/mach/regs-clock.h
@@ -42,24 +42,6 @@
42#define S3C2410_CLKCON_IIS (1<<17) 42#define S3C2410_CLKCON_IIS (1<<17)
43#define S3C2410_CLKCON_SPI (1<<18) 43#define S3C2410_CLKCON_SPI (1<<18)
44 44
45/* DCLKCON register addresses in gpio.h */
46
47#define S3C2410_DCLKCON_DCLK0EN (1<<0)
48#define S3C2410_DCLKCON_DCLK0_PCLK (0<<1)
49#define S3C2410_DCLKCON_DCLK0_UCLK (1<<1)
50#define S3C2410_DCLKCON_DCLK0_DIV(x) (((x) - 1 )<<4)
51#define S3C2410_DCLKCON_DCLK0_CMP(x) (((x) - 1 )<<8)
52#define S3C2410_DCLKCON_DCLK0_DIV_MASK ((0xf)<<4)
53#define S3C2410_DCLKCON_DCLK0_CMP_MASK ((0xf)<<8)
54
55#define S3C2410_DCLKCON_DCLK1EN (1<<16)
56#define S3C2410_DCLKCON_DCLK1_PCLK (0<<17)
57#define S3C2410_DCLKCON_DCLK1_UCLK (1<<17)
58#define S3C2410_DCLKCON_DCLK1_DIV(x) (((x) - 1) <<20)
59#define S3C2410_DCLKCON_DCLK1_CMP(x) (((x) - 1) <<24)
60#define S3C2410_DCLKCON_DCLK1_DIV_MASK ((0xf) <<20)
61#define S3C2410_DCLKCON_DCLK1_CMP_MASK ((0xf) <<24)
62
63#define S3C2410_CLKDIVN_PDIVN (1<<0) 45#define S3C2410_CLKDIVN_PDIVN (1<<0)
64#define S3C2410_CLKDIVN_HDIVN (1<<1) 46#define S3C2410_CLKDIVN_HDIVN (1<<1)
65 47
diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h b/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h
index c2ef016032ab..c6583cfa5835 100644
--- a/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h
@@ -457,9 +457,6 @@
457 457
458/* miscellaneous control */ 458/* miscellaneous control */
459#define S3C2410_MISCCR S3C2410_GPIOREG(0x80) 459#define S3C2410_MISCCR S3C2410_GPIOREG(0x80)
460#define S3C2410_DCLKCON S3C2410_GPIOREG(0x84)
461
462#define S3C24XX_DCLKCON S3C24XX_GPIOREG2(0x84)
463 460
464/* see clock.h for dclk definitions */ 461/* see clock.h for dclk definitions */
465 462
diff --git a/arch/arm/mach-s3c24xx/pm.c b/arch/arm/mach-s3c24xx/pm.c
index 16281bdc750a..3d8cf3054e7f 100644
--- a/arch/arm/mach-s3c24xx/pm.c
+++ b/arch/arm/mach-s3c24xx/pm.c
@@ -80,12 +80,6 @@ static struct sleep_save core_save[] = {
80#endif /* CONFIG_SAMSUNG_CLOCK */ 80#endif /* CONFIG_SAMSUNG_CLOCK */
81}; 81};
82 82
83#ifdef CONFIG_SAMSUNG_CLOCK
84static struct sleep_save misc_save[] = {
85 SAVE_ITEM(S3C2410_DCLKCON),
86};
87#endif
88
89/* s3c_pm_check_resume_pin 83/* s3c_pm_check_resume_pin
90 * 84 *
91 * check to see if the pin is configured correctly for sleep mode, and 85 * check to see if the pin is configured correctly for sleep mode, and
@@ -143,16 +137,10 @@ void s3c_pm_configure_extint(void)
143void s3c_pm_restore_core(void) 137void s3c_pm_restore_core(void)
144{ 138{
145 s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); 139 s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
146#ifdef CONFIG_SAMSUNG_CLOCK
147 s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
148#endif
149} 140}
150 141
151void s3c_pm_save_core(void) 142void s3c_pm_save_core(void)
152{ 143{
153#ifdef CONFIG_SAMSUNG_CLOCK
154 s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
155#endif
156 s3c_pm_do_save(core_save, ARRAY_SIZE(core_save)); 144 s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
157} 145}
158 146
diff --git a/arch/arm/mach-s3c24xx/s3c2410.c b/arch/arm/mach-s3c24xx/s3c2410.c
index 52801730ab24..7eab88829883 100644
--- a/arch/arm/mach-s3c24xx/s3c2410.c
+++ b/arch/arm/mach-s3c24xx/s3c2410.c
@@ -83,71 +83,9 @@ void __init s3c2410_map_io(void)
83 iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc)); 83 iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
84} 84}
85 85
86#ifdef CONFIG_SAMSUNG_CLOCK
87void __init_or_cpufreq s3c2410_setup_clocks(void) 86void __init_or_cpufreq s3c2410_setup_clocks(void)
88{ 87{
89 struct clk *xtal_clk;
90 unsigned long tmp;
91 unsigned long xtal;
92 unsigned long fclk;
93 unsigned long hclk;
94 unsigned long pclk;
95
96 xtal_clk = clk_get(NULL, "xtal");
97 xtal = clk_get_rate(xtal_clk);
98 clk_put(xtal_clk);
99
100 /* now we've got our machine bits initialised, work out what
101 * clocks we've got */
102
103 fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal);
104
105 tmp = __raw_readl(S3C2410_CLKDIVN);
106
107 /* work out clock scalings */
108
109 hclk = fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1);
110 pclk = hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1);
111
112 /* print brieft summary of clocks, etc */
113
114 printk("S3C2410: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
115 print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
116
117 /* initialise the clocks here, to allow other things like the
118 * console to use them
119 */
120
121 s3c24xx_setup_clocks(fclk, hclk, pclk);
122}
123
124/* fake ARMCLK for use with cpufreq, etc. */
125
126static struct clk s3c2410_armclk = {
127 .name = "armclk",
128 .parent = &clk_f,
129 .id = -1,
130};
131
132static struct clk_lookup s3c2410_clk_lookup[] = {
133 CLKDEV_INIT(NULL, "clk_uart_baud0", &clk_p),
134 CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
135};
136
137void __init s3c2410_init_clocks(int xtal)
138{
139 s3c24xx_register_baseclocks(xtal);
140 s3c2410_setup_clocks();
141 s3c2410_baseclk_add();
142 s3c24xx_register_clock(&s3c2410_armclk);
143 clkdev_add_table(s3c2410_clk_lookup, ARRAY_SIZE(s3c2410_clk_lookup));
144 samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG);
145} 88}
146#else
147void __init_or_cpufreq s3c2410_setup_clocks(void)
148{
149}
150#endif
151 89
152struct bus_type s3c2410_subsys = { 90struct bus_type s3c2410_subsys = {
153 .name = "s3c2410-core", 91 .name = "s3c2410-core",
diff --git a/arch/arm/mach-s3c24xx/s3c2442.c b/arch/arm/mach-s3c24xx/s3c2442.c
index 564c65037ff2..fb9da2b603a2 100644
--- a/arch/arm/mach-s3c24xx/s3c2442.c
+++ b/arch/arm/mach-s3c24xx/s3c2442.c
@@ -53,118 +53,6 @@
53 53
54#include "common.h" 54#include "common.h"
55 55
56#ifdef CONFIG_SAMSUNG_CLOCK
57/* S3C2442 extended clock support */
58
59static unsigned long s3c2442_camif_upll_round(struct clk *clk,
60 unsigned long rate)
61{
62 unsigned long parent_rate = clk_get_rate(clk->parent);
63 int div;
64
65 if (rate > parent_rate)
66 return parent_rate;
67
68 div = parent_rate / rate;
69
70 if (div == 3)
71 return parent_rate / 3;
72
73 /* note, we remove the +/- 1 calculations for the divisor */
74
75 div /= 2;
76
77 if (div < 1)
78 div = 1;
79 else if (div > 16)
80 div = 16;
81
82 return parent_rate / (div * 2);
83}
84
85static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
86{
87 unsigned long parent_rate = clk_get_rate(clk->parent);
88 unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
89
90 rate = s3c2442_camif_upll_round(clk, rate);
91
92 camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3;
93
94 if (rate == parent_rate) {
95 camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL;
96 } else if ((parent_rate / rate) == 3) {
97 camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
98 camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3;
99 } else {
100 camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK;
101 camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
102 camdivn |= (((parent_rate / rate) / 2) - 1);
103 }
104
105 __raw_writel(camdivn, S3C2440_CAMDIVN);
106
107 return 0;
108}
109
110/* Extra S3C2442 clocks */
111
112static struct clk s3c2442_clk_cam = {
113 .name = "camif",
114 .id = -1,
115 .enable = s3c2410_clkcon_enable,
116 .ctrlbit = S3C2440_CLKCON_CAMERA,
117};
118
119static struct clk s3c2442_clk_cam_upll = {
120 .name = "camif-upll",
121 .id = -1,
122 .ops = &(struct clk_ops) {
123 .set_rate = s3c2442_camif_upll_setrate,
124 .round_rate = s3c2442_camif_upll_round,
125 },
126};
127
128static int s3c2442_clk_add(struct device *dev, struct subsys_interface *sif)
129{
130 struct clk *clock_upll;
131 struct clk *clock_h;
132 struct clk *clock_p;
133
134 clock_p = clk_get(NULL, "pclk");
135 clock_h = clk_get(NULL, "hclk");
136 clock_upll = clk_get(NULL, "upll");
137
138 if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
139 printk(KERN_ERR "S3C2442: Failed to get parent clocks\n");
140 return -EINVAL;
141 }
142
143 s3c2442_clk_cam.parent = clock_h;
144 s3c2442_clk_cam_upll.parent = clock_upll;
145
146 s3c24xx_register_clock(&s3c2442_clk_cam);
147 s3c24xx_register_clock(&s3c2442_clk_cam_upll);
148
149 clk_disable(&s3c2442_clk_cam);
150
151 return 0;
152}
153
154static struct subsys_interface s3c2442_clk_interface = {
155 .name = "s3c2442_clk",
156 .subsys = &s3c2442_subsys,
157 .add_dev = s3c2442_clk_add,
158};
159
160static __init int s3c2442_clk_init(void)
161{
162 return subsys_interface_register(&s3c2442_clk_interface);
163}
164
165arch_initcall(s3c2442_clk_init);
166#endif
167
168static struct device s3c2442_dev = { 56static struct device s3c2442_dev = {
169 .bus = &s3c2442_subsys, 57 .bus = &s3c2442_subsys,
170}; 58};
diff --git a/arch/arm/mach-s3c24xx/s3c244x.c b/arch/arm/mach-s3c24xx/s3c244x.c
index 1d665d50b034..4a64bcc9eb51 100644
--- a/arch/arm/mach-s3c24xx/s3c244x.c
+++ b/arch/arm/mach-s3c24xx/s3c244x.c
@@ -78,72 +78,9 @@ void __init s3c244x_map_io(void)
78 s3c2410_device_dclk.name = "s3c2440-dclk"; 78 s3c2410_device_dclk.name = "s3c2440-dclk";
79} 79}
80 80
81#ifdef CONFIG_SAMSUNG_CLOCK
82void __init_or_cpufreq s3c244x_setup_clocks(void) 81void __init_or_cpufreq s3c244x_setup_clocks(void)
83{ 82{
84 struct clk *xtal_clk;
85 unsigned long clkdiv;
86 unsigned long camdiv;
87 unsigned long xtal;
88 unsigned long hclk, fclk, pclk;
89 int hdiv = 1;
90
91 xtal_clk = clk_get(NULL, "xtal");
92 xtal = clk_get_rate(xtal_clk);
93 clk_put(xtal_clk);
94
95 fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
96
97 clkdiv = __raw_readl(S3C2410_CLKDIVN);
98 camdiv = __raw_readl(S3C2440_CAMDIVN);
99
100 /* work out clock scalings */
101
102 switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
103 case S3C2440_CLKDIVN_HDIVN_1:
104 hdiv = 1;
105 break;
106
107 case S3C2440_CLKDIVN_HDIVN_2:
108 hdiv = 2;
109 break;
110
111 case S3C2440_CLKDIVN_HDIVN_4_8:
112 hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
113 break;
114
115 case S3C2440_CLKDIVN_HDIVN_3_6:
116 hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
117 break;
118 }
119
120 hclk = fclk / hdiv;
121 pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN) ? 2 : 1);
122
123 /* print brief summary of clocks, etc */
124
125 printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
126 print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
127
128 s3c24xx_setup_clocks(fclk, hclk, pclk);
129}
130
131void __init s3c244x_init_clocks(int xtal)
132{
133 /* initialise the clocks here, to allow other things like the
134 * console to use them, and to add new ones after the initialisation
135 */
136
137 s3c24xx_register_baseclocks(xtal);
138 s3c244x_setup_clocks();
139 s3c2410_baseclk_add();
140 samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG);
141} 83}
142#else
143void __init_or_cpufreq s3c244x_setup_clocks(void)
144{
145}
146#endif
147 84
148/* Since the S3C2442 and S3C2440 share items, put both subsystems here */ 85/* Since the S3C2442 and S3C2440 share items, put both subsystems here */
149 86