diff options
author | Tomasz Figa <tomasz.figa@gmail.com> | 2013-03-07 18:44:29 -0500 |
---|---|---|
committer | Tomasz Figa <tomasz.figa@gmail.com> | 2013-08-12 15:53:24 -0400 |
commit | 7c93c200f66c2b7f0e0de7ccc0d6718b151adc56 (patch) | |
tree | d6f1af8cf75c667b5f916fc5cd85c59038b94f41 /arch/arm/plat-samsung | |
parent | a2eed492f8192db692c3697b3465ea467b7abc10 (diff) |
ARM: SAMSUNG: Remove pwm-clock infrastructure
Since all the used PWM prescalers and dividers configuration has been
moved to appropriate drivers, the pwm-clock infrastructure is now
unused and so this patch removes it.
Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Mark Brown <broonie@linaro.org>
Tested-by: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arm/plat-samsung')
-rw-r--r-- | arch/arm/plat-samsung/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/clock.h | 4 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/pwm-clock.h | 81 | ||||
-rw-r--r-- | arch/arm/plat-samsung/pwm-clock.c | 474 |
4 files changed, 0 insertions, 560 deletions
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index ec4241ce3db3..498c7c23e9f4 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile | |||
@@ -14,7 +14,6 @@ obj- := | |||
14 | obj-y += init.o cpu.o | 14 | obj-y += init.o cpu.o |
15 | 15 | ||
16 | obj-$(CONFIG_SAMSUNG_CLOCK) += clock.o | 16 | obj-$(CONFIG_SAMSUNG_CLOCK) += clock.o |
17 | obj-$(CONFIG_SAMSUNG_CLOCK) += pwm-clock.o | ||
18 | 17 | ||
19 | obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o | 18 | obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o |
20 | obj-$(CONFIG_S5P_CLOCK) += s5p-clock.o | 19 | obj-$(CONFIG_S5P_CLOCK) += s5p-clock.o |
diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h index df45d6edc98d..63239f409807 100644 --- a/arch/arm/plat-samsung/include/plat/clock.h +++ b/arch/arm/plat-samsung/include/plat/clock.h | |||
@@ -145,10 +145,6 @@ extern int s3c2443_clkcon_enable_s(struct clk *clk, int enable); | |||
145 | 145 | ||
146 | extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); | 146 | extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); |
147 | 147 | ||
148 | /* Init for pwm clock code */ | ||
149 | |||
150 | extern void s3c_pwmclk_init(void); | ||
151 | |||
152 | /* Global watchdog clock used by arch_wtd_reset() callback */ | 148 | /* Global watchdog clock used by arch_wtd_reset() callback */ |
153 | 149 | ||
154 | extern struct clk *s3c2410_wdtclk; | 150 | extern struct clk *s3c2410_wdtclk; |
diff --git a/arch/arm/plat-samsung/include/plat/pwm-clock.h b/arch/arm/plat-samsung/include/plat/pwm-clock.h deleted file mode 100644 index bf6a60eb6237..000000000000 --- a/arch/arm/plat-samsung/include/plat/pwm-clock.h +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /* linux/arch/arm/plat-samsung/include/plat/pwm-clock.h | ||
2 | * | ||
3 | * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Copyright 2008 Openmoko, Inc. | ||
7 | * Copyright 2008 Simtec Electronics | ||
8 | * Ben Dooks <ben@simtec.co.uk> | ||
9 | * http://armlinux.simtec.co.uk/ | ||
10 | * | ||
11 | * SAMSUNG - pwm clock and timer support | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #ifndef __ASM_PLAT_PWM_CLOCK_H | ||
19 | #define __ASM_PLAT_PWM_CLOCK_H __FILE__ | ||
20 | |||
21 | /** | ||
22 | * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk | ||
23 | * @tcfg: The timer TCFG1 register bits shifted down to 0. | ||
24 | * | ||
25 | * Return true if the given configuration from TCFG1 is a TCLK instead | ||
26 | * any of the TDIV clocks. | ||
27 | */ | ||
28 | static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) | ||
29 | { | ||
30 | if (soc_is_s3c24xx()) | ||
31 | return tcfg == S3C2410_TCFG1_MUX_TCLK; | ||
32 | else if (soc_is_s3c64xx() || soc_is_s5pc100()) | ||
33 | return tcfg >= S3C64XX_TCFG1_MUX_TCLK; | ||
34 | else if (soc_is_s5p6440() || soc_is_s5p6450()) | ||
35 | return 0; | ||
36 | else | ||
37 | return tcfg == S3C64XX_TCFG1_MUX_TCLK; | ||
38 | } | ||
39 | |||
40 | /** | ||
41 | * tcfg_to_divisor() - convert tcfg1 setting to a divisor | ||
42 | * @tcfg1: The tcfg1 setting, shifted down. | ||
43 | * | ||
44 | * Get the divisor value for the given tcfg1 setting. We assume the | ||
45 | * caller has already checked to see if this is not a TCLK source. | ||
46 | */ | ||
47 | static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) | ||
48 | { | ||
49 | if (soc_is_s3c24xx()) | ||
50 | return 1 << (tcfg1 + 1); | ||
51 | else | ||
52 | return 1 << tcfg1; | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * pwm_tdiv_has_div1() - does the tdiv setting have a /1 | ||
57 | * | ||
58 | * Return true if we have a /1 in the tdiv setting. | ||
59 | */ | ||
60 | static inline unsigned int pwm_tdiv_has_div1(void) | ||
61 | { | ||
62 | if (soc_is_s3c24xx()) | ||
63 | return 0; | ||
64 | else | ||
65 | return 1; | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * pwm_tdiv_div_bits() - calculate TCFG1 divisor value. | ||
70 | * @div: The divisor to calculate the bit information for. | ||
71 | * | ||
72 | * Turn a divisor into the necessary bit field for TCFG1. | ||
73 | */ | ||
74 | static inline unsigned long pwm_tdiv_div_bits(unsigned int div) | ||
75 | { | ||
76 | if (soc_is_s3c24xx()) | ||
77 | return ilog2(div) - 1; | ||
78 | else | ||
79 | return ilog2(div); | ||
80 | } | ||
81 | #endif /* __ASM_PLAT_PWM_CLOCK_H */ | ||
diff --git a/arch/arm/plat-samsung/pwm-clock.c b/arch/arm/plat-samsung/pwm-clock.c deleted file mode 100644 index a35ff3bcffe4..000000000000 --- a/arch/arm/plat-samsung/pwm-clock.c +++ /dev/null | |||
@@ -1,474 +0,0 @@ | |||
1 | /* linux/arch/arm/plat-s3c24xx/pwm-clock.c | ||
2 | * | ||
3 | * Copyright (c) 2007 Simtec Electronics | ||
4 | * Copyright (c) 2007, 2008 Ben Dooks | ||
5 | * Ben Dooks <ben-linux@fluff.org> | ||
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. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/log2.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #include <mach/hardware.h> | ||
23 | #include <mach/map.h> | ||
24 | #include <asm/irq.h> | ||
25 | |||
26 | #include <plat/clock.h> | ||
27 | #include <plat/cpu.h> | ||
28 | |||
29 | #include <plat/regs-timer.h> | ||
30 | #include <plat/pwm-clock.h> | ||
31 | |||
32 | /* Each of the timers 0 through 5 go through the following | ||
33 | * clock tree, with the inputs depending on the timers. | ||
34 | * | ||
35 | * pclk ---- [ prescaler 0 ] -+---> timer 0 | ||
36 | * +---> timer 1 | ||
37 | * | ||
38 | * pclk ---- [ prescaler 1 ] -+---> timer 2 | ||
39 | * +---> timer 3 | ||
40 | * \---> timer 4 | ||
41 | * | ||
42 | * Which are fed into the timers as so: | ||
43 | * | ||
44 | * prescaled 0 ---- [ div 2,4,8,16 ] ---\ | ||
45 | * [mux] -> timer 0 | ||
46 | * tclk 0 ------------------------------/ | ||
47 | * | ||
48 | * prescaled 0 ---- [ div 2,4,8,16 ] ---\ | ||
49 | * [mux] -> timer 1 | ||
50 | * tclk 0 ------------------------------/ | ||
51 | * | ||
52 | * | ||
53 | * prescaled 1 ---- [ div 2,4,8,16 ] ---\ | ||
54 | * [mux] -> timer 2 | ||
55 | * tclk 1 ------------------------------/ | ||
56 | * | ||
57 | * prescaled 1 ---- [ div 2,4,8,16 ] ---\ | ||
58 | * [mux] -> timer 3 | ||
59 | * tclk 1 ------------------------------/ | ||
60 | * | ||
61 | * prescaled 1 ---- [ div 2,4,8, 16 ] --\ | ||
62 | * [mux] -> timer 4 | ||
63 | * tclk 1 ------------------------------/ | ||
64 | * | ||
65 | * Since the mux and the divider are tied together in the | ||
66 | * same register space, it is impossible to set the parent | ||
67 | * and the rate at the same time. To avoid this, we add an | ||
68 | * intermediate 'prescaled-and-divided' clock to select | ||
69 | * as the parent for the timer input clock called tdiv. | ||
70 | * | ||
71 | * prescaled clk --> pwm-tdiv ---\ | ||
72 | * [ mux ] --> timer X | ||
73 | * tclk -------------------------/ | ||
74 | */ | ||
75 | |||
76 | static struct clk clk_timer_scaler[]; | ||
77 | |||
78 | static unsigned long clk_pwm_scaler_get_rate(struct clk *clk) | ||
79 | { | ||
80 | unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0); | ||
81 | |||
82 | if (clk == &clk_timer_scaler[1]) { | ||
83 | tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK; | ||
84 | tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT; | ||
85 | } else { | ||
86 | tcfg0 &= S3C2410_TCFG_PRESCALER0_MASK; | ||
87 | } | ||
88 | |||
89 | return clk_get_rate(clk->parent) / (tcfg0 + 1); | ||
90 | } | ||
91 | |||
92 | static unsigned long clk_pwm_scaler_round_rate(struct clk *clk, | ||
93 | unsigned long rate) | ||
94 | { | ||
95 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
96 | unsigned long divisor = parent_rate / rate; | ||
97 | |||
98 | if (divisor > 256) | ||
99 | divisor = 256; | ||
100 | else if (divisor < 2) | ||
101 | divisor = 2; | ||
102 | |||
103 | return parent_rate / divisor; | ||
104 | } | ||
105 | |||
106 | static int clk_pwm_scaler_set_rate(struct clk *clk, unsigned long rate) | ||
107 | { | ||
108 | unsigned long round = clk_pwm_scaler_round_rate(clk, rate); | ||
109 | unsigned long tcfg0; | ||
110 | unsigned long divisor; | ||
111 | unsigned long flags; | ||
112 | |||
113 | divisor = clk_get_rate(clk->parent) / round; | ||
114 | divisor--; | ||
115 | |||
116 | local_irq_save(flags); | ||
117 | tcfg0 = __raw_readl(S3C2410_TCFG0); | ||
118 | |||
119 | if (clk == &clk_timer_scaler[1]) { | ||
120 | tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK; | ||
121 | tcfg0 |= divisor << S3C2410_TCFG_PRESCALER1_SHIFT; | ||
122 | } else { | ||
123 | tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK; | ||
124 | tcfg0 |= divisor; | ||
125 | } | ||
126 | |||
127 | __raw_writel(tcfg0, S3C2410_TCFG0); | ||
128 | local_irq_restore(flags); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static struct clk_ops clk_pwm_scaler_ops = { | ||
134 | .get_rate = clk_pwm_scaler_get_rate, | ||
135 | .set_rate = clk_pwm_scaler_set_rate, | ||
136 | .round_rate = clk_pwm_scaler_round_rate, | ||
137 | }; | ||
138 | |||
139 | static struct clk clk_timer_scaler[] = { | ||
140 | [0] = { | ||
141 | .name = "pwm-scaler0", | ||
142 | .id = -1, | ||
143 | .ops = &clk_pwm_scaler_ops, | ||
144 | }, | ||
145 | [1] = { | ||
146 | .name = "pwm-scaler1", | ||
147 | .id = -1, | ||
148 | .ops = &clk_pwm_scaler_ops, | ||
149 | }, | ||
150 | }; | ||
151 | |||
152 | static struct clk clk_timer_tclk[] = { | ||
153 | [0] = { | ||
154 | .name = "pwm-tclk0", | ||
155 | .id = -1, | ||
156 | }, | ||
157 | [1] = { | ||
158 | .name = "pwm-tclk1", | ||
159 | .id = -1, | ||
160 | }, | ||
161 | }; | ||
162 | |||
163 | struct pwm_tdiv_clk { | ||
164 | struct clk clk; | ||
165 | unsigned int divisor; | ||
166 | }; | ||
167 | |||
168 | static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk) | ||
169 | { | ||
170 | return container_of(clk, struct pwm_tdiv_clk, clk); | ||
171 | } | ||
172 | |||
173 | static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) | ||
174 | { | ||
175 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
176 | unsigned int divisor; | ||
177 | |||
178 | tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id); | ||
179 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | ||
180 | |||
181 | if (pwm_cfg_src_is_tclk(tcfg1)) | ||
182 | divisor = to_tdiv(clk)->divisor; | ||
183 | else | ||
184 | divisor = tcfg_to_divisor(tcfg1); | ||
185 | |||
186 | return clk_get_rate(clk->parent) / divisor; | ||
187 | } | ||
188 | |||
189 | static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk, | ||
190 | unsigned long rate) | ||
191 | { | ||
192 | unsigned long parent_rate; | ||
193 | unsigned long divisor; | ||
194 | |||
195 | parent_rate = clk_get_rate(clk->parent); | ||
196 | divisor = parent_rate / rate; | ||
197 | |||
198 | if (divisor <= 1 && pwm_tdiv_has_div1()) | ||
199 | divisor = 1; | ||
200 | else if (divisor <= 2) | ||
201 | divisor = 2; | ||
202 | else if (divisor <= 4) | ||
203 | divisor = 4; | ||
204 | else if (divisor <= 8) | ||
205 | divisor = 8; | ||
206 | else | ||
207 | divisor = 16; | ||
208 | |||
209 | return parent_rate / divisor; | ||
210 | } | ||
211 | |||
212 | static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk) | ||
213 | { | ||
214 | return pwm_tdiv_div_bits(divclk->divisor); | ||
215 | } | ||
216 | |||
217 | static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk) | ||
218 | { | ||
219 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
220 | unsigned long bits = clk_pwm_tdiv_bits(divclk); | ||
221 | unsigned long flags; | ||
222 | unsigned long shift = S3C2410_TCFG1_SHIFT(divclk->clk.id); | ||
223 | |||
224 | local_irq_save(flags); | ||
225 | |||
226 | tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
227 | tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift); | ||
228 | tcfg1 |= bits << shift; | ||
229 | __raw_writel(tcfg1, S3C2410_TCFG1); | ||
230 | |||
231 | local_irq_restore(flags); | ||
232 | } | ||
233 | |||
234 | static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate) | ||
235 | { | ||
236 | struct pwm_tdiv_clk *divclk = to_tdiv(clk); | ||
237 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
238 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
239 | unsigned long divisor; | ||
240 | |||
241 | tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id); | ||
242 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | ||
243 | |||
244 | rate = clk_round_rate(clk, rate); | ||
245 | divisor = parent_rate / rate; | ||
246 | |||
247 | if (divisor > 16) | ||
248 | return -EINVAL; | ||
249 | |||
250 | divclk->divisor = divisor; | ||
251 | |||
252 | /* Update the current MUX settings if we are currently | ||
253 | * selected as the clock source for this clock. */ | ||
254 | |||
255 | if (!pwm_cfg_src_is_tclk(tcfg1)) | ||
256 | clk_pwm_tdiv_update(divclk); | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static struct clk_ops clk_tdiv_ops = { | ||
262 | .get_rate = clk_pwm_tdiv_get_rate, | ||
263 | .set_rate = clk_pwm_tdiv_set_rate, | ||
264 | .round_rate = clk_pwm_tdiv_round_rate, | ||
265 | }; | ||
266 | |||
267 | static struct pwm_tdiv_clk clk_timer_tdiv[] = { | ||
268 | [0] = { | ||
269 | .clk = { | ||
270 | .name = "pwm-tdiv", | ||
271 | .devname = "s3c24xx-pwm.0", | ||
272 | .ops = &clk_tdiv_ops, | ||
273 | .parent = &clk_timer_scaler[0], | ||
274 | }, | ||
275 | }, | ||
276 | [1] = { | ||
277 | .clk = { | ||
278 | .name = "pwm-tdiv", | ||
279 | .devname = "s3c24xx-pwm.1", | ||
280 | .ops = &clk_tdiv_ops, | ||
281 | .parent = &clk_timer_scaler[0], | ||
282 | } | ||
283 | }, | ||
284 | [2] = { | ||
285 | .clk = { | ||
286 | .name = "pwm-tdiv", | ||
287 | .devname = "s3c24xx-pwm.2", | ||
288 | .ops = &clk_tdiv_ops, | ||
289 | .parent = &clk_timer_scaler[1], | ||
290 | }, | ||
291 | }, | ||
292 | [3] = { | ||
293 | .clk = { | ||
294 | .name = "pwm-tdiv", | ||
295 | .devname = "s3c24xx-pwm.3", | ||
296 | .ops = &clk_tdiv_ops, | ||
297 | .parent = &clk_timer_scaler[1], | ||
298 | }, | ||
299 | }, | ||
300 | [4] = { | ||
301 | .clk = { | ||
302 | .name = "pwm-tdiv", | ||
303 | .devname = "s3c24xx-pwm.4", | ||
304 | .ops = &clk_tdiv_ops, | ||
305 | .parent = &clk_timer_scaler[1], | ||
306 | }, | ||
307 | }, | ||
308 | }; | ||
309 | |||
310 | static int __init clk_pwm_tdiv_register(unsigned int id) | ||
311 | { | ||
312 | struct pwm_tdiv_clk *divclk = &clk_timer_tdiv[id]; | ||
313 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
314 | |||
315 | tcfg1 >>= S3C2410_TCFG1_SHIFT(id); | ||
316 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | ||
317 | |||
318 | divclk->clk.id = id; | ||
319 | divclk->divisor = tcfg_to_divisor(tcfg1); | ||
320 | |||
321 | return s3c24xx_register_clock(&divclk->clk); | ||
322 | } | ||
323 | |||
324 | static inline struct clk *s3c24xx_pwmclk_tclk(unsigned int id) | ||
325 | { | ||
326 | return (id >= 2) ? &clk_timer_tclk[1] : &clk_timer_tclk[0]; | ||
327 | } | ||
328 | |||
329 | static inline struct clk *s3c24xx_pwmclk_tdiv(unsigned int id) | ||
330 | { | ||
331 | return &clk_timer_tdiv[id].clk; | ||
332 | } | ||
333 | |||
334 | static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent) | ||
335 | { | ||
336 | unsigned int id = clk->id; | ||
337 | unsigned long tcfg1; | ||
338 | unsigned long flags; | ||
339 | unsigned long bits; | ||
340 | unsigned long shift = S3C2410_TCFG1_SHIFT(id); | ||
341 | |||
342 | unsigned long mux_tclk; | ||
343 | |||
344 | if (soc_is_s3c24xx()) | ||
345 | mux_tclk = S3C2410_TCFG1_MUX_TCLK; | ||
346 | else if (soc_is_s5p6440() || soc_is_s5p6450()) | ||
347 | mux_tclk = 0; | ||
348 | else | ||
349 | mux_tclk = S3C64XX_TCFG1_MUX_TCLK; | ||
350 | |||
351 | if (parent == s3c24xx_pwmclk_tclk(id)) | ||
352 | bits = mux_tclk << shift; | ||
353 | else if (parent == s3c24xx_pwmclk_tdiv(id)) | ||
354 | bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift; | ||
355 | else | ||
356 | return -EINVAL; | ||
357 | |||
358 | clk->parent = parent; | ||
359 | |||
360 | local_irq_save(flags); | ||
361 | |||
362 | tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
363 | tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift); | ||
364 | __raw_writel(tcfg1 | bits, S3C2410_TCFG1); | ||
365 | |||
366 | local_irq_restore(flags); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static struct clk_ops clk_tin_ops = { | ||
372 | .set_parent = clk_pwm_tin_set_parent, | ||
373 | }; | ||
374 | |||
375 | static struct clk clk_tin[] = { | ||
376 | [0] = { | ||
377 | .name = "pwm-tin", | ||
378 | .devname = "s3c24xx-pwm.0", | ||
379 | .id = 0, | ||
380 | .ops = &clk_tin_ops, | ||
381 | }, | ||
382 | [1] = { | ||
383 | .name = "pwm-tin", | ||
384 | .devname = "s3c24xx-pwm.1", | ||
385 | .id = 1, | ||
386 | .ops = &clk_tin_ops, | ||
387 | }, | ||
388 | [2] = { | ||
389 | .name = "pwm-tin", | ||
390 | .devname = "s3c24xx-pwm.2", | ||
391 | .id = 2, | ||
392 | .ops = &clk_tin_ops, | ||
393 | }, | ||
394 | [3] = { | ||
395 | .name = "pwm-tin", | ||
396 | .devname = "s3c24xx-pwm.3", | ||
397 | .id = 3, | ||
398 | .ops = &clk_tin_ops, | ||
399 | }, | ||
400 | [4] = { | ||
401 | .name = "pwm-tin", | ||
402 | .devname = "s3c24xx-pwm.4", | ||
403 | .id = 4, | ||
404 | .ops = &clk_tin_ops, | ||
405 | }, | ||
406 | }; | ||
407 | |||
408 | static __init int clk_pwm_tin_register(struct clk *pwm) | ||
409 | { | ||
410 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
411 | unsigned int id = pwm->id; | ||
412 | |||
413 | struct clk *parent; | ||
414 | int ret; | ||
415 | |||
416 | ret = s3c24xx_register_clock(pwm); | ||
417 | if (ret < 0) | ||
418 | return ret; | ||
419 | |||
420 | tcfg1 >>= S3C2410_TCFG1_SHIFT(id); | ||
421 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | ||
422 | |||
423 | if (pwm_cfg_src_is_tclk(tcfg1)) | ||
424 | parent = s3c24xx_pwmclk_tclk(id); | ||
425 | else | ||
426 | parent = s3c24xx_pwmclk_tdiv(id); | ||
427 | |||
428 | return clk_set_parent(pwm, parent); | ||
429 | } | ||
430 | |||
431 | /** | ||
432 | * s3c_pwmclk_init() - initialise pwm clocks | ||
433 | * | ||
434 | * Initialise and register the clocks which provide the inputs for the | ||
435 | * pwm timer blocks. | ||
436 | * | ||
437 | * Note, this call is required by the time core, so must be called after | ||
438 | * the base clocks are added and before any of the initcalls are run. | ||
439 | */ | ||
440 | __init void s3c_pwmclk_init(void) | ||
441 | { | ||
442 | struct clk *clk_timers; | ||
443 | unsigned int clk; | ||
444 | int ret; | ||
445 | |||
446 | clk_timers = clk_get(NULL, "timers"); | ||
447 | if (IS_ERR(clk_timers)) { | ||
448 | printk(KERN_ERR "%s: no parent clock\n", __func__); | ||
449 | return; | ||
450 | } | ||
451 | |||
452 | for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) | ||
453 | clk_timer_scaler[clk].parent = clk_timers; | ||
454 | |||
455 | s3c_register_clocks(clk_timer_scaler, ARRAY_SIZE(clk_timer_scaler)); | ||
456 | s3c_register_clocks(clk_timer_tclk, ARRAY_SIZE(clk_timer_tclk)); | ||
457 | |||
458 | for (clk = 0; clk < ARRAY_SIZE(clk_timer_tdiv); clk++) { | ||
459 | ret = clk_pwm_tdiv_register(clk); | ||
460 | |||
461 | if (ret < 0) { | ||
462 | printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk); | ||
463 | return; | ||
464 | } | ||
465 | } | ||
466 | |||
467 | for (clk = 0; clk < ARRAY_SIZE(clk_tin); clk++) { | ||
468 | ret = clk_pwm_tin_register(&clk_tin[clk]); | ||
469 | if (ret < 0) { | ||
470 | printk(KERN_ERR "error adding pwm%d tin clock\n", clk); | ||
471 | return; | ||
472 | } | ||
473 | } | ||
474 | } | ||