diff options
author | Kevin Wells <wellsk40@gmail.com> | 2010-02-26 18:53:40 -0500 |
---|---|---|
committer | Kevin Wells <wellsk40@gmail.com> | 2010-07-27 06:08:09 -0400 |
commit | b9cc4bf6656d5f349c283e6ac267b852b7a2e42e (patch) | |
tree | 22d6dfdbbece219091183f441b8cd86e43b73866 /arch/arm/mach-lpc32xx | |
parent | 343d3537917bd74648fa2a360b42f64ad5ec551d (diff) |
ARM: LPC32XX: Clock driver
Clock driver for the LPC32XX architecture
Signed-off-by: Kevin Wells <wellsk40@gmail.com>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Diffstat (limited to 'arch/arm/mach-lpc32xx')
-rw-r--r-- | arch/arm/mach-lpc32xx/clock.c | 1137 | ||||
-rw-r--r-- | arch/arm/mach-lpc32xx/clock.h | 38 |
2 files changed, 1175 insertions, 0 deletions
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c new file mode 100644 index 000000000000..32d63796430a --- /dev/null +++ b/arch/arm/mach-lpc32xx/clock.c | |||
@@ -0,0 +1,1137 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-lpc32xx/clock.c | ||
3 | * | ||
4 | * Author: Kevin Wells <kevin.wells@nxp.com> | ||
5 | * | ||
6 | * Copyright (C) 2010 NXP Semiconductors | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * LPC32xx clock management driver overview | ||
21 | * | ||
22 | * The LPC32XX contains a number of high level system clocks that can be | ||
23 | * generated from different sources. These system clocks are used to | ||
24 | * generate the CPU and bus rates and the individual peripheral clocks in | ||
25 | * the system. When Linux is started by the boot loader, the system | ||
26 | * clocks are already running. Stopping a system clock during normal | ||
27 | * Linux operation should never be attempted, as peripherals that require | ||
28 | * those clocks will quit working (ie, DRAM). | ||
29 | * | ||
30 | * The LPC32xx high level clock tree looks as follows. Clocks marked with | ||
31 | * an asterisk are always on and cannot be disabled. Clocks marked with | ||
32 | * an ampersand can only be disabled in CPU suspend mode. Clocks marked | ||
33 | * with a caret are always on if it is the selected clock for the SYSCLK | ||
34 | * source. The clock that isn't used for SYSCLK can be enabled and | ||
35 | * disabled normally. | ||
36 | * 32KHz oscillator* | ||
37 | * / | \ | ||
38 | * RTC* PLL397^ TOUCH | ||
39 | * / | ||
40 | * Main oscillator^ / | ||
41 | * | \ / | ||
42 | * | SYSCLK& | ||
43 | * | \ | ||
44 | * | \ | ||
45 | * USB_PLL HCLK_PLL& | ||
46 | * | | | | ||
47 | * USB host/device PCLK& | | ||
48 | * | | | ||
49 | * Peripherals | ||
50 | * | ||
51 | * The CPU and chip bus rates are derived from the HCLK PLL, which can | ||
52 | * generate various clock rates up to 266MHz and beyond. The internal bus | ||
53 | * rates (PCLK and HCLK) are generated from dividers based on the HCLK | ||
54 | * PLL rate. HCLK can be a ratio of 1:1, 1:2, or 1:4 or HCLK PLL rate, | ||
55 | * while PCLK can be 1:1 to 1:32 of HCLK PLL rate. Most peripherals high | ||
56 | * level clocks are based on either HCLK or PCLK, but have their own | ||
57 | * dividers as part of the IP itself. Because of this, the system clock | ||
58 | * rates should not be changed. | ||
59 | * | ||
60 | * The HCLK PLL is clocked from SYSCLK, which can be derived from the | ||
61 | * main oscillator or PLL397. PLL397 generates a rate that is 397 times | ||
62 | * the 32KHz oscillator rate. The main oscillator runs at the selected | ||
63 | * oscillator/crystal rate on the mosc_in pin of the LPC32xx. This rate | ||
64 | * is normally 13MHz, but depends on the selection of external crystals | ||
65 | * or oscillators. If USB operation is required, the main oscillator must | ||
66 | * be used in the system. | ||
67 | * | ||
68 | * Switching SYSCLK between sources during normal Linux operation is not | ||
69 | * supported. SYSCLK is preset in the bootloader. Because of the | ||
70 | * complexities of clock management during clock frequency changes, | ||
71 | * there are some limitations to the clock driver explained below: | ||
72 | * - The PLL397 and main oscillator can be enabled and disabled by the | ||
73 | * clk_enable() and clk_disable() functions unless SYSCLK is based | ||
74 | * on that clock. This allows the other oscillator that isn't driving | ||
75 | * the HCLK PLL to be used as another system clock that can be routed | ||
76 | * to an external pin. | ||
77 | * - The muxed SYSCLK input and HCLK_PLL rate cannot be changed with | ||
78 | * this driver. | ||
79 | * - HCLK and PCLK rates cannot be changed as part of this driver. | ||
80 | * - Most peripherals have their own dividers are part of the peripheral | ||
81 | * block. Changing SYSCLK, HCLK PLL, HCLK, or PCLK sources or rates | ||
82 | * will also impact the individual peripheral rates. | ||
83 | */ | ||
84 | |||
85 | #include <linux/kernel.h> | ||
86 | #include <linux/list.h> | ||
87 | #include <linux/errno.h> | ||
88 | #include <linux/device.h> | ||
89 | #include <linux/err.h> | ||
90 | #include <linux/clk.h> | ||
91 | #include <linux/amba/bus.h> | ||
92 | #include <linux/amba/clcd.h> | ||
93 | |||
94 | #include <mach/hardware.h> | ||
95 | #include <asm/clkdev.h> | ||
96 | #include <mach/clkdev.h> | ||
97 | #include <mach/platform.h> | ||
98 | #include "clock.h" | ||
99 | #include "common.h" | ||
100 | |||
101 | static struct clk clk_armpll; | ||
102 | static struct clk clk_usbpll; | ||
103 | static DEFINE_MUTEX(clkm_lock); | ||
104 | |||
105 | /* | ||
106 | * Post divider values for PLLs based on selected register value | ||
107 | */ | ||
108 | static const u32 pll_postdivs[4] = {1, 2, 4, 8}; | ||
109 | |||
110 | static unsigned long local_return_parent_rate(struct clk *clk) | ||
111 | { | ||
112 | /* | ||
113 | * If a clock has a rate of 0, then it inherits it's parent | ||
114 | * clock rate | ||
115 | */ | ||
116 | while (clk->rate == 0) | ||
117 | clk = clk->parent; | ||
118 | |||
119 | return clk->rate; | ||
120 | } | ||
121 | |||
122 | /* 32KHz clock has a fixed rate and is not stoppable */ | ||
123 | static struct clk osc_32KHz = { | ||
124 | .rate = LPC32XX_CLOCK_OSC_FREQ, | ||
125 | .get_rate = local_return_parent_rate, | ||
126 | }; | ||
127 | |||
128 | static int local_pll397_enable(struct clk *clk, int enable) | ||
129 | { | ||
130 | u32 reg; | ||
131 | unsigned long timeout = 1 + msecs_to_jiffies(10); | ||
132 | |||
133 | reg = __raw_readl(LPC32XX_CLKPWR_PLL397_CTRL); | ||
134 | |||
135 | if (enable == 0) { | ||
136 | reg |= LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS; | ||
137 | __raw_writel(reg, LPC32XX_CLKPWR_PLL397_CTRL); | ||
138 | } else { | ||
139 | /* Enable PLL397 */ | ||
140 | reg &= ~LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS; | ||
141 | __raw_writel(reg, LPC32XX_CLKPWR_PLL397_CTRL); | ||
142 | |||
143 | /* Wait for PLL397 lock */ | ||
144 | while (((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) & | ||
145 | LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0) && | ||
146 | (timeout > jiffies)) | ||
147 | cpu_relax(); | ||
148 | |||
149 | if ((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) & | ||
150 | LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0) | ||
151 | return -ENODEV; | ||
152 | } | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static int local_oscmain_enable(struct clk *clk, int enable) | ||
158 | { | ||
159 | u32 reg; | ||
160 | unsigned long timeout = 1 + msecs_to_jiffies(10); | ||
161 | |||
162 | reg = __raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL); | ||
163 | |||
164 | if (enable == 0) { | ||
165 | reg |= LPC32XX_CLKPWR_MOSC_DISABLE; | ||
166 | __raw_writel(reg, LPC32XX_CLKPWR_MAIN_OSC_CTRL); | ||
167 | } else { | ||
168 | /* Enable main oscillator */ | ||
169 | reg &= ~LPC32XX_CLKPWR_MOSC_DISABLE; | ||
170 | __raw_writel(reg, LPC32XX_CLKPWR_MAIN_OSC_CTRL); | ||
171 | |||
172 | /* Wait for main oscillator to start */ | ||
173 | while (((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) & | ||
174 | LPC32XX_CLKPWR_MOSC_DISABLE) != 0) && | ||
175 | (timeout > jiffies)) | ||
176 | cpu_relax(); | ||
177 | |||
178 | if ((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) & | ||
179 | LPC32XX_CLKPWR_MOSC_DISABLE) != 0) | ||
180 | return -ENODEV; | ||
181 | } | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static struct clk osc_pll397 = { | ||
187 | .parent = &osc_32KHz, | ||
188 | .enable = local_pll397_enable, | ||
189 | .rate = LPC32XX_CLOCK_OSC_FREQ * 397, | ||
190 | .get_rate = local_return_parent_rate, | ||
191 | }; | ||
192 | |||
193 | static struct clk osc_main = { | ||
194 | .enable = local_oscmain_enable, | ||
195 | .rate = LPC32XX_MAIN_OSC_FREQ, | ||
196 | .get_rate = local_return_parent_rate, | ||
197 | }; | ||
198 | |||
199 | static struct clk clk_sys; | ||
200 | |||
201 | /* | ||
202 | * Convert a PLL register value to a PLL output frequency | ||
203 | */ | ||
204 | u32 clk_get_pllrate_from_reg(u32 inputclk, u32 regval) | ||
205 | { | ||
206 | struct clk_pll_setup pllcfg; | ||
207 | |||
208 | pllcfg.cco_bypass_b15 = 0; | ||
209 | pllcfg.direct_output_b14 = 0; | ||
210 | pllcfg.fdbk_div_ctrl_b13 = 0; | ||
211 | if ((regval & LPC32XX_CLKPWR_HCLKPLL_CCO_BYPASS) != 0) | ||
212 | pllcfg.cco_bypass_b15 = 1; | ||
213 | if ((regval & LPC32XX_CLKPWR_HCLKPLL_POSTDIV_BYPASS) != 0) | ||
214 | pllcfg.direct_output_b14 = 1; | ||
215 | if ((regval & LPC32XX_CLKPWR_HCLKPLL_FDBK_SEL_FCLK) != 0) | ||
216 | pllcfg.fdbk_div_ctrl_b13 = 1; | ||
217 | pllcfg.pll_m = 1 + ((regval >> 1) & 0xFF); | ||
218 | pllcfg.pll_n = 1 + ((regval >> 9) & 0x3); | ||
219 | pllcfg.pll_p = pll_postdivs[((regval >> 11) & 0x3)]; | ||
220 | |||
221 | return clk_check_pll_setup(inputclk, &pllcfg); | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * Setup the HCLK PLL with a PLL structure | ||
226 | */ | ||
227 | static u32 local_clk_pll_setup(struct clk_pll_setup *PllSetup) | ||
228 | { | ||
229 | u32 tv, tmp = 0; | ||
230 | |||
231 | if (PllSetup->analog_on != 0) | ||
232 | tmp |= LPC32XX_CLKPWR_HCLKPLL_POWER_UP; | ||
233 | if (PllSetup->cco_bypass_b15 != 0) | ||
234 | tmp |= LPC32XX_CLKPWR_HCLKPLL_CCO_BYPASS; | ||
235 | if (PllSetup->direct_output_b14 != 0) | ||
236 | tmp |= LPC32XX_CLKPWR_HCLKPLL_POSTDIV_BYPASS; | ||
237 | if (PllSetup->fdbk_div_ctrl_b13 != 0) | ||
238 | tmp |= LPC32XX_CLKPWR_HCLKPLL_FDBK_SEL_FCLK; | ||
239 | |||
240 | tv = ffs(PllSetup->pll_p) - 1; | ||
241 | if ((!is_power_of_2(PllSetup->pll_p)) || (tv > 3)) | ||
242 | return 0; | ||
243 | |||
244 | tmp |= LPC32XX_CLKPWR_HCLKPLL_POSTDIV_2POW(tv); | ||
245 | tmp |= LPC32XX_CLKPWR_HCLKPLL_PREDIV_PLUS1(PllSetup->pll_n - 1); | ||
246 | tmp |= LPC32XX_CLKPWR_HCLKPLL_PLLM(PllSetup->pll_m - 1); | ||
247 | |||
248 | return tmp; | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * Update the ARM core PLL frequency rate variable from the actual PLL setting | ||
253 | */ | ||
254 | static void local_update_armpll_rate(void) | ||
255 | { | ||
256 | u32 clkin, pllreg; | ||
257 | |||
258 | clkin = clk_armpll.parent->rate; | ||
259 | pllreg = __raw_readl(LPC32XX_CLKPWR_HCLKPLL_CTRL) & 0x1FFFF; | ||
260 | |||
261 | clk_armpll.rate = clk_get_pllrate_from_reg(clkin, pllreg); | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * Find a PLL configuration for the selected input frequency | ||
266 | */ | ||
267 | static u32 local_clk_find_pll_cfg(u32 pllin_freq, u32 target_freq, | ||
268 | struct clk_pll_setup *pllsetup) | ||
269 | { | ||
270 | u32 ifreq, freqtol, m, n, p, fclkout; | ||
271 | |||
272 | /* Determine frequency tolerance limits */ | ||
273 | freqtol = target_freq / 250; | ||
274 | ifreq = pllin_freq; | ||
275 | |||
276 | /* Is direct bypass mode possible? */ | ||
277 | if (abs(pllin_freq - target_freq) <= freqtol) { | ||
278 | pllsetup->analog_on = 0; | ||
279 | pllsetup->cco_bypass_b15 = 1; | ||
280 | pllsetup->direct_output_b14 = 1; | ||
281 | pllsetup->fdbk_div_ctrl_b13 = 1; | ||
282 | pllsetup->pll_p = pll_postdivs[0]; | ||
283 | pllsetup->pll_n = 1; | ||
284 | pllsetup->pll_m = 1; | ||
285 | return clk_check_pll_setup(ifreq, pllsetup); | ||
286 | } else if (target_freq <= ifreq) { | ||
287 | pllsetup->analog_on = 0; | ||
288 | pllsetup->cco_bypass_b15 = 1; | ||
289 | pllsetup->direct_output_b14 = 0; | ||
290 | pllsetup->fdbk_div_ctrl_b13 = 1; | ||
291 | pllsetup->pll_n = 1; | ||
292 | pllsetup->pll_m = 1; | ||
293 | for (p = 0; p <= 3; p++) { | ||
294 | pllsetup->pll_p = pll_postdivs[p]; | ||
295 | fclkout = clk_check_pll_setup(ifreq, pllsetup); | ||
296 | if (abs(target_freq - fclkout) <= freqtol) | ||
297 | return fclkout; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | /* Is direct mode possible? */ | ||
302 | pllsetup->analog_on = 1; | ||
303 | pllsetup->cco_bypass_b15 = 0; | ||
304 | pllsetup->direct_output_b14 = 1; | ||
305 | pllsetup->fdbk_div_ctrl_b13 = 0; | ||
306 | pllsetup->pll_p = pll_postdivs[0]; | ||
307 | for (m = 1; m <= 256; m++) { | ||
308 | for (n = 1; n <= 4; n++) { | ||
309 | /* Compute output frequency for this value */ | ||
310 | pllsetup->pll_n = n; | ||
311 | pllsetup->pll_m = m; | ||
312 | fclkout = clk_check_pll_setup(ifreq, | ||
313 | pllsetup); | ||
314 | if (abs(target_freq - fclkout) <= | ||
315 | freqtol) | ||
316 | return fclkout; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | /* Is integer mode possible? */ | ||
321 | pllsetup->analog_on = 1; | ||
322 | pllsetup->cco_bypass_b15 = 0; | ||
323 | pllsetup->direct_output_b14 = 0; | ||
324 | pllsetup->fdbk_div_ctrl_b13 = 1; | ||
325 | for (m = 1; m <= 256; m++) { | ||
326 | for (n = 1; n <= 4; n++) { | ||
327 | for (p = 0; p < 4; p++) { | ||
328 | /* Compute output frequency */ | ||
329 | pllsetup->pll_p = pll_postdivs[p]; | ||
330 | pllsetup->pll_n = n; | ||
331 | pllsetup->pll_m = m; | ||
332 | fclkout = clk_check_pll_setup( | ||
333 | ifreq, pllsetup); | ||
334 | if (abs(target_freq - fclkout) <= freqtol) | ||
335 | return fclkout; | ||
336 | } | ||
337 | } | ||
338 | } | ||
339 | |||
340 | /* Try non-integer mode */ | ||
341 | pllsetup->analog_on = 1; | ||
342 | pllsetup->cco_bypass_b15 = 0; | ||
343 | pllsetup->direct_output_b14 = 0; | ||
344 | pllsetup->fdbk_div_ctrl_b13 = 0; | ||
345 | for (m = 1; m <= 256; m++) { | ||
346 | for (n = 1; n <= 4; n++) { | ||
347 | for (p = 0; p < 4; p++) { | ||
348 | /* Compute output frequency */ | ||
349 | pllsetup->pll_p = pll_postdivs[p]; | ||
350 | pllsetup->pll_n = n; | ||
351 | pllsetup->pll_m = m; | ||
352 | fclkout = clk_check_pll_setup( | ||
353 | ifreq, pllsetup); | ||
354 | if (abs(target_freq - fclkout) <= freqtol) | ||
355 | return fclkout; | ||
356 | } | ||
357 | } | ||
358 | } | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static struct clk clk_armpll = { | ||
364 | .parent = &clk_sys, | ||
365 | .get_rate = local_return_parent_rate, | ||
366 | }; | ||
367 | |||
368 | /* | ||
369 | * Setup the USB PLL with a PLL structure | ||
370 | */ | ||
371 | static u32 local_clk_usbpll_setup(struct clk_pll_setup *pHCLKPllSetup) | ||
372 | { | ||
373 | u32 reg, tmp = local_clk_pll_setup(pHCLKPllSetup); | ||
374 | |||
375 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL) & ~0x1FFFF; | ||
376 | reg |= tmp; | ||
377 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | ||
378 | |||
379 | return clk_check_pll_setup(clk_usbpll.parent->rate, | ||
380 | pHCLKPllSetup); | ||
381 | } | ||
382 | |||
383 | static int local_usbpll_enable(struct clk *clk, int enable) | ||
384 | { | ||
385 | u32 reg; | ||
386 | int ret = -ENODEV; | ||
387 | unsigned long timeout = 1 + msecs_to_jiffies(10); | ||
388 | |||
389 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); | ||
390 | |||
391 | if (enable == 0) { | ||
392 | reg &= ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN1 | | ||
393 | LPC32XX_CLKPWR_USBCTRL_CLK_EN2); | ||
394 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | ||
395 | } else if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP) { | ||
396 | reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1; | ||
397 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | ||
398 | |||
399 | /* Wait for PLL lock */ | ||
400 | while ((timeout > jiffies) & (ret == -ENODEV)) { | ||
401 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); | ||
402 | if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS) | ||
403 | ret = 0; | ||
404 | } | ||
405 | |||
406 | if (ret == 0) { | ||
407 | reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2; | ||
408 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | ||
409 | } | ||
410 | } | ||
411 | |||
412 | return ret; | ||
413 | } | ||
414 | |||
415 | static unsigned long local_usbpll_round_rate(struct clk *clk, | ||
416 | unsigned long rate) | ||
417 | { | ||
418 | u32 clkin, usbdiv; | ||
419 | struct clk_pll_setup pllsetup; | ||
420 | |||
421 | /* | ||
422 | * Unlike other clocks, this clock has a KHz input rate, so bump | ||
423 | * it up to work with the PLL function | ||
424 | */ | ||
425 | rate = rate * 1000; | ||
426 | |||
427 | clkin = clk->parent->rate; | ||
428 | usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) & | ||
429 | LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1; | ||
430 | clkin = clkin / usbdiv; | ||
431 | |||
432 | /* Try to find a good rate setup */ | ||
433 | if (local_clk_find_pll_cfg(clkin, rate, &pllsetup) == 0) | ||
434 | return 0; | ||
435 | |||
436 | return clk_check_pll_setup(clkin, &pllsetup); | ||
437 | } | ||
438 | |||
439 | static int local_usbpll_set_rate(struct clk *clk, unsigned long rate) | ||
440 | { | ||
441 | u32 clkin, reg, usbdiv; | ||
442 | struct clk_pll_setup pllsetup; | ||
443 | |||
444 | /* | ||
445 | * Unlike other clocks, this clock has a KHz input rate, so bump | ||
446 | * it up to work with the PLL function | ||
447 | */ | ||
448 | rate = rate * 1000; | ||
449 | |||
450 | clkin = clk->get_rate(clk); | ||
451 | usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) & | ||
452 | LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1; | ||
453 | clkin = clkin / usbdiv; | ||
454 | |||
455 | /* Try to find a good rate setup */ | ||
456 | if (local_clk_find_pll_cfg(clkin, rate, &pllsetup) == 0) | ||
457 | return -EINVAL; | ||
458 | |||
459 | local_usbpll_enable(clk, 0); | ||
460 | |||
461 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); | ||
462 | reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1; | ||
463 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | ||
464 | |||
465 | pllsetup.analog_on = 1; | ||
466 | local_clk_usbpll_setup(&pllsetup); | ||
467 | |||
468 | clk->rate = clk_check_pll_setup(clkin, &pllsetup); | ||
469 | |||
470 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); | ||
471 | reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2; | ||
472 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | ||
473 | |||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static struct clk clk_usbpll = { | ||
478 | .parent = &osc_main, | ||
479 | .set_rate = local_usbpll_set_rate, | ||
480 | .enable = local_usbpll_enable, | ||
481 | .rate = 48000, /* In KHz */ | ||
482 | .get_rate = local_return_parent_rate, | ||
483 | .round_rate = local_usbpll_round_rate, | ||
484 | }; | ||
485 | |||
486 | static u32 clk_get_hclk_div(void) | ||
487 | { | ||
488 | static const u32 hclkdivs[4] = {1, 2, 4, 4}; | ||
489 | return hclkdivs[LPC32XX_CLKPWR_HCLKDIV_DIV_2POW( | ||
490 | __raw_readl(LPC32XX_CLKPWR_HCLK_DIV))]; | ||
491 | } | ||
492 | |||
493 | static struct clk clk_hclk = { | ||
494 | .parent = &clk_armpll, | ||
495 | .get_rate = local_return_parent_rate, | ||
496 | }; | ||
497 | |||
498 | static struct clk clk_pclk = { | ||
499 | .parent = &clk_armpll, | ||
500 | .get_rate = local_return_parent_rate, | ||
501 | }; | ||
502 | |||
503 | static int local_onoff_enable(struct clk *clk, int enable) | ||
504 | { | ||
505 | u32 tmp; | ||
506 | |||
507 | tmp = __raw_readl(clk->enable_reg); | ||
508 | |||
509 | if (enable == 0) | ||
510 | tmp &= ~clk->enable_mask; | ||
511 | else | ||
512 | tmp |= clk->enable_mask; | ||
513 | |||
514 | __raw_writel(tmp, clk->enable_reg); | ||
515 | |||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | /* Peripheral clock sources */ | ||
520 | static struct clk clk_timer0 = { | ||
521 | .parent = &clk_pclk, | ||
522 | .enable = local_onoff_enable, | ||
523 | .enable_reg = LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1, | ||
524 | .enable_mask = LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN, | ||
525 | .get_rate = local_return_parent_rate, | ||
526 | }; | ||
527 | static struct clk clk_timer1 = { | ||
528 | .parent = &clk_pclk, | ||
529 | .enable = local_onoff_enable, | ||
530 | .enable_reg = LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1, | ||
531 | .enable_mask = LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN, | ||
532 | .get_rate = local_return_parent_rate, | ||
533 | }; | ||
534 | static struct clk clk_timer2 = { | ||
535 | .parent = &clk_pclk, | ||
536 | .enable = local_onoff_enable, | ||
537 | .enable_reg = LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1, | ||
538 | .enable_mask = LPC32XX_CLKPWR_TMRPWMCLK_TIMER2_EN, | ||
539 | .get_rate = local_return_parent_rate, | ||
540 | }; | ||
541 | static struct clk clk_timer3 = { | ||
542 | .parent = &clk_pclk, | ||
543 | .enable = local_onoff_enable, | ||
544 | .enable_reg = LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1, | ||
545 | .enable_mask = LPC32XX_CLKPWR_TMRPWMCLK_TIMER3_EN, | ||
546 | .get_rate = local_return_parent_rate, | ||
547 | }; | ||
548 | static struct clk clk_wdt = { | ||
549 | .parent = &clk_pclk, | ||
550 | .enable = local_onoff_enable, | ||
551 | .enable_reg = LPC32XX_CLKPWR_TIMER_CLK_CTRL, | ||
552 | .enable_mask = LPC32XX_CLKPWR_PWMCLK_WDOG_EN, | ||
553 | .get_rate = local_return_parent_rate, | ||
554 | }; | ||
555 | static struct clk clk_vfp9 = { | ||
556 | .parent = &clk_pclk, | ||
557 | .enable = local_onoff_enable, | ||
558 | .enable_reg = LPC32XX_CLKPWR_DEBUG_CTRL, | ||
559 | .enable_mask = LPC32XX_CLKPWR_VFP_CLOCK_ENABLE_BIT, | ||
560 | .get_rate = local_return_parent_rate, | ||
561 | }; | ||
562 | static struct clk clk_dma = { | ||
563 | .parent = &clk_hclk, | ||
564 | .enable = local_onoff_enable, | ||
565 | .enable_reg = LPC32XX_CLKPWR_DMA_CLK_CTRL, | ||
566 | .enable_mask = LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN, | ||
567 | .get_rate = local_return_parent_rate, | ||
568 | }; | ||
569 | |||
570 | static struct clk clk_uart3 = { | ||
571 | .parent = &clk_pclk, | ||
572 | .enable = local_onoff_enable, | ||
573 | .enable_reg = LPC32XX_CLKPWR_UART_CLK_CTRL, | ||
574 | .enable_mask = LPC32XX_CLKPWR_UARTCLKCTRL_UART3_EN, | ||
575 | .get_rate = local_return_parent_rate, | ||
576 | }; | ||
577 | |||
578 | static struct clk clk_uart4 = { | ||
579 | .parent = &clk_pclk, | ||
580 | .enable = local_onoff_enable, | ||
581 | .enable_reg = LPC32XX_CLKPWR_UART_CLK_CTRL, | ||
582 | .enable_mask = LPC32XX_CLKPWR_UARTCLKCTRL_UART4_EN, | ||
583 | .get_rate = local_return_parent_rate, | ||
584 | }; | ||
585 | |||
586 | static struct clk clk_uart5 = { | ||
587 | .parent = &clk_pclk, | ||
588 | .enable = local_onoff_enable, | ||
589 | .enable_reg = LPC32XX_CLKPWR_UART_CLK_CTRL, | ||
590 | .enable_mask = LPC32XX_CLKPWR_UARTCLKCTRL_UART5_EN, | ||
591 | .get_rate = local_return_parent_rate, | ||
592 | }; | ||
593 | |||
594 | static struct clk clk_uart6 = { | ||
595 | .parent = &clk_pclk, | ||
596 | .enable = local_onoff_enable, | ||
597 | .enable_reg = LPC32XX_CLKPWR_UART_CLK_CTRL, | ||
598 | .enable_mask = LPC32XX_CLKPWR_UARTCLKCTRL_UART6_EN, | ||
599 | .get_rate = local_return_parent_rate, | ||
600 | }; | ||
601 | |||
602 | static struct clk clk_i2c0 = { | ||
603 | .parent = &clk_hclk, | ||
604 | .enable = local_onoff_enable, | ||
605 | .enable_reg = LPC32XX_CLKPWR_I2C_CLK_CTRL, | ||
606 | .enable_mask = LPC32XX_CLKPWR_I2CCLK_I2C1CLK_EN, | ||
607 | .get_rate = local_return_parent_rate, | ||
608 | }; | ||
609 | |||
610 | static struct clk clk_i2c1 = { | ||
611 | .parent = &clk_hclk, | ||
612 | .enable = local_onoff_enable, | ||
613 | .enable_reg = LPC32XX_CLKPWR_I2C_CLK_CTRL, | ||
614 | .enable_mask = LPC32XX_CLKPWR_I2CCLK_I2C2CLK_EN, | ||
615 | .get_rate = local_return_parent_rate, | ||
616 | }; | ||
617 | |||
618 | static struct clk clk_i2c2 = { | ||
619 | .parent = &clk_pclk, | ||
620 | .enable = local_onoff_enable, | ||
621 | .enable_reg = io_p2v(LPC32XX_USB_BASE + 0xFF4), | ||
622 | .enable_mask = 0x4, | ||
623 | .get_rate = local_return_parent_rate, | ||
624 | }; | ||
625 | |||
626 | static struct clk clk_ssp0 = { | ||
627 | .parent = &clk_hclk, | ||
628 | .enable = local_onoff_enable, | ||
629 | .enable_reg = LPC32XX_CLKPWR_SSP_CLK_CTRL, | ||
630 | .enable_mask = LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN, | ||
631 | .get_rate = local_return_parent_rate, | ||
632 | }; | ||
633 | |||
634 | static struct clk clk_ssp1 = { | ||
635 | .parent = &clk_hclk, | ||
636 | .enable = local_onoff_enable, | ||
637 | .enable_reg = LPC32XX_CLKPWR_SSP_CLK_CTRL, | ||
638 | .enable_mask = LPC32XX_CLKPWR_SSPCTRL_SSPCLK1_EN, | ||
639 | .get_rate = local_return_parent_rate, | ||
640 | }; | ||
641 | |||
642 | static struct clk clk_kscan = { | ||
643 | .parent = &osc_32KHz, | ||
644 | .enable = local_onoff_enable, | ||
645 | .enable_reg = LPC32XX_CLKPWR_KEY_CLK_CTRL, | ||
646 | .enable_mask = LPC32XX_CLKPWR_KEYCLKCTRL_CLK_EN, | ||
647 | .get_rate = local_return_parent_rate, | ||
648 | }; | ||
649 | |||
650 | static struct clk clk_nand = { | ||
651 | .parent = &clk_hclk, | ||
652 | .enable = local_onoff_enable, | ||
653 | .enable_reg = LPC32XX_CLKPWR_NAND_CLK_CTRL, | ||
654 | .enable_mask = LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN, | ||
655 | .get_rate = local_return_parent_rate, | ||
656 | }; | ||
657 | |||
658 | static struct clk clk_i2s0 = { | ||
659 | .parent = &clk_hclk, | ||
660 | .enable = local_onoff_enable, | ||
661 | .enable_reg = LPC32XX_CLKPWR_I2S_CLK_CTRL, | ||
662 | .enable_mask = LPC32XX_CLKPWR_I2SCTRL_I2SCLK0_EN, | ||
663 | .get_rate = local_return_parent_rate, | ||
664 | }; | ||
665 | |||
666 | static struct clk clk_i2s1 = { | ||
667 | .parent = &clk_hclk, | ||
668 | .enable = local_onoff_enable, | ||
669 | .enable_reg = LPC32XX_CLKPWR_I2S_CLK_CTRL, | ||
670 | .enable_mask = LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN, | ||
671 | .get_rate = local_return_parent_rate, | ||
672 | }; | ||
673 | |||
674 | static struct clk clk_net = { | ||
675 | .parent = &clk_hclk, | ||
676 | .enable = local_onoff_enable, | ||
677 | .enable_reg = LPC32XX_CLKPWR_MACCLK_CTRL, | ||
678 | .enable_mask = (LPC32XX_CLKPWR_MACCTRL_DMACLK_EN | | ||
679 | LPC32XX_CLKPWR_MACCTRL_MMIOCLK_EN | | ||
680 | LPC32XX_CLKPWR_MACCTRL_HRCCLK_EN), | ||
681 | .get_rate = local_return_parent_rate, | ||
682 | }; | ||
683 | |||
684 | static struct clk clk_rtc = { | ||
685 | .parent = &osc_32KHz, | ||
686 | .rate = 1, /* 1 Hz */ | ||
687 | .get_rate = local_return_parent_rate, | ||
688 | }; | ||
689 | |||
690 | static struct clk clk_usbd = { | ||
691 | .parent = &clk_usbpll, | ||
692 | .enable = local_onoff_enable, | ||
693 | .enable_reg = LPC32XX_CLKPWR_USB_CTRL, | ||
694 | .enable_mask = LPC32XX_CLKPWR_USBCTRL_HCLK_EN, | ||
695 | .get_rate = local_return_parent_rate, | ||
696 | }; | ||
697 | |||
698 | static int tsc_onoff_enable(struct clk *clk, int enable) | ||
699 | { | ||
700 | u32 tmp; | ||
701 | |||
702 | /* Make sure 32KHz clock is the selected clock */ | ||
703 | tmp = __raw_readl(LPC32XX_CLKPWR_ADC_CLK_CTRL_1); | ||
704 | tmp &= ~LPC32XX_CLKPWR_ADCCTRL1_PCLK_SEL; | ||
705 | __raw_writel(tmp, LPC32XX_CLKPWR_ADC_CLK_CTRL_1); | ||
706 | |||
707 | if (enable == 0) | ||
708 | __raw_writel(0, clk->enable_reg); | ||
709 | else | ||
710 | __raw_writel(clk->enable_mask, clk->enable_reg); | ||
711 | |||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | static struct clk clk_tsc = { | ||
716 | .parent = &osc_32KHz, | ||
717 | .enable = tsc_onoff_enable, | ||
718 | .enable_reg = LPC32XX_CLKPWR_ADC_CLK_CTRL, | ||
719 | .enable_mask = LPC32XX_CLKPWR_ADC32CLKCTRL_CLK_EN, | ||
720 | .get_rate = local_return_parent_rate, | ||
721 | }; | ||
722 | |||
723 | static int mmc_onoff_enable(struct clk *clk, int enable) | ||
724 | { | ||
725 | u32 tmp; | ||
726 | |||
727 | tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL) & | ||
728 | ~LPC32XX_CLKPWR_MSCARD_SDCARD_EN; | ||
729 | |||
730 | /* If rate is 0, disable clock */ | ||
731 | if (enable != 0) | ||
732 | tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN; | ||
733 | |||
734 | __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL); | ||
735 | |||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | static unsigned long mmc_get_rate(struct clk *clk) | ||
740 | { | ||
741 | u32 div, rate, oldclk; | ||
742 | |||
743 | /* The MMC clock must be on when accessing an MMC register */ | ||
744 | oldclk = __raw_readl(LPC32XX_CLKPWR_MS_CTRL); | ||
745 | __raw_writel(oldclk | LPC32XX_CLKPWR_MSCARD_SDCARD_EN, | ||
746 | LPC32XX_CLKPWR_MS_CTRL); | ||
747 | div = __raw_readl(LPC32XX_CLKPWR_MS_CTRL); | ||
748 | __raw_writel(oldclk, LPC32XX_CLKPWR_MS_CTRL); | ||
749 | |||
750 | /* Get the parent clock rate */ | ||
751 | rate = clk->parent->get_rate(clk->parent); | ||
752 | |||
753 | /* Get the MMC controller clock divider value */ | ||
754 | div = div & LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(0xf); | ||
755 | |||
756 | if (!div) | ||
757 | div = 1; | ||
758 | |||
759 | return rate / div; | ||
760 | } | ||
761 | |||
762 | static unsigned long mmc_round_rate(struct clk *clk, unsigned long rate) | ||
763 | { | ||
764 | unsigned long div, prate; | ||
765 | |||
766 | /* Get the parent clock rate */ | ||
767 | prate = clk->parent->get_rate(clk->parent); | ||
768 | |||
769 | if (rate >= prate) | ||
770 | return prate; | ||
771 | |||
772 | div = prate / rate; | ||
773 | if (div > 0xf) | ||
774 | div = 0xf; | ||
775 | |||
776 | return prate / div; | ||
777 | } | ||
778 | |||
779 | static int mmc_set_rate(struct clk *clk, unsigned long rate) | ||
780 | { | ||
781 | u32 oldclk, tmp; | ||
782 | unsigned long prate, div, crate = mmc_round_rate(clk, rate); | ||
783 | |||
784 | prate = clk->parent->get_rate(clk->parent); | ||
785 | |||
786 | div = prate / crate; | ||
787 | |||
788 | /* The MMC clock must be on when accessing an MMC register */ | ||
789 | oldclk = __raw_readl(LPC32XX_CLKPWR_MS_CTRL); | ||
790 | __raw_writel(oldclk | LPC32XX_CLKPWR_MSCARD_SDCARD_EN, | ||
791 | LPC32XX_CLKPWR_MS_CTRL); | ||
792 | tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL) & | ||
793 | ~LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(0xf); | ||
794 | tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(div); | ||
795 | __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL); | ||
796 | |||
797 | __raw_writel(oldclk, LPC32XX_CLKPWR_MS_CTRL); | ||
798 | |||
799 | return 0; | ||
800 | } | ||
801 | |||
802 | static struct clk clk_mmc = { | ||
803 | .parent = &clk_armpll, | ||
804 | .set_rate = mmc_set_rate, | ||
805 | .get_rate = mmc_get_rate, | ||
806 | .round_rate = mmc_round_rate, | ||
807 | .enable = mmc_onoff_enable, | ||
808 | .enable_reg = LPC32XX_CLKPWR_MS_CTRL, | ||
809 | .enable_mask = LPC32XX_CLKPWR_MSCARD_SDCARD_EN, | ||
810 | }; | ||
811 | |||
812 | static unsigned long clcd_get_rate(struct clk *clk) | ||
813 | { | ||
814 | u32 tmp, div, rate, oldclk; | ||
815 | |||
816 | /* The LCD clock must be on when accessing an LCD register */ | ||
817 | oldclk = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL); | ||
818 | __raw_writel(oldclk | LPC32XX_CLKPWR_LCDCTRL_CLK_EN, | ||
819 | LPC32XX_CLKPWR_LCDCLK_CTRL); | ||
820 | tmp = __raw_readl(io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2)); | ||
821 | __raw_writel(oldclk, LPC32XX_CLKPWR_LCDCLK_CTRL); | ||
822 | |||
823 | rate = clk->parent->get_rate(clk->parent); | ||
824 | |||
825 | /* Only supports internal clocking */ | ||
826 | if (tmp & TIM2_BCD) | ||
827 | return rate; | ||
828 | |||
829 | div = (tmp & 0x1F) | ((tmp & 0xF8) >> 22); | ||
830 | tmp = rate / (2 + div); | ||
831 | |||
832 | return tmp; | ||
833 | } | ||
834 | |||
835 | static int clcd_set_rate(struct clk *clk, unsigned long rate) | ||
836 | { | ||
837 | u32 tmp, prate, div, oldclk; | ||
838 | |||
839 | /* The LCD clock must be on when accessing an LCD register */ | ||
840 | oldclk = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL); | ||
841 | __raw_writel(oldclk | LPC32XX_CLKPWR_LCDCTRL_CLK_EN, | ||
842 | LPC32XX_CLKPWR_LCDCLK_CTRL); | ||
843 | |||
844 | tmp = __raw_readl(io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2)) | TIM2_BCD; | ||
845 | prate = clk->parent->get_rate(clk->parent); | ||
846 | |||
847 | if (rate < prate) { | ||
848 | /* Find closest divider */ | ||
849 | div = prate / rate; | ||
850 | if (div >= 2) { | ||
851 | div -= 2; | ||
852 | tmp &= ~TIM2_BCD; | ||
853 | } | ||
854 | |||
855 | tmp &= ~(0xF800001F); | ||
856 | tmp |= (div & 0x1F); | ||
857 | tmp |= (((div >> 5) & 0x1F) << 27); | ||
858 | } | ||
859 | |||
860 | __raw_writel(tmp, io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2)); | ||
861 | __raw_writel(oldclk, LPC32XX_CLKPWR_LCDCLK_CTRL); | ||
862 | |||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static unsigned long clcd_round_rate(struct clk *clk, unsigned long rate) | ||
867 | { | ||
868 | u32 prate, div; | ||
869 | |||
870 | prate = clk->parent->get_rate(clk->parent); | ||
871 | |||
872 | if (rate >= prate) | ||
873 | rate = prate; | ||
874 | else { | ||
875 | div = prate / rate; | ||
876 | if (div > 0x3ff) | ||
877 | div = 0x3ff; | ||
878 | |||
879 | rate = prate / div; | ||
880 | } | ||
881 | |||
882 | return rate; | ||
883 | } | ||
884 | |||
885 | static struct clk clk_lcd = { | ||
886 | .parent = &clk_hclk, | ||
887 | .set_rate = clcd_set_rate, | ||
888 | .get_rate = clcd_get_rate, | ||
889 | .round_rate = clcd_round_rate, | ||
890 | .enable = local_onoff_enable, | ||
891 | .enable_reg = LPC32XX_CLKPWR_LCDCLK_CTRL, | ||
892 | .enable_mask = LPC32XX_CLKPWR_LCDCTRL_CLK_EN, | ||
893 | }; | ||
894 | |||
895 | static inline void clk_lock(void) | ||
896 | { | ||
897 | mutex_lock(&clkm_lock); | ||
898 | } | ||
899 | |||
900 | static inline void clk_unlock(void) | ||
901 | { | ||
902 | mutex_unlock(&clkm_lock); | ||
903 | } | ||
904 | |||
905 | static void local_clk_disable(struct clk *clk) | ||
906 | { | ||
907 | WARN_ON(clk->usecount == 0); | ||
908 | |||
909 | /* Don't attempt to disable clock if it has no users */ | ||
910 | if (clk->usecount > 0) { | ||
911 | clk->usecount--; | ||
912 | |||
913 | /* Only disable clock when it has no more users */ | ||
914 | if ((clk->usecount == 0) && (clk->enable)) | ||
915 | clk->enable(clk, 0); | ||
916 | |||
917 | /* Check parent clocks, they may need to be disabled too */ | ||
918 | if (clk->parent) | ||
919 | local_clk_disable(clk->parent); | ||
920 | } | ||
921 | } | ||
922 | |||
923 | static int local_clk_enable(struct clk *clk) | ||
924 | { | ||
925 | int ret = 0; | ||
926 | |||
927 | /* Enable parent clocks first and update use counts */ | ||
928 | if (clk->parent) | ||
929 | ret = local_clk_enable(clk->parent); | ||
930 | |||
931 | if (!ret) { | ||
932 | /* Only enable clock if it's currently disabled */ | ||
933 | if ((clk->usecount == 0) && (clk->enable)) | ||
934 | ret = clk->enable(clk, 1); | ||
935 | |||
936 | if (!ret) | ||
937 | clk->usecount++; | ||
938 | else if (clk->parent) | ||
939 | local_clk_disable(clk->parent); | ||
940 | } | ||
941 | |||
942 | return ret; | ||
943 | } | ||
944 | |||
945 | /* | ||
946 | * clk_enable - inform the system when the clock source should be running. | ||
947 | */ | ||
948 | int clk_enable(struct clk *clk) | ||
949 | { | ||
950 | int ret; | ||
951 | |||
952 | clk_lock(); | ||
953 | ret = local_clk_enable(clk); | ||
954 | clk_unlock(); | ||
955 | |||
956 | return ret; | ||
957 | } | ||
958 | EXPORT_SYMBOL(clk_enable); | ||
959 | |||
960 | /* | ||
961 | * clk_disable - inform the system when the clock source is no longer required | ||
962 | */ | ||
963 | void clk_disable(struct clk *clk) | ||
964 | { | ||
965 | clk_lock(); | ||
966 | local_clk_disable(clk); | ||
967 | clk_unlock(); | ||
968 | } | ||
969 | EXPORT_SYMBOL(clk_disable); | ||
970 | |||
971 | /* | ||
972 | * clk_get_rate - obtain the current clock rate (in Hz) for a clock source | ||
973 | */ | ||
974 | unsigned long clk_get_rate(struct clk *clk) | ||
975 | { | ||
976 | unsigned long rate; | ||
977 | |||
978 | clk_lock(); | ||
979 | rate = clk->get_rate(clk); | ||
980 | clk_unlock(); | ||
981 | |||
982 | return rate; | ||
983 | } | ||
984 | EXPORT_SYMBOL(clk_get_rate); | ||
985 | |||
986 | /* | ||
987 | * clk_set_rate - set the clock rate for a clock source | ||
988 | */ | ||
989 | int clk_set_rate(struct clk *clk, unsigned long rate) | ||
990 | { | ||
991 | int ret = -EINVAL; | ||
992 | |||
993 | /* | ||
994 | * Most system clocks can only be enabled or disabled, with | ||
995 | * the actual rate set as part of the peripheral dividers | ||
996 | * instead of high level clock control | ||
997 | */ | ||
998 | if (clk->set_rate) { | ||
999 | clk_lock(); | ||
1000 | ret = clk->set_rate(clk, rate); | ||
1001 | clk_unlock(); | ||
1002 | } | ||
1003 | |||
1004 | return ret; | ||
1005 | } | ||
1006 | EXPORT_SYMBOL(clk_set_rate); | ||
1007 | |||
1008 | /* | ||
1009 | * clk_round_rate - adjust a rate to the exact rate a clock can provide | ||
1010 | */ | ||
1011 | long clk_round_rate(struct clk *clk, unsigned long rate) | ||
1012 | { | ||
1013 | clk_lock(); | ||
1014 | |||
1015 | if (clk->round_rate) | ||
1016 | rate = clk->round_rate(clk, rate); | ||
1017 | else | ||
1018 | rate = clk->get_rate(clk); | ||
1019 | |||
1020 | clk_unlock(); | ||
1021 | |||
1022 | return rate; | ||
1023 | } | ||
1024 | EXPORT_SYMBOL(clk_round_rate); | ||
1025 | |||
1026 | /* | ||
1027 | * clk_set_parent - set the parent clock source for this clock | ||
1028 | */ | ||
1029 | int clk_set_parent(struct clk *clk, struct clk *parent) | ||
1030 | { | ||
1031 | /* Clock re-parenting is not supported */ | ||
1032 | return -EINVAL; | ||
1033 | } | ||
1034 | EXPORT_SYMBOL(clk_set_parent); | ||
1035 | |||
1036 | /* | ||
1037 | * clk_get_parent - get the parent clock source for this clock | ||
1038 | */ | ||
1039 | struct clk *clk_get_parent(struct clk *clk) | ||
1040 | { | ||
1041 | return clk->parent; | ||
1042 | } | ||
1043 | EXPORT_SYMBOL(clk_get_parent); | ||
1044 | |||
1045 | #define _REGISTER_CLOCK(d, n, c) \ | ||
1046 | { \ | ||
1047 | .dev_id = (d), \ | ||
1048 | .con_id = (n), \ | ||
1049 | .clk = &(c), \ | ||
1050 | }, | ||
1051 | |||
1052 | static struct clk_lookup lookups[] = { | ||
1053 | _REGISTER_CLOCK(NULL, "osc_32KHz", osc_32KHz) | ||
1054 | _REGISTER_CLOCK(NULL, "osc_pll397", osc_pll397) | ||
1055 | _REGISTER_CLOCK(NULL, "osc_main", osc_main) | ||
1056 | _REGISTER_CLOCK(NULL, "sys_ck", clk_sys) | ||
1057 | _REGISTER_CLOCK(NULL, "arm_pll_ck", clk_armpll) | ||
1058 | _REGISTER_CLOCK(NULL, "ck_pll5", clk_usbpll) | ||
1059 | _REGISTER_CLOCK(NULL, "hclk_ck", clk_hclk) | ||
1060 | _REGISTER_CLOCK(NULL, "pclk_ck", clk_pclk) | ||
1061 | _REGISTER_CLOCK(NULL, "timer0_ck", clk_timer0) | ||
1062 | _REGISTER_CLOCK(NULL, "timer1_ck", clk_timer1) | ||
1063 | _REGISTER_CLOCK(NULL, "timer2_ck", clk_timer2) | ||
1064 | _REGISTER_CLOCK(NULL, "timer3_ck", clk_timer3) | ||
1065 | _REGISTER_CLOCK(NULL, "vfp9_ck", clk_vfp9) | ||
1066 | _REGISTER_CLOCK(NULL, "clk_dmac", clk_dma) | ||
1067 | _REGISTER_CLOCK("pnx4008-watchdog", NULL, clk_wdt) | ||
1068 | _REGISTER_CLOCK(NULL, "uart3_ck", clk_uart3) | ||
1069 | _REGISTER_CLOCK(NULL, "uart4_ck", clk_uart4) | ||
1070 | _REGISTER_CLOCK(NULL, "uart5_ck", clk_uart5) | ||
1071 | _REGISTER_CLOCK(NULL, "uart6_ck", clk_uart6) | ||
1072 | _REGISTER_CLOCK("pnx-i2c.0", NULL, clk_i2c0) | ||
1073 | _REGISTER_CLOCK("pnx-i2c.1", NULL, clk_i2c1) | ||
1074 | _REGISTER_CLOCK("pnx-i2c.2", NULL, clk_i2c2) | ||
1075 | _REGISTER_CLOCK("dev:ssp0", NULL, clk_ssp0) | ||
1076 | _REGISTER_CLOCK("dev:ssp1", NULL, clk_ssp1) | ||
1077 | _REGISTER_CLOCK("lpc32xx_keys.0", NULL, clk_kscan) | ||
1078 | _REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand) | ||
1079 | _REGISTER_CLOCK("tbd", "i2s0_ck", clk_i2s0) | ||
1080 | _REGISTER_CLOCK("tbd", "i2s1_ck", clk_i2s1) | ||
1081 | _REGISTER_CLOCK("lpc32xx-ts", NULL, clk_tsc) | ||
1082 | _REGISTER_CLOCK("dev:mmc0", "MCLK", clk_mmc) | ||
1083 | _REGISTER_CLOCK("lpc-net.0", NULL, clk_net) | ||
1084 | _REGISTER_CLOCK("dev:clcd", NULL, clk_lcd) | ||
1085 | _REGISTER_CLOCK("lpc32xx_udc", "ck_usbd", clk_usbd) | ||
1086 | _REGISTER_CLOCK("lpc32xx_rtc", NULL, clk_rtc) | ||
1087 | }; | ||
1088 | |||
1089 | static int __init clk_init(void) | ||
1090 | { | ||
1091 | int i; | ||
1092 | |||
1093 | for (i = 0; i < ARRAY_SIZE(lookups); i++) | ||
1094 | clkdev_add(&lookups[i]); | ||
1095 | |||
1096 | /* | ||
1097 | * Setup muxed SYSCLK for HCLK PLL base -this selects the | ||
1098 | * parent clock used for the ARM PLL and is used to derive | ||
1099 | * the many system clock rates in the device. | ||
1100 | */ | ||
1101 | if (clk_is_sysclk_mainosc() != 0) | ||
1102 | clk_sys.parent = &osc_main; | ||
1103 | else | ||
1104 | clk_sys.parent = &osc_pll397; | ||
1105 | |||
1106 | clk_sys.rate = clk_sys.parent->rate; | ||
1107 | |||
1108 | /* Compute the current ARM PLL and USB PLL frequencies */ | ||
1109 | local_update_armpll_rate(); | ||
1110 | |||
1111 | /* Compute HCLK and PCLK bus rates */ | ||
1112 | clk_hclk.rate = clk_hclk.parent->rate / clk_get_hclk_div(); | ||
1113 | clk_pclk.rate = clk_pclk.parent->rate / clk_get_pclk_div(); | ||
1114 | |||
1115 | /* | ||
1116 | * Enable system clocks - this step is somewhat formal, as the | ||
1117 | * clocks are already running, but it does get the clock data | ||
1118 | * inline with the actual system state. Never disable these | ||
1119 | * clocks as they will only stop if the system is going to sleep. | ||
1120 | * In that case, the chip/system power management functions will | ||
1121 | * handle clock gating. | ||
1122 | */ | ||
1123 | if (clk_enable(&clk_hclk) || clk_enable(&clk_pclk)) | ||
1124 | printk(KERN_ERR "Error enabling system HCLK and PCLK\n"); | ||
1125 | |||
1126 | /* | ||
1127 | * Timers 0 and 1 were enabled and are being used by the high | ||
1128 | * resolution tick function prior to this driver being initialized. | ||
1129 | * Tag them now as used. | ||
1130 | */ | ||
1131 | if (clk_enable(&clk_timer0) || clk_enable(&clk_timer1)) | ||
1132 | printk(KERN_ERR "Error enabling timer tick clocks\n"); | ||
1133 | |||
1134 | return 0; | ||
1135 | } | ||
1136 | core_initcall(clk_init); | ||
1137 | |||
diff --git a/arch/arm/mach-lpc32xx/clock.h b/arch/arm/mach-lpc32xx/clock.h new file mode 100644 index 000000000000..c0a8434307f7 --- /dev/null +++ b/arch/arm/mach-lpc32xx/clock.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-lpc32xx/clock.h | ||
3 | * | ||
4 | * Author: Kevin Wells <kevin.wells@nxp.com> | ||
5 | * | ||
6 | * Copyright (C) 2010 NXP Semiconductors | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #ifndef __LPC32XX_CLOCK_H | ||
20 | #define __LPC32XX_CLOCK_H | ||
21 | |||
22 | struct clk { | ||
23 | struct list_head node; | ||
24 | struct clk *parent; | ||
25 | u32 rate; | ||
26 | u32 usecount; | ||
27 | |||
28 | int (*set_rate) (struct clk *, unsigned long); | ||
29 | unsigned long (*round_rate) (struct clk *, unsigned long); | ||
30 | unsigned long (*get_rate) (struct clk *clk); | ||
31 | int (*enable) (struct clk *, int); | ||
32 | |||
33 | /* Register address and bit mask for simple clocks */ | ||
34 | void __iomem *enable_reg; | ||
35 | u32 enable_mask; | ||
36 | }; | ||
37 | |||
38 | #endif | ||