diff options
author | Ben Dooks <ben-linux@fluff.org> | 2010-03-07 17:56:19 -0500 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2010-03-07 17:56:19 -0500 |
commit | 3b05007e43ea629394e89ea0b023d7b15375a2bb (patch) | |
tree | f96ba06dc0f8934786d40351eeeadb40675e04ee /arch | |
parent | f9fed7cd7efaa0d050f21f6f9ed532d3143b7369 (diff) | |
parent | 41f23a09f32124322dc41bea7f65baff6e9b0ac5 (diff) |
ARM: Merge next-samsung-s3c2443-clock
Merge branch 'next-samsung-s3c2443-clock' into next-samsung
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h | 32 | ||||
-rw-r--r-- | arch/arm/mach-s3c2443/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-s3c2443/clock.c | 817 |
3 files changed, 261 insertions, 589 deletions
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h index 6026d091a2fe..d87ebe0cb625 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h | |||
@@ -42,23 +42,14 @@ | |||
42 | 42 | ||
43 | #define S3C2443_PLLCON_OFF (1<<24) | 43 | #define S3C2443_PLLCON_OFF (1<<24) |
44 | 44 | ||
45 | #define S3C2443_CLKSRC_I2S_EXT (1<<14) | ||
46 | #define S3C2443_CLKSRC_I2S_EPLLDIV (0<<14) | ||
47 | #define S3C2443_CLKSRC_I2S_EPLLREF (2<<14) | ||
48 | #define S3C2443_CLKSRC_I2S_EPLLREF3 (3<<14) | ||
49 | #define S3C2443_CLKSRC_I2S_MASK (3<<14) | ||
50 | |||
51 | #define S3C2443_CLKSRC_EPLLREF_XTAL (2<<7) | 45 | #define S3C2443_CLKSRC_EPLLREF_XTAL (2<<7) |
52 | #define S3C2443_CLKSRC_EPLLREF_EXTCLK (3<<7) | 46 | #define S3C2443_CLKSRC_EPLLREF_EXTCLK (3<<7) |
53 | #define S3C2443_CLKSRC_EPLLREF_MPLLREF (0<<7) | 47 | #define S3C2443_CLKSRC_EPLLREF_MPLLREF (0<<7) |
54 | #define S3C2443_CLKSRC_EPLLREF_MPLLREF2 (1<<7) | 48 | #define S3C2443_CLKSRC_EPLLREF_MPLLREF2 (1<<7) |
55 | #define S3C2443_CLKSRC_EPLLREF_MASK (3<<7) | 49 | #define S3C2443_CLKSRC_EPLLREF_MASK (3<<7) |
56 | 50 | ||
57 | #define S3C2443_CLKSRC_ESYSCLK_EPLL (1<<6) | ||
58 | #define S3C2443_CLKSRC_MSYSCLK_MPLL (1<<4) | ||
59 | #define S3C2443_CLKSRC_EXTCLK_DIV (1<<3) | 51 | #define S3C2443_CLKSRC_EXTCLK_DIV (1<<3) |
60 | 52 | ||
61 | #define S3C2443_CLKDIV0_DVS (1<<13) | ||
62 | #define S3C2443_CLKDIV0_HALF_HCLK (1<<3) | 53 | #define S3C2443_CLKDIV0_HALF_HCLK (1<<3) |
63 | #define S3C2443_CLKDIV0_HALF_PCLK (1<<2) | 54 | #define S3C2443_CLKDIV0_HALF_PCLK (1<<2) |
64 | 55 | ||
@@ -81,28 +72,7 @@ | |||
81 | #define S3C2443_CLKDIV0_ARMDIV_12 (13<<9) | 72 | #define S3C2443_CLKDIV0_ARMDIV_12 (13<<9) |
82 | #define S3C2443_CLKDIV0_ARMDIV_16 (15<<9) | 73 | #define S3C2443_CLKDIV0_ARMDIV_16 (15<<9) |
83 | 74 | ||
84 | /* S3C2443_CLKDIV1 */ | 75 | /* S3C2443_CLKDIV1 removed, only used in clock.c code */ |
85 | |||
86 | #define S3C2443_CLKDIV1_CAMDIV_MASK (15<<26) | ||
87 | #define S3C2443_CLKDIV1_CAMDIV_SHIFT (26) | ||
88 | |||
89 | #define S3C2443_CLKDIV1_HSSPIDIV_MASK (3<<24) | ||
90 | #define S3C2443_CLKDIV1_HSSPIDIV_SHIFT (24) | ||
91 | |||
92 | #define S3C2443_CLKDIV1_DISPDIV_MASK (0xff<<16) | ||
93 | #define S3C2443_CLKDIV1_DISPDIV_SHIFT (16) | ||
94 | |||
95 | #define S3C2443_CLKDIV1_I2SDIV_MASK (15<<12) | ||
96 | #define S3C2443_CLKDIV1_I2SDIV_SHIFT (12) | ||
97 | |||
98 | #define S3C2443_CLKDIV1_UARTDIV_MASK (15<<8) | ||
99 | #define S3C2443_CLKDIV1_UARTDIV_SHIFT (8) | ||
100 | |||
101 | #define S3C2443_CLKDIV1_HSMMCDIV_MASK (3<<6) | ||
102 | #define S3C2443_CLKDIV1_HSMMCDIV_SHIFT (6) | ||
103 | |||
104 | #define S3C2443_CLKDIV1_USBHOSTDIV_MASK (3<<4) | ||
105 | #define S3C2443_CLKDIV1_USBHOSTDIV_SHIFT (4) | ||
106 | 76 | ||
107 | #define S3C2443_CLKCON_NAND | 77 | #define S3C2443_CLKCON_NAND |
108 | 78 | ||
diff --git a/arch/arm/mach-s3c2443/Kconfig b/arch/arm/mach-s3c2443/Kconfig index 4314c4424909..698140af247c 100644 --- a/arch/arm/mach-s3c2443/Kconfig +++ b/arch/arm/mach-s3c2443/Kconfig | |||
@@ -7,6 +7,7 @@ config CPU_S3C2443 | |||
7 | depends on ARCH_S3C2410 | 7 | depends on ARCH_S3C2410 |
8 | select S3C2443_DMA if S3C2410_DMA | 8 | select S3C2443_DMA if S3C2410_DMA |
9 | select CPU_LLSERIAL_S3C2440 | 9 | select CPU_LLSERIAL_S3C2440 |
10 | select SAMSUNG_CLKSRC | ||
10 | help | 11 | help |
11 | Support for the S3C2443 SoC from the S3C24XX line | 12 | Support for the S3C2443 SoC from the S3C24XX line |
12 | 13 | ||
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c index 3eb8b935d64c..62cd4eaee01b 100644 --- a/arch/arm/mach-s3c2443/clock.c +++ b/arch/arm/mach-s3c2443/clock.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* linux/arch/arm/mach-s3c2443/clock.c | 1 | /* linux/arch/arm/mach-s3c2443/clock.c |
2 | * | 2 | * |
3 | * Copyright (c) 2007 Simtec Electronics | 3 | * Copyright (c) 2007, 2010 Simtec Electronics |
4 | * Ben Dooks <ben@simtec.co.uk> | 4 | * Ben Dooks <ben@simtec.co.uk> |
5 | * | 5 | * |
6 | * S3C2443 Clock control support | 6 | * S3C2443 Clock control support |
@@ -42,6 +42,7 @@ | |||
42 | 42 | ||
43 | #include <plat/s3c2443.h> | 43 | #include <plat/s3c2443.h> |
44 | #include <plat/clock.h> | 44 | #include <plat/clock.h> |
45 | #include <plat/clock-clksrc.h> | ||
45 | #include <plat/cpu.h> | 46 | #include <plat/cpu.h> |
46 | 47 | ||
47 | /* We currently have to assume that the system is running | 48 | /* We currently have to assume that the system is running |
@@ -53,143 +54,69 @@ | |||
53 | * set the correct muxing at initialisation | 54 | * set the correct muxing at initialisation |
54 | */ | 55 | */ |
55 | 56 | ||
56 | static int s3c2443_clkcon_enable_h(struct clk *clk, int enable) | 57 | static int s3c2443_gate(void __iomem *reg, struct clk *clk, int enable) |
57 | { | ||
58 | unsigned int clocks = clk->ctrlbit; | ||
59 | unsigned long clkcon; | ||
60 | |||
61 | clkcon = __raw_readl(S3C2443_HCLKCON); | ||
62 | |||
63 | if (enable) | ||
64 | clkcon |= clocks; | ||
65 | else | ||
66 | clkcon &= ~clocks; | ||
67 | |||
68 | __raw_writel(clkcon, S3C2443_HCLKCON); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int s3c2443_clkcon_enable_p(struct clk *clk, int enable) | ||
74 | { | ||
75 | unsigned int clocks = clk->ctrlbit; | ||
76 | unsigned long clkcon; | ||
77 | |||
78 | clkcon = __raw_readl(S3C2443_PCLKCON); | ||
79 | |||
80 | if (enable) | ||
81 | clkcon |= clocks; | ||
82 | else | ||
83 | clkcon &= ~clocks; | ||
84 | |||
85 | __raw_writel(clkcon, S3C2443_PCLKCON); | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int s3c2443_clkcon_enable_s(struct clk *clk, int enable) | ||
91 | { | 58 | { |
92 | unsigned int clocks = clk->ctrlbit; | 59 | u32 ctrlbit = clk->ctrlbit; |
93 | unsigned long clkcon; | 60 | u32 con = __raw_readl(reg); |
94 | |||
95 | clkcon = __raw_readl(S3C2443_SCLKCON); | ||
96 | 61 | ||
97 | if (enable) | 62 | if (enable) |
98 | clkcon |= clocks; | 63 | con |= ctrlbit; |
99 | else | 64 | else |
100 | clkcon &= ~clocks; | 65 | con &= ~ctrlbit; |
101 | |||
102 | __raw_writel(clkcon, S3C2443_SCLKCON); | ||
103 | 66 | ||
67 | __raw_writel(con, reg); | ||
104 | return 0; | 68 | return 0; |
105 | } | 69 | } |
106 | 70 | ||
107 | static unsigned long s3c2443_roundrate_clksrc(struct clk *clk, | 71 | static int s3c2443_clkcon_enable_h(struct clk *clk, int enable) |
108 | unsigned long rate, | ||
109 | unsigned int max) | ||
110 | { | ||
111 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
112 | int div; | ||
113 | |||
114 | if (rate > parent_rate) | ||
115 | return parent_rate; | ||
116 | |||
117 | /* note, we remove the +/- 1 calculations as they cancel out */ | ||
118 | |||
119 | div = (rate / parent_rate); | ||
120 | |||
121 | if (div < 1) | ||
122 | div = 1; | ||
123 | else if (div > max) | ||
124 | div = max; | ||
125 | |||
126 | return parent_rate / div; | ||
127 | } | ||
128 | |||
129 | static unsigned long s3c2443_roundrate_clksrc4(struct clk *clk, | ||
130 | unsigned long rate) | ||
131 | { | 72 | { |
132 | return s3c2443_roundrate_clksrc(clk, rate, 4); | 73 | return s3c2443_gate(S3C2443_HCLKCON, clk, enable); |
133 | } | 74 | } |
134 | 75 | ||
135 | static unsigned long s3c2443_roundrate_clksrc16(struct clk *clk, | 76 | static int s3c2443_clkcon_enable_p(struct clk *clk, int enable) |
136 | unsigned long rate) | ||
137 | { | 77 | { |
138 | return s3c2443_roundrate_clksrc(clk, rate, 16); | 78 | return s3c2443_gate(S3C2443_PCLKCON, clk, enable); |
139 | } | 79 | } |
140 | 80 | ||
141 | static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk, | 81 | static int s3c2443_clkcon_enable_s(struct clk *clk, int enable) |
142 | unsigned long rate) | ||
143 | { | 82 | { |
144 | return s3c2443_roundrate_clksrc(clk, rate, 256); | 83 | return s3c2443_gate(S3C2443_SCLKCON, clk, enable); |
145 | } | 84 | } |
146 | 85 | ||
147 | /* clock selections */ | 86 | /* clock selections */ |
148 | 87 | ||
88 | /* mpllref is a direct descendant of clk_xtal by default, but it is not | ||
89 | * elided as the EPLL can be either sourced by the XTAL or EXTCLK and as | ||
90 | * such directly equating the two source clocks is impossible. | ||
91 | */ | ||
149 | static struct clk clk_mpllref = { | 92 | static struct clk clk_mpllref = { |
150 | .name = "mpllref", | 93 | .name = "mpllref", |
151 | .parent = &clk_xtal, | 94 | .parent = &clk_xtal, |
152 | .id = -1, | 95 | .id = -1, |
153 | }; | 96 | }; |
154 | 97 | ||
155 | #if 0 | ||
156 | static struct clk clk_mpll = { | ||
157 | .name = "mpll", | ||
158 | .parent = &clk_mpllref, | ||
159 | .id = -1, | ||
160 | }; | ||
161 | #endif | ||
162 | |||
163 | static struct clk clk_i2s_ext = { | 98 | static struct clk clk_i2s_ext = { |
164 | .name = "i2s-ext", | 99 | .name = "i2s-ext", |
165 | .id = -1, | 100 | .id = -1, |
166 | }; | 101 | }; |
167 | 102 | ||
168 | static int s3c2443_setparent_epllref(struct clk *clk, struct clk *parent) | 103 | static struct clk *clk_epllref_sources[] = { |
169 | { | 104 | [0] = &clk_mpllref, |
170 | unsigned long clksrc = __raw_readl(S3C2443_CLKSRC); | 105 | [1] = &clk_mpllref, |
171 | 106 | [2] = &clk_xtal, | |
172 | clksrc &= ~S3C2443_CLKSRC_EPLLREF_MASK; | 107 | [3] = &clk_ext, |
173 | 108 | }; | |
174 | if (parent == &clk_xtal) | ||
175 | clksrc |= S3C2443_CLKSRC_EPLLREF_XTAL; | ||
176 | else if (parent == &clk_ext) | ||
177 | clksrc |= S3C2443_CLKSRC_EPLLREF_EXTCLK; | ||
178 | else if (parent != &clk_mpllref) | ||
179 | return -EINVAL; | ||
180 | |||
181 | __raw_writel(clksrc, S3C2443_CLKSRC); | ||
182 | clk->parent = parent; | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | 109 | ||
187 | static struct clk clk_epllref = { | 110 | static struct clksrc_clk clk_epllref = { |
188 | .name = "epllref", | 111 | .clk = { |
189 | .id = -1, | 112 | .name = "epllref", |
190 | .ops = &(struct clk_ops) { | 113 | .id = -1, |
191 | .set_parent = s3c2443_setparent_epllref, | 114 | }, |
115 | .sources = &(struct clksrc_sources) { | ||
116 | .sources = clk_epllref_sources, | ||
117 | .nr_sources = ARRAY_SIZE(clk_epllref_sources), | ||
192 | }, | 118 | }, |
119 | .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 7 }, | ||
193 | }; | 120 | }; |
194 | 121 | ||
195 | static unsigned long s3c2443_getrate_mdivclk(struct clk *clk) | 122 | static unsigned long s3c2443_getrate_mdivclk(struct clk *clk) |
@@ -212,33 +139,24 @@ static struct clk clk_mdivclk = { | |||
212 | }, | 139 | }, |
213 | }; | 140 | }; |
214 | 141 | ||
215 | static int s3c2443_setparent_msysclk(struct clk *clk, struct clk *parent) | 142 | static struct clk *clk_msysclk_sources[] = { |
216 | { | 143 | [0] = &clk_mpllref, |
217 | unsigned long clksrc = __raw_readl(S3C2443_CLKSRC); | 144 | [1] = &clk_mpll, |
218 | 145 | [2] = &clk_mdivclk, | |
219 | clksrc &= ~(S3C2443_CLKSRC_MSYSCLK_MPLL | | 146 | [3] = &clk_mpllref, |
220 | S3C2443_CLKSRC_EXTCLK_DIV); | 147 | }; |
221 | |||
222 | if (parent == &clk_mpll) | ||
223 | clksrc |= S3C2443_CLKSRC_MSYSCLK_MPLL; | ||
224 | else if (parent == &clk_mdivclk) | ||
225 | clksrc |= S3C2443_CLKSRC_EXTCLK_DIV; | ||
226 | else if (parent != &clk_mpllref) | ||
227 | return -EINVAL; | ||
228 | |||
229 | __raw_writel(clksrc, S3C2443_CLKSRC); | ||
230 | clk->parent = parent; | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | 148 | ||
235 | static struct clk clk_msysclk = { | 149 | static struct clksrc_clk clk_msysclk = { |
236 | .name = "msysclk", | 150 | .clk = { |
237 | .parent = &clk_xtal, | 151 | .name = "msysclk", |
238 | .id = -1, | 152 | .parent = &clk_xtal, |
239 | .ops = &(struct clk_ops) { | 153 | .id = -1, |
240 | .set_parent = s3c2443_setparent_msysclk, | 154 | }, |
155 | .sources = &(struct clksrc_sources) { | ||
156 | .sources = clk_msysclk_sources, | ||
157 | .nr_sources = ARRAY_SIZE(clk_msysclk_sources), | ||
241 | }, | 158 | }, |
159 | .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 3 }, | ||
242 | }; | 160 | }; |
243 | 161 | ||
244 | /* armdiv | 162 | /* armdiv |
@@ -247,72 +165,128 @@ static struct clk clk_msysclk = { | |||
247 | * divider values applied to it to then be fed into armclk. | 165 | * divider values applied to it to then be fed into armclk. |
248 | */ | 166 | */ |
249 | 167 | ||
250 | static struct clk clk_armdiv = { | 168 | /* armdiv divisor table */ |
251 | .name = "armdiv", | 169 | |
252 | .id = -1, | 170 | static unsigned int armdiv[16] = { |
253 | .parent = &clk_msysclk, | 171 | [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1, |
172 | [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2, | ||
173 | [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3, | ||
174 | [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4, | ||
175 | [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6, | ||
176 | [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8, | ||
177 | [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12, | ||
178 | [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16, | ||
254 | }; | 179 | }; |
255 | 180 | ||
256 | /* armclk | 181 | static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0) |
257 | * | 182 | { |
258 | * this is the clock fed into the ARM core itself, either from | 183 | clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK; |
259 | * armdiv or from hclk. | ||
260 | */ | ||
261 | 184 | ||
262 | static int s3c2443_setparent_armclk(struct clk *clk, struct clk *parent) | 185 | return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]; |
186 | } | ||
187 | |||
188 | static unsigned long s3c2443_armclk_roundrate(struct clk *clk, | ||
189 | unsigned long rate) | ||
263 | { | 190 | { |
264 | unsigned long clkdiv0; | 191 | unsigned long parent = clk_get_rate(clk->parent); |
192 | unsigned long calc; | ||
193 | unsigned best = 256; /* bigger than any value */ | ||
194 | unsigned div; | ||
195 | int ptr; | ||
265 | 196 | ||
266 | clkdiv0 = __raw_readl(S3C2443_CLKDIV0); | 197 | for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) { |
198 | div = armdiv[ptr]; | ||
199 | calc = parent / div; | ||
200 | if (calc <= rate && div < best) | ||
201 | best = div; | ||
202 | } | ||
267 | 203 | ||
268 | if (parent == &clk_armdiv) | 204 | return parent / best; |
269 | clkdiv0 &= ~S3C2443_CLKDIV0_DVS; | 205 | } |
270 | else if (parent == &clk_h) | ||
271 | clkdiv0 |= S3C2443_CLKDIV0_DVS; | ||
272 | else | ||
273 | return -EINVAL; | ||
274 | 206 | ||
275 | __raw_writel(clkdiv0, S3C2443_CLKDIV0); | 207 | static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate) |
276 | return 0; | 208 | { |
209 | unsigned long parent = clk_get_rate(clk->parent); | ||
210 | unsigned long calc; | ||
211 | unsigned div; | ||
212 | unsigned best = 256; /* bigger than any value */ | ||
213 | int ptr; | ||
214 | int val = -1; | ||
215 | |||
216 | for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) { | ||
217 | div = armdiv[ptr]; | ||
218 | calc = parent / div; | ||
219 | if (calc <= rate && div < best) { | ||
220 | best = div; | ||
221 | val = ptr; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | if (val >= 0) { | ||
226 | unsigned long clkcon0; | ||
227 | |||
228 | clkcon0 = __raw_readl(S3C2443_CLKDIV0); | ||
229 | clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK; | ||
230 | clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT; | ||
231 | __raw_writel(clkcon0, S3C2443_CLKDIV0); | ||
232 | } | ||
233 | |||
234 | return (val == -1) ? -EINVAL : 0; | ||
277 | } | 235 | } |
278 | 236 | ||
279 | static struct clk clk_arm = { | 237 | static struct clk clk_armdiv = { |
280 | .name = "armclk", | 238 | .name = "armdiv", |
281 | .id = -1, | 239 | .id = -1, |
240 | .parent = &clk_msysclk.clk, | ||
282 | .ops = &(struct clk_ops) { | 241 | .ops = &(struct clk_ops) { |
283 | .set_parent = s3c2443_setparent_armclk, | 242 | .round_rate = s3c2443_armclk_roundrate, |
243 | .set_rate = s3c2443_armclk_setrate, | ||
284 | }, | 244 | }, |
285 | }; | 245 | }; |
286 | 246 | ||
287 | /* esysclk | 247 | /* armclk |
288 | * | 248 | * |
289 | * this is sourced from either the EPLL or the EPLLref clock | 249 | * this is the clock fed into the ARM core itself, from armdiv or from hclk. |
290 | */ | 250 | */ |
291 | 251 | ||
292 | static int s3c2443_setparent_esysclk(struct clk *clk, struct clk *parent) | 252 | static struct clk *clk_arm_sources[] = { |
293 | { | 253 | [0] = &clk_armdiv, |
294 | unsigned long clksrc = __raw_readl(S3C2443_CLKSRC); | 254 | [1] = &clk_h, |
255 | }; | ||
295 | 256 | ||
296 | if (parent == &clk_epll) | 257 | static struct clksrc_clk clk_arm = { |
297 | clksrc |= S3C2443_CLKSRC_ESYSCLK_EPLL; | 258 | .clk = { |
298 | else if (parent == &clk_epllref) | 259 | .name = "armclk", |
299 | clksrc &= ~S3C2443_CLKSRC_ESYSCLK_EPLL; | 260 | .id = -1, |
300 | else | 261 | }, |
301 | return -EINVAL; | 262 | .sources = &(struct clksrc_sources) { |
263 | .sources = clk_arm_sources, | ||
264 | .nr_sources = ARRAY_SIZE(clk_arm_sources), | ||
265 | }, | ||
266 | .reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 }, | ||
267 | }; | ||
302 | 268 | ||
303 | __raw_writel(clksrc, S3C2443_CLKSRC); | 269 | /* esysclk |
304 | clk->parent = parent; | 270 | * |
271 | * this is sourced from either the EPLL or the EPLLref clock | ||
272 | */ | ||
305 | 273 | ||
306 | return 0; | 274 | static struct clk *clk_sysclk_sources[] = { |
307 | } | 275 | [0] = &clk_epllref.clk, |
276 | [1] = &clk_epll, | ||
277 | }; | ||
308 | 278 | ||
309 | static struct clk clk_esysclk = { | 279 | static struct clksrc_clk clk_esysclk = { |
310 | .name = "esysclk", | 280 | .clk = { |
311 | .parent = &clk_epll, | 281 | .name = "esysclk", |
312 | .id = -1, | 282 | .parent = &clk_epll, |
313 | .ops = &(struct clk_ops) { | 283 | .id = -1, |
314 | .set_parent = s3c2443_setparent_esysclk, | 284 | }, |
285 | .sources = &(struct clksrc_sources) { | ||
286 | .sources = clk_sysclk_sources, | ||
287 | .nr_sources = ARRAY_SIZE(clk_sysclk_sources), | ||
315 | }, | 288 | }, |
289 | .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 6 }, | ||
316 | }; | 290 | }; |
317 | 291 | ||
318 | /* uartclk | 292 | /* uartclk |
@@ -320,87 +294,30 @@ static struct clk clk_esysclk = { | |||
320 | * UART baud-rate clock sourced from esysclk via a divisor | 294 | * UART baud-rate clock sourced from esysclk via a divisor |
321 | */ | 295 | */ |
322 | 296 | ||
323 | static unsigned long s3c2443_getrate_uart(struct clk *clk) | 297 | static struct clksrc_clk clk_uart = { |
324 | { | 298 | .clk = { |
325 | unsigned long parent_rate = clk_get_rate(clk->parent); | 299 | .name = "uartclk", |
326 | unsigned long div = __raw_readl(S3C2443_CLKDIV1); | 300 | .id = -1, |
327 | 301 | .parent = &clk_esysclk.clk, | |
328 | div &= S3C2443_CLKDIV1_UARTDIV_MASK; | ||
329 | div >>= S3C2443_CLKDIV1_UARTDIV_SHIFT; | ||
330 | |||
331 | return parent_rate / (div + 1); | ||
332 | } | ||
333 | |||
334 | |||
335 | static int s3c2443_setrate_uart(struct clk *clk, unsigned long rate) | ||
336 | { | ||
337 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
338 | unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1); | ||
339 | |||
340 | rate = s3c2443_roundrate_clksrc16(clk, rate); | ||
341 | rate = parent_rate / rate; | ||
342 | |||
343 | clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK; | ||
344 | clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT; | ||
345 | |||
346 | __raw_writel(clkdivn, S3C2443_CLKDIV1); | ||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static struct clk clk_uart = { | ||
351 | .name = "uartclk", | ||
352 | .id = -1, | ||
353 | .parent = &clk_esysclk, | ||
354 | .ops = &(struct clk_ops) { | ||
355 | .get_rate = s3c2443_getrate_uart, | ||
356 | .set_rate = s3c2443_setrate_uart, | ||
357 | .round_rate = s3c2443_roundrate_clksrc16, | ||
358 | }, | 302 | }, |
303 | .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 }, | ||
359 | }; | 304 | }; |
360 | 305 | ||
306 | |||
361 | /* hsspi | 307 | /* hsspi |
362 | * | 308 | * |
363 | * high-speed spi clock, sourced from esysclk | 309 | * high-speed spi clock, sourced from esysclk |
364 | */ | 310 | */ |
365 | 311 | ||
366 | static unsigned long s3c2443_getrate_hsspi(struct clk *clk) | 312 | static struct clksrc_clk clk_hsspi = { |
367 | { | 313 | .clk = { |
368 | unsigned long parent_rate = clk_get_rate(clk->parent); | 314 | .name = "hsspi", |
369 | unsigned long div = __raw_readl(S3C2443_CLKDIV1); | 315 | .id = -1, |
370 | 316 | .parent = &clk_esysclk.clk, | |
371 | div &= S3C2443_CLKDIV1_HSSPIDIV_MASK; | 317 | .ctrlbit = S3C2443_SCLKCON_HSSPICLK, |
372 | div >>= S3C2443_CLKDIV1_HSSPIDIV_SHIFT; | 318 | .enable = s3c2443_clkcon_enable_s, |
373 | |||
374 | return parent_rate / (div + 1); | ||
375 | } | ||
376 | |||
377 | |||
378 | static int s3c2443_setrate_hsspi(struct clk *clk, unsigned long rate) | ||
379 | { | ||
380 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
381 | unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1); | ||
382 | |||
383 | rate = s3c2443_roundrate_clksrc4(clk, rate); | ||
384 | rate = parent_rate / rate; | ||
385 | |||
386 | clkdivn &= ~S3C2443_CLKDIV1_HSSPIDIV_MASK; | ||
387 | clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSSPIDIV_SHIFT; | ||
388 | |||
389 | __raw_writel(clkdivn, S3C2443_CLKDIV1); | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static struct clk clk_hsspi = { | ||
394 | .name = "hsspi", | ||
395 | .id = -1, | ||
396 | .parent = &clk_esysclk, | ||
397 | .ctrlbit = S3C2443_SCLKCON_HSSPICLK, | ||
398 | .enable = s3c2443_clkcon_enable_s, | ||
399 | .ops = &(struct clk_ops) { | ||
400 | .get_rate = s3c2443_getrate_hsspi, | ||
401 | .set_rate = s3c2443_setrate_hsspi, | ||
402 | .round_rate = s3c2443_roundrate_clksrc4, | ||
403 | }, | 319 | }, |
320 | .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 }, | ||
404 | }; | 321 | }; |
405 | 322 | ||
406 | /* usbhost | 323 | /* usbhost |
@@ -408,43 +325,15 @@ static struct clk clk_hsspi = { | |||
408 | * usb host bus-clock, usually 48MHz to provide USB bus clock timing | 325 | * usb host bus-clock, usually 48MHz to provide USB bus clock timing |
409 | */ | 326 | */ |
410 | 327 | ||
411 | static unsigned long s3c2443_getrate_usbhost(struct clk *clk) | 328 | static struct clksrc_clk clk_usb_bus_host = { |
412 | { | 329 | .clk = { |
413 | unsigned long parent_rate = clk_get_rate(clk->parent); | 330 | .name = "usb-bus-host-parent", |
414 | unsigned long div = __raw_readl(S3C2443_CLKDIV1); | 331 | .id = -1, |
415 | 332 | .parent = &clk_esysclk.clk, | |
416 | div &= S3C2443_CLKDIV1_USBHOSTDIV_MASK; | 333 | .ctrlbit = S3C2443_SCLKCON_USBHOST, |
417 | div >>= S3C2443_CLKDIV1_USBHOSTDIV_SHIFT; | 334 | .enable = s3c2443_clkcon_enable_s, |
418 | |||
419 | return parent_rate / (div + 1); | ||
420 | } | ||
421 | |||
422 | static int s3c2443_setrate_usbhost(struct clk *clk, unsigned long rate) | ||
423 | { | ||
424 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
425 | unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1); | ||
426 | |||
427 | rate = s3c2443_roundrate_clksrc4(clk, rate); | ||
428 | rate = parent_rate / rate; | ||
429 | |||
430 | clkdivn &= ~S3C2443_CLKDIV1_USBHOSTDIV_MASK; | ||
431 | clkdivn |= (rate - 1) << S3C2443_CLKDIV1_USBHOSTDIV_SHIFT; | ||
432 | |||
433 | __raw_writel(clkdivn, S3C2443_CLKDIV1); | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static struct clk clk_usb_bus_host = { | ||
438 | .name = "usb-bus-host-parent", | ||
439 | .id = -1, | ||
440 | .parent = &clk_esysclk, | ||
441 | .ctrlbit = S3C2443_SCLKCON_USBHOST, | ||
442 | .enable = s3c2443_clkcon_enable_s, | ||
443 | .ops = &(struct clk_ops) { | ||
444 | .get_rate = s3c2443_getrate_usbhost, | ||
445 | .set_rate = s3c2443_setrate_usbhost, | ||
446 | .round_rate = s3c2443_roundrate_clksrc4, | ||
447 | }, | 335 | }, |
336 | .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 }, | ||
448 | }; | 337 | }; |
449 | 338 | ||
450 | /* clk_hsmcc_div | 339 | /* clk_hsmcc_div |
@@ -454,41 +343,13 @@ static struct clk clk_usb_bus_host = { | |||
454 | * be fed to the hsmmc block | 343 | * be fed to the hsmmc block |
455 | */ | 344 | */ |
456 | 345 | ||
457 | static unsigned long s3c2443_getrate_hsmmc_div(struct clk *clk) | 346 | static struct clksrc_clk clk_hsmmc_div = { |
458 | { | 347 | .clk = { |
459 | unsigned long parent_rate = clk_get_rate(clk->parent); | 348 | .name = "hsmmc-div", |
460 | unsigned long div = __raw_readl(S3C2443_CLKDIV1); | 349 | .id = -1, |
461 | 350 | .parent = &clk_esysclk.clk, | |
462 | div &= S3C2443_CLKDIV1_HSMMCDIV_MASK; | ||
463 | div >>= S3C2443_CLKDIV1_HSMMCDIV_SHIFT; | ||
464 | |||
465 | return parent_rate / (div + 1); | ||
466 | } | ||
467 | |||
468 | static int s3c2443_setrate_hsmmc_div(struct clk *clk, unsigned long rate) | ||
469 | { | ||
470 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
471 | unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1); | ||
472 | |||
473 | rate = s3c2443_roundrate_clksrc4(clk, rate); | ||
474 | rate = parent_rate / rate; | ||
475 | |||
476 | clkdivn &= ~S3C2443_CLKDIV1_HSMMCDIV_MASK; | ||
477 | clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSMMCDIV_SHIFT; | ||
478 | |||
479 | __raw_writel(clkdivn, S3C2443_CLKDIV1); | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | static struct clk clk_hsmmc_div = { | ||
484 | .name = "hsmmc-div", | ||
485 | .id = -1, | ||
486 | .parent = &clk_esysclk, | ||
487 | .ops = &(struct clk_ops) { | ||
488 | .get_rate = s3c2443_getrate_hsmmc_div, | ||
489 | .set_rate = s3c2443_setrate_hsmmc_div, | ||
490 | .round_rate = s3c2443_roundrate_clksrc4, | ||
491 | }, | 351 | }, |
352 | .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 }, | ||
492 | }; | 353 | }; |
493 | 354 | ||
494 | static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent) | 355 | static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent) |
@@ -521,7 +382,7 @@ static int s3c2443_enable_hsmmc(struct clk *clk, int enable) | |||
521 | static struct clk clk_hsmmc = { | 382 | static struct clk clk_hsmmc = { |
522 | .name = "hsmmc-if", | 383 | .name = "hsmmc-if", |
523 | .id = -1, | 384 | .id = -1, |
524 | .parent = &clk_hsmmc_div, | 385 | .parent = &clk_hsmmc_div.clk, |
525 | .enable = s3c2443_enable_hsmmc, | 386 | .enable = s3c2443_enable_hsmmc, |
526 | .ops = &(struct clk_ops) { | 387 | .ops = &(struct clk_ops) { |
527 | .set_parent = s3c2443_setparent_hsmmc, | 388 | .set_parent = s3c2443_setparent_hsmmc, |
@@ -530,79 +391,46 @@ static struct clk clk_hsmmc = { | |||
530 | 391 | ||
531 | /* i2s_eplldiv | 392 | /* i2s_eplldiv |
532 | * | 393 | * |
533 | * this clock is the output from the i2s divisor of esysclk | 394 | * This clock is the output from the I2S divisor of ESYSCLK, and is seperate |
395 | * from the mux that comes after it (cannot merge into one single clock) | ||
534 | */ | 396 | */ |
535 | 397 | ||
536 | static unsigned long s3c2443_getrate_i2s_eplldiv(struct clk *clk) | 398 | static struct clksrc_clk clk_i2s_eplldiv = { |
537 | { | 399 | .clk = { |
538 | unsigned long parent_rate = clk_get_rate(clk->parent); | 400 | .name = "i2s-eplldiv", |
539 | unsigned long div = __raw_readl(S3C2443_CLKDIV1); | 401 | .id = -1, |
540 | 402 | .parent = &clk_esysclk.clk, | |
541 | div &= S3C2443_CLKDIV1_I2SDIV_MASK; | ||
542 | div >>= S3C2443_CLKDIV1_I2SDIV_SHIFT; | ||
543 | |||
544 | return parent_rate / (div + 1); | ||
545 | } | ||
546 | |||
547 | static int s3c2443_setrate_i2s_eplldiv(struct clk *clk, unsigned long rate) | ||
548 | { | ||
549 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
550 | unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1); | ||
551 | |||
552 | rate = s3c2443_roundrate_clksrc16(clk, rate); | ||
553 | rate = parent_rate / rate; | ||
554 | |||
555 | clkdivn &= ~S3C2443_CLKDIV1_I2SDIV_MASK; | ||
556 | clkdivn |= (rate - 1) << S3C2443_CLKDIV1_I2SDIV_SHIFT; | ||
557 | |||
558 | __raw_writel(clkdivn, S3C2443_CLKDIV1); | ||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | static struct clk clk_i2s_eplldiv = { | ||
563 | .name = "i2s-eplldiv", | ||
564 | .id = -1, | ||
565 | .parent = &clk_esysclk, | ||
566 | .ops = &(struct clk_ops) { | ||
567 | .get_rate = s3c2443_getrate_i2s_eplldiv, | ||
568 | .set_rate = s3c2443_setrate_i2s_eplldiv, | ||
569 | .round_rate = s3c2443_roundrate_clksrc16, | ||
570 | }, | 403 | }, |
404 | .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, }, | ||
571 | }; | 405 | }; |
572 | 406 | ||
573 | /* i2s-ref | 407 | /* i2s-ref |
574 | * | 408 | * |
575 | * i2s bus reference clock, selectable from external, esysclk or epllref | 409 | * i2s bus reference clock, selectable from external, esysclk or epllref |
410 | * | ||
411 | * Note, this used to be two clocks, but was compressed into one. | ||
576 | */ | 412 | */ |
577 | 413 | ||
578 | static int s3c2443_setparent_i2s(struct clk *clk, struct clk *parent) | 414 | struct clk *clk_i2s_srclist[] = { |
579 | { | 415 | [0] = &clk_i2s_eplldiv.clk, |
580 | unsigned long clksrc = __raw_readl(S3C2443_CLKSRC); | 416 | [1] = &clk_i2s_ext, |
581 | 417 | [2] = &clk_epllref.clk, | |
582 | clksrc &= ~S3C2443_CLKSRC_I2S_MASK; | 418 | [3] = &clk_epllref.clk, |
583 | 419 | }; | |
584 | if (parent == &clk_epllref) | ||
585 | clksrc |= S3C2443_CLKSRC_I2S_EPLLREF; | ||
586 | else if (parent == &clk_i2s_ext) | ||
587 | clksrc |= S3C2443_CLKSRC_I2S_EXT; | ||
588 | else if (parent != &clk_i2s_eplldiv) | ||
589 | return -EINVAL; | ||
590 | |||
591 | clk->parent = parent; | ||
592 | __raw_writel(clksrc, S3C2443_CLKSRC); | ||
593 | 420 | ||
594 | return 0; | 421 | static struct clksrc_clk clk_i2s = { |
595 | } | 422 | .clk = { |
423 | .name = "i2s-if", | ||
424 | .id = -1, | ||
425 | .ctrlbit = S3C2443_SCLKCON_I2SCLK, | ||
426 | .enable = s3c2443_clkcon_enable_s, | ||
596 | 427 | ||
597 | static struct clk clk_i2s = { | ||
598 | .name = "i2s-if", | ||
599 | .id = -1, | ||
600 | .parent = &clk_i2s_eplldiv, | ||
601 | .ctrlbit = S3C2443_SCLKCON_I2SCLK, | ||
602 | .enable = s3c2443_clkcon_enable_s, | ||
603 | .ops = &(struct clk_ops) { | ||
604 | .set_parent = s3c2443_setparent_i2s, | ||
605 | }, | 428 | }, |
429 | .sources = &(struct clksrc_sources) { | ||
430 | .sources = clk_i2s_srclist, | ||
431 | .nr_sources = ARRAY_SIZE(clk_i2s_srclist), | ||
432 | }, | ||
433 | .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 }, | ||
606 | }; | 434 | }; |
607 | 435 | ||
608 | /* cam-if | 436 | /* cam-if |
@@ -610,43 +438,15 @@ static struct clk clk_i2s = { | |||
610 | * camera interface bus-clock, divided down from esysclk | 438 | * camera interface bus-clock, divided down from esysclk |
611 | */ | 439 | */ |
612 | 440 | ||
613 | static unsigned long s3c2443_getrate_cam(struct clk *clk) | 441 | static struct clksrc_clk clk_cam = { |
614 | { | 442 | .clk = { |
615 | unsigned long parent_rate = clk_get_rate(clk->parent); | 443 | .name = "camif-upll", /* same as 2440 name */ |
616 | unsigned long div = __raw_readl(S3C2443_CLKDIV1); | 444 | .id = -1, |
617 | 445 | .parent = &clk_esysclk.clk, | |
618 | div &= S3C2443_CLKDIV1_CAMDIV_MASK; | 446 | .ctrlbit = S3C2443_SCLKCON_CAMCLK, |
619 | div >>= S3C2443_CLKDIV1_CAMDIV_SHIFT; | 447 | .enable = s3c2443_clkcon_enable_s, |
620 | |||
621 | return parent_rate / (div + 1); | ||
622 | } | ||
623 | |||
624 | static int s3c2443_setrate_cam(struct clk *clk, unsigned long rate) | ||
625 | { | ||
626 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
627 | unsigned long clkdiv1 = __raw_readl(S3C2443_CLKDIV1); | ||
628 | |||
629 | rate = s3c2443_roundrate_clksrc16(clk, rate); | ||
630 | rate = parent_rate / rate; | ||
631 | |||
632 | clkdiv1 &= ~S3C2443_CLKDIV1_CAMDIV_MASK; | ||
633 | clkdiv1 |= (rate - 1) << S3C2443_CLKDIV1_CAMDIV_SHIFT; | ||
634 | |||
635 | __raw_writel(clkdiv1, S3C2443_CLKDIV1); | ||
636 | return 0; | ||
637 | } | ||
638 | |||
639 | static struct clk clk_cam = { | ||
640 | .name = "camif-upll", /* same as 2440 name */ | ||
641 | .id = -1, | ||
642 | .parent = &clk_esysclk, | ||
643 | .ctrlbit = S3C2443_SCLKCON_CAMCLK, | ||
644 | .enable = s3c2443_clkcon_enable_s, | ||
645 | .ops = &(struct clk_ops) { | ||
646 | .get_rate = s3c2443_getrate_cam, | ||
647 | .set_rate = s3c2443_setrate_cam, | ||
648 | .round_rate = s3c2443_roundrate_clksrc16, | ||
649 | }, | 448 | }, |
449 | .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 26 }, | ||
650 | }; | 450 | }; |
651 | 451 | ||
652 | /* display-if | 452 | /* display-if |
@@ -654,43 +454,15 @@ static struct clk clk_cam = { | |||
654 | * display interface clock, divided from esysclk | 454 | * display interface clock, divided from esysclk |
655 | */ | 455 | */ |
656 | 456 | ||
657 | static unsigned long s3c2443_getrate_display(struct clk *clk) | 457 | static struct clksrc_clk clk_display = { |
658 | { | 458 | .clk = { |
659 | unsigned long parent_rate = clk_get_rate(clk->parent); | 459 | .name = "display-if", |
660 | unsigned long div = __raw_readl(S3C2443_CLKDIV1); | 460 | .id = -1, |
661 | 461 | .parent = &clk_esysclk.clk, | |
662 | div &= S3C2443_CLKDIV1_DISPDIV_MASK; | 462 | .ctrlbit = S3C2443_SCLKCON_DISPCLK, |
663 | div >>= S3C2443_CLKDIV1_DISPDIV_SHIFT; | 463 | .enable = s3c2443_clkcon_enable_s, |
664 | |||
665 | return parent_rate / (div + 1); | ||
666 | } | ||
667 | |||
668 | static int s3c2443_setrate_display(struct clk *clk, unsigned long rate) | ||
669 | { | ||
670 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
671 | unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1); | ||
672 | |||
673 | rate = s3c2443_roundrate_clksrc256(clk, rate); | ||
674 | rate = parent_rate / rate; | ||
675 | |||
676 | clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK; | ||
677 | clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT; | ||
678 | |||
679 | __raw_writel(clkdivn, S3C2443_CLKDIV1); | ||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | static struct clk clk_display = { | ||
684 | .name = "display-if", | ||
685 | .id = -1, | ||
686 | .parent = &clk_esysclk, | ||
687 | .ctrlbit = S3C2443_SCLKCON_DISPCLK, | ||
688 | .enable = s3c2443_clkcon_enable_s, | ||
689 | .ops = &(struct clk_ops) { | ||
690 | .get_rate = s3c2443_getrate_display, | ||
691 | .set_rate = s3c2443_setrate_display, | ||
692 | .round_rate = s3c2443_roundrate_clksrc256, | ||
693 | }, | 464 | }, |
465 | .reg_div = { .reg = S3C2443_CLKDIV1, .size = 8, .shift = 16 }, | ||
694 | }; | 466 | }; |
695 | 467 | ||
696 | /* prediv | 468 | /* prediv |
@@ -712,7 +484,7 @@ static unsigned long s3c2443_prediv_getrate(struct clk *clk) | |||
712 | static struct clk clk_prediv = { | 484 | static struct clk clk_prediv = { |
713 | .name = "prediv", | 485 | .name = "prediv", |
714 | .id = -1, | 486 | .id = -1, |
715 | .parent = &clk_msysclk, | 487 | .parent = &clk_msysclk.clk, |
716 | .ops = &(struct clk_ops) { | 488 | .ops = &(struct clk_ops) { |
717 | .get_rate = s3c2443_prediv_getrate, | 489 | .get_rate = s3c2443_prediv_getrate, |
718 | }, | 490 | }, |
@@ -887,7 +659,7 @@ static struct clk init_clocks[] = { | |||
887 | }, { | 659 | }, { |
888 | .name = "usb-bus-host", | 660 | .name = "usb-bus-host", |
889 | .id = -1, | 661 | .id = -1, |
890 | .parent = &clk_usb_bus_host, | 662 | .parent = &clk_usb_bus_host.clk, |
891 | }, { | 663 | }, { |
892 | .name = "ac97", | 664 | .name = "ac97", |
893 | .id = -1, | 665 | .id = -1, |
@@ -898,103 +670,26 @@ static struct clk init_clocks[] = { | |||
898 | 670 | ||
899 | /* clocks to add where we need to check their parentage */ | 671 | /* clocks to add where we need to check their parentage */ |
900 | 672 | ||
901 | /* s3c2443_clk_initparents | 673 | static struct clksrc_clk __initdata *init_list[] = { |
902 | * | 674 | &clk_epllref, /* should be first */ |
903 | * Initialise the parents for the clocks that we get at start-time | 675 | &clk_esysclk, |
904 | */ | 676 | &clk_msysclk, |
905 | 677 | &clk_arm, | |
906 | static int __init clk_init_set_parent(struct clk *clk, struct clk *parent) | 678 | &clk_i2s_eplldiv, |
907 | { | 679 | &clk_i2s, |
908 | printk(KERN_DEBUG "clock %s: parent %s\n", clk->name, parent->name); | 680 | &clk_cam, |
909 | return clk_set_parent(clk, parent); | 681 | &clk_uart, |
910 | } | 682 | &clk_display, |
911 | 683 | &clk_hsmmc_div, | |
912 | static void __init s3c2443_clk_initparents(void) | 684 | &clk_usb_bus_host, |
913 | { | ||
914 | unsigned long clksrc = __raw_readl(S3C2443_CLKSRC); | ||
915 | struct clk *parent; | ||
916 | |||
917 | switch (clksrc & S3C2443_CLKSRC_EPLLREF_MASK) { | ||
918 | case S3C2443_CLKSRC_EPLLREF_EXTCLK: | ||
919 | parent = &clk_ext; | ||
920 | break; | ||
921 | |||
922 | case S3C2443_CLKSRC_EPLLREF_XTAL: | ||
923 | default: | ||
924 | parent = &clk_xtal; | ||
925 | break; | ||
926 | |||
927 | case S3C2443_CLKSRC_EPLLREF_MPLLREF: | ||
928 | case S3C2443_CLKSRC_EPLLREF_MPLLREF2: | ||
929 | parent = &clk_mpllref; | ||
930 | break; | ||
931 | } | ||
932 | |||
933 | clk_init_set_parent(&clk_epllref, parent); | ||
934 | |||
935 | switch (clksrc & S3C2443_CLKSRC_I2S_MASK) { | ||
936 | case S3C2443_CLKSRC_I2S_EXT: | ||
937 | parent = &clk_i2s_ext; | ||
938 | break; | ||
939 | |||
940 | case S3C2443_CLKSRC_I2S_EPLLDIV: | ||
941 | default: | ||
942 | parent = &clk_i2s_eplldiv; | ||
943 | break; | ||
944 | |||
945 | case S3C2443_CLKSRC_I2S_EPLLREF: | ||
946 | case S3C2443_CLKSRC_I2S_EPLLREF3: | ||
947 | parent = &clk_epllref; | ||
948 | } | ||
949 | |||
950 | clk_init_set_parent(&clk_i2s, &clk_epllref); | ||
951 | |||
952 | /* esysclk source */ | ||
953 | |||
954 | parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ? | ||
955 | &clk_epll : &clk_epllref; | ||
956 | |||
957 | clk_init_set_parent(&clk_esysclk, parent); | ||
958 | |||
959 | /* msysclk source */ | ||
960 | |||
961 | if (clksrc & S3C2443_CLKSRC_MSYSCLK_MPLL) { | ||
962 | parent = &clk_mpll; | ||
963 | } else { | ||
964 | parent = (clksrc & S3C2443_CLKSRC_EXTCLK_DIV) ? | ||
965 | &clk_mdivclk : &clk_mpllref; | ||
966 | } | ||
967 | |||
968 | clk_init_set_parent(&clk_msysclk, parent); | ||
969 | |||
970 | /* arm */ | ||
971 | |||
972 | if (__raw_readl(S3C2443_CLKDIV0) & S3C2443_CLKDIV0_DVS) | ||
973 | parent = &clk_h; | ||
974 | else | ||
975 | parent = &clk_armdiv; | ||
976 | |||
977 | clk_init_set_parent(&clk_arm, parent); | ||
978 | } | ||
979 | |||
980 | /* armdiv divisor table */ | ||
981 | |||
982 | static unsigned int armdiv[16] = { | ||
983 | [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1, | ||
984 | [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2, | ||
985 | [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3, | ||
986 | [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4, | ||
987 | [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6, | ||
988 | [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8, | ||
989 | [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12, | ||
990 | [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16, | ||
991 | }; | 685 | }; |
992 | 686 | ||
993 | static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0) | 687 | static void __init s3c2443_clk_initparents(void) |
994 | { | 688 | { |
995 | clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK; | 689 | int ptr; |
996 | 690 | ||
997 | return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]; | 691 | for (ptr = 0; ptr < ARRAY_SIZE(init_list); ptr++) |
692 | s3c_set_clksrc(init_list[ptr], true); | ||
998 | } | 693 | } |
999 | 694 | ||
1000 | static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0) | 695 | static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0) |
@@ -1006,15 +701,12 @@ static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0) | |||
1006 | 701 | ||
1007 | /* clocks to add straight away */ | 702 | /* clocks to add straight away */ |
1008 | 703 | ||
1009 | static struct clk *clks[] __initdata = { | 704 | static struct clksrc_clk *clksrcs[] __initdata = { |
1010 | &clk_ext, | ||
1011 | &clk_epll, | ||
1012 | &clk_usb_bus_host, | 705 | &clk_usb_bus_host, |
1013 | &clk_usb_bus, | ||
1014 | &clk_esysclk, | ||
1015 | &clk_epllref, | 706 | &clk_epllref, |
1016 | &clk_mpllref, | 707 | &clk_esysclk, |
1017 | &clk_msysclk, | 708 | &clk_msysclk, |
709 | &clk_arm, | ||
1018 | &clk_uart, | 710 | &clk_uart, |
1019 | &clk_display, | 711 | &clk_display, |
1020 | &clk_cam, | 712 | &clk_cam, |
@@ -1022,9 +714,15 @@ static struct clk *clks[] __initdata = { | |||
1022 | &clk_i2s, | 714 | &clk_i2s, |
1023 | &clk_hsspi, | 715 | &clk_hsspi, |
1024 | &clk_hsmmc_div, | 716 | &clk_hsmmc_div, |
717 | }; | ||
718 | |||
719 | static struct clk *clks[] __initdata = { | ||
720 | &clk_ext, | ||
721 | &clk_epll, | ||
722 | &clk_usb_bus, | ||
723 | &clk_mpllref, | ||
1025 | &clk_hsmmc, | 724 | &clk_hsmmc, |
1026 | &clk_armdiv, | 725 | &clk_armdiv, |
1027 | &clk_arm, | ||
1028 | &clk_prediv, | 726 | &clk_prediv, |
1029 | }; | 727 | }; |
1030 | 728 | ||
@@ -1044,7 +742,7 @@ void __init_or_cpufreq s3c2443_setup_clocks(void) | |||
1044 | clk_put(xtal_clk); | 742 | clk_put(xtal_clk); |
1045 | 743 | ||
1046 | pll = s3c2443_get_mpll(mpllcon, xtal); | 744 | pll = s3c2443_get_mpll(mpllcon, xtal); |
1047 | clk_msysclk.rate = pll; | 745 | clk_msysclk.clk.rate = pll; |
1048 | 746 | ||
1049 | fclk = pll / s3c2443_fclk_div(clkdiv0); | 747 | fclk = pll / s3c2443_fclk_div(clkdiv0); |
1050 | hclk = s3c2443_prediv_getrate(&clk_prediv); | 748 | hclk = s3c2443_prediv_getrate(&clk_prediv); |
@@ -1086,15 +784,18 @@ void __init s3c2443_init_clocks(int xtal) | |||
1086 | } | 784 | } |
1087 | } | 785 | } |
1088 | 786 | ||
787 | for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) | ||
788 | s3c_register_clksrc(clksrcs[ptr], 1); | ||
789 | |||
1089 | clk_epll.rate = s3c2443_get_epll(epllcon, xtal); | 790 | clk_epll.rate = s3c2443_get_epll(epllcon, xtal); |
1090 | clk_epll.parent = &clk_epllref; | 791 | clk_epll.parent = &clk_epllref.clk; |
1091 | clk_usb_bus.parent = &clk_usb_bus_host; | 792 | clk_usb_bus.parent = &clk_usb_bus_host.clk; |
1092 | 793 | ||
1093 | /* ensure usb bus clock is within correct rate of 48MHz */ | 794 | /* ensure usb bus clock is within correct rate of 48MHz */ |
1094 | 795 | ||
1095 | if (clk_get_rate(&clk_usb_bus_host) != (48 * 1000 * 1000)) { | 796 | if (clk_get_rate(&clk_usb_bus_host.clk) != (48 * 1000 * 1000)) { |
1096 | printk(KERN_INFO "Warning: USB host bus not at 48MHz\n"); | 797 | printk(KERN_INFO "Warning: USB host bus not at 48MHz\n"); |
1097 | clk_set_rate(&clk_usb_bus_host, 48*1000*1000); | 798 | clk_set_rate(&clk_usb_bus_host.clk, 48*1000*1000); |
1098 | } | 799 | } |
1099 | 800 | ||
1100 | printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", | 801 | printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", |