blob: df3ad3836576f6c604da36a0804515e3ee9b5a2d [file] [log] [blame]
Holger Schurigaa3b0a62009-01-26 16:34:54 +01001/*
2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
4 * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301, USA.
19 */
20
21#include <linux/clk.h>
22#include <linux/io.h>
23#include <linux/module.h>
24
25#include <mach/clock.h>
Uwe Kleine-König5113f812009-12-11 10:07:15 +010026#include <mach/hardware.h>
Holger Schurigaa3b0a62009-01-26 16:34:54 +010027#include <mach/common.h>
28#include <asm/clkdev.h>
29#include <asm/div64.h>
30
Uwe Kleine-König5113f812009-12-11 10:07:15 +010031/* Register offsets */
32#define CCM_CSCR (IO_ADDRESS(CCM_BASE_ADDR) + 0x0)
33#define CCM_MPCTL0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x4)
34#define CCM_MPCTL1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x8)
35#define CCM_SPCTL0 (IO_ADDRESS(CCM_BASE_ADDR) + 0xC)
36#define CCM_SPCTL1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x10)
37#define CCM_OSC26MCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x14)
38#define CCM_PCDR0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x18)
39#define CCM_PCDR1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x1c)
40#define CCM_PCCR0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x20)
41#define CCM_PCCR1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x24)
42#define CCM_CCSR (IO_ADDRESS(CCM_BASE_ADDR) + 0x28)
43#define CCM_PMCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x2c)
44#define CCM_PMCOUNT (IO_ADDRESS(CCM_BASE_ADDR) + 0x30)
45#define CCM_WKGDCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x34)
46
47#define CCM_CSCR_PRESC_OFFSET 29
48#define CCM_CSCR_PRESC_MASK (0x7 << CCM_CSCR_PRESC_OFFSET)
49
50#define CCM_CSCR_USB_OFFSET 26
51#define CCM_CSCR_USB_MASK (0x7 << CCM_CSCR_USB_OFFSET)
52#define CCM_CSCR_SD_OFFSET 24
53#define CCM_CSCR_SD_MASK (0x3 << CCM_CSCR_SD_OFFSET)
54#define CCM_CSCR_SPLLRES (1 << 22)
55#define CCM_CSCR_MPLLRES (1 << 21)
56#define CCM_CSCR_SSI2_OFFSET 20
57#define CCM_CSCR_SSI2 (1 << CCM_CSCR_SSI2_OFFSET)
58#define CCM_CSCR_SSI1_OFFSET 19
59#define CCM_CSCR_SSI1 (1 << CCM_CSCR_SSI1_OFFSET)
60#define CCM_CSCR_FIR_OFFSET 18
61#define CCM_CSCR_FIR (1 << CCM_CSCR_FIR_OFFSET)
62#define CCM_CSCR_SP (1 << 17)
63#define CCM_CSCR_MCU (1 << 16)
64#define CCM_CSCR_BCLK_OFFSET 10
65#define CCM_CSCR_BCLK_MASK (0xf << CCM_CSCR_BCLK_OFFSET)
66#define CCM_CSCR_IPDIV_OFFSET 9
67#define CCM_CSCR_IPDIV (1 << CCM_CSCR_IPDIV_OFFSET)
68
69#define CCM_CSCR_OSC26MDIV (1 << 4)
70#define CCM_CSCR_OSC26M (1 << 3)
71#define CCM_CSCR_FPM (1 << 2)
72#define CCM_CSCR_SPEN (1 << 1)
73#define CCM_CSCR_MPEN 1
74
75#define CCM_MPCTL0_CPLM (1 << 31)
76#define CCM_MPCTL0_PD_OFFSET 26
77#define CCM_MPCTL0_PD_MASK (0xf << 26)
78#define CCM_MPCTL0_MFD_OFFSET 16
79#define CCM_MPCTL0_MFD_MASK (0x3ff << 16)
80#define CCM_MPCTL0_MFI_OFFSET 10
81#define CCM_MPCTL0_MFI_MASK (0xf << 10)
82#define CCM_MPCTL0_MFN_OFFSET 0
83#define CCM_MPCTL0_MFN_MASK 0x3ff
84
85#define CCM_MPCTL1_LF (1 << 15)
86#define CCM_MPCTL1_BRMO (1 << 6)
87
88#define CCM_SPCTL0_CPLM (1 << 31)
89#define CCM_SPCTL0_PD_OFFSET 26
90#define CCM_SPCTL0_PD_MASK (0xf << 26)
91#define CCM_SPCTL0_MFD_OFFSET 16
92#define CCM_SPCTL0_MFD_MASK (0x3ff << 16)
93#define CCM_SPCTL0_MFI_OFFSET 10
94#define CCM_SPCTL0_MFI_MASK (0xf << 10)
95#define CCM_SPCTL0_MFN_OFFSET 0
96#define CCM_SPCTL0_MFN_MASK 0x3ff
97
98#define CCM_SPCTL1_LF (1 << 15)
99#define CCM_SPCTL1_BRMO (1 << 6)
100
101#define CCM_OSC26MCTL_PEAK_OFFSET 16
102#define CCM_OSC26MCTL_PEAK_MASK (0x3 << 16)
103#define CCM_OSC26MCTL_AGC_OFFSET 8
104#define CCM_OSC26MCTL_AGC_MASK (0x3f << 8)
105#define CCM_OSC26MCTL_ANATEST_OFFSET 0
106#define CCM_OSC26MCTL_ANATEST_MASK 0x3f
107
108#define CCM_PCDR0_SSI2BAUDDIV_OFFSET 26
109#define CCM_PCDR0_SSI2BAUDDIV_MASK (0x3f << 26)
110#define CCM_PCDR0_SSI1BAUDDIV_OFFSET 16
111#define CCM_PCDR0_SSI1BAUDDIV_MASK (0x3f << 16)
112#define CCM_PCDR0_NFCDIV_OFFSET 12
113#define CCM_PCDR0_NFCDIV_MASK (0xf << 12)
114#define CCM_PCDR0_48MDIV_OFFSET 5
115#define CCM_PCDR0_48MDIV_MASK (0x7 << CCM_PCDR0_48MDIV_OFFSET)
116#define CCM_PCDR0_FIRIDIV_OFFSET 0
117#define CCM_PCDR0_FIRIDIV_MASK 0x1f
118#define CCM_PCDR1_PERDIV4_OFFSET 24
119#define CCM_PCDR1_PERDIV4_MASK (0x3f << 24)
120#define CCM_PCDR1_PERDIV3_OFFSET 16
121#define CCM_PCDR1_PERDIV3_MASK (0x3f << 16)
122#define CCM_PCDR1_PERDIV2_OFFSET 8
123#define CCM_PCDR1_PERDIV2_MASK (0x3f << 8)
124#define CCM_PCDR1_PERDIV1_OFFSET 0
125#define CCM_PCDR1_PERDIV1_MASK 0x3f
126
127#define CCM_PCCR_HCLK_CSI_OFFSET 31
128#define CCM_PCCR_HCLK_CSI_REG CCM_PCCR0
129#define CCM_PCCR_HCLK_DMA_OFFSET 30
130#define CCM_PCCR_HCLK_DMA_REG CCM_PCCR0
131#define CCM_PCCR_HCLK_BROM_OFFSET 28
132#define CCM_PCCR_HCLK_BROM_REG CCM_PCCR0
133#define CCM_PCCR_HCLK_EMMA_OFFSET 27
134#define CCM_PCCR_HCLK_EMMA_REG CCM_PCCR0
135#define CCM_PCCR_HCLK_LCDC_OFFSET 26
136#define CCM_PCCR_HCLK_LCDC_REG CCM_PCCR0
137#define CCM_PCCR_HCLK_SLCDC_OFFSET 25
138#define CCM_PCCR_HCLK_SLCDC_REG CCM_PCCR0
139#define CCM_PCCR_HCLK_USBOTG_OFFSET 24
140#define CCM_PCCR_HCLK_USBOTG_REG CCM_PCCR0
141#define CCM_PCCR_HCLK_BMI_OFFSET 23
142#define CCM_PCCR_BMI_MASK (1 << CCM_PCCR_BMI_MASK)
143#define CCM_PCCR_HCLK_BMI_REG CCM_PCCR0
144#define CCM_PCCR_PERCLK4_OFFSET 22
145#define CCM_PCCR_PERCLK4_REG CCM_PCCR0
146#define CCM_PCCR_SLCDC_OFFSET 21
147#define CCM_PCCR_SLCDC_REG CCM_PCCR0
148#define CCM_PCCR_FIRI_BAUD_OFFSET 20
149#define CCM_PCCR_FIRI_BAUD_MASK (1 << CCM_PCCR_FIRI_BAUD_MASK)
150#define CCM_PCCR_FIRI_BAUD_REG CCM_PCCR0
151#define CCM_PCCR_NFC_OFFSET 19
152#define CCM_PCCR_NFC_REG CCM_PCCR0
153#define CCM_PCCR_LCDC_OFFSET 18
154#define CCM_PCCR_LCDC_REG CCM_PCCR0
155#define CCM_PCCR_SSI1_BAUD_OFFSET 17
156#define CCM_PCCR_SSI1_BAUD_REG CCM_PCCR0
157#define CCM_PCCR_SSI2_BAUD_OFFSET 16
158#define CCM_PCCR_SSI2_BAUD_REG CCM_PCCR0
159#define CCM_PCCR_EMMA_OFFSET 15
160#define CCM_PCCR_EMMA_REG CCM_PCCR0
161#define CCM_PCCR_USBOTG_OFFSET 14
162#define CCM_PCCR_USBOTG_REG CCM_PCCR0
163#define CCM_PCCR_DMA_OFFSET 13
164#define CCM_PCCR_DMA_REG CCM_PCCR0
165#define CCM_PCCR_I2C1_OFFSET 12
166#define CCM_PCCR_I2C1_REG CCM_PCCR0
167#define CCM_PCCR_GPIO_OFFSET 11
168#define CCM_PCCR_GPIO_REG CCM_PCCR0
169#define CCM_PCCR_SDHC2_OFFSET 10
170#define CCM_PCCR_SDHC2_REG CCM_PCCR0
171#define CCM_PCCR_SDHC1_OFFSET 9
172#define CCM_PCCR_SDHC1_REG CCM_PCCR0
173#define CCM_PCCR_FIRI_OFFSET 8
174#define CCM_PCCR_FIRI_MASK (1 << CCM_PCCR_BAUD_MASK)
175#define CCM_PCCR_FIRI_REG CCM_PCCR0
176#define CCM_PCCR_SSI2_IPG_OFFSET 7
177#define CCM_PCCR_SSI2_REG CCM_PCCR0
178#define CCM_PCCR_SSI1_IPG_OFFSET 6
179#define CCM_PCCR_SSI1_REG CCM_PCCR0
180#define CCM_PCCR_CSPI2_OFFSET 5
181#define CCM_PCCR_CSPI2_REG CCM_PCCR0
182#define CCM_PCCR_CSPI1_OFFSET 4
183#define CCM_PCCR_CSPI1_REG CCM_PCCR0
184#define CCM_PCCR_UART4_OFFSET 3
185#define CCM_PCCR_UART4_REG CCM_PCCR0
186#define CCM_PCCR_UART3_OFFSET 2
187#define CCM_PCCR_UART3_REG CCM_PCCR0
188#define CCM_PCCR_UART2_OFFSET 1
189#define CCM_PCCR_UART2_REG CCM_PCCR0
190#define CCM_PCCR_UART1_OFFSET 0
191#define CCM_PCCR_UART1_REG CCM_PCCR0
192
193#define CCM_PCCR_OWIRE_OFFSET 31
194#define CCM_PCCR_OWIRE_REG CCM_PCCR1
195#define CCM_PCCR_KPP_OFFSET 30
196#define CCM_PCCR_KPP_REG CCM_PCCR1
197#define CCM_PCCR_RTC_OFFSET 29
198#define CCM_PCCR_RTC_REG CCM_PCCR1
199#define CCM_PCCR_PWM_OFFSET 28
200#define CCM_PCCR_PWM_REG CCM_PCCR1
201#define CCM_PCCR_GPT3_OFFSET 27
202#define CCM_PCCR_GPT3_REG CCM_PCCR1
203#define CCM_PCCR_GPT2_OFFSET 26
204#define CCM_PCCR_GPT2_REG CCM_PCCR1
205#define CCM_PCCR_GPT1_OFFSET 25
206#define CCM_PCCR_GPT1_REG CCM_PCCR1
207#define CCM_PCCR_WDT_OFFSET 24
208#define CCM_PCCR_WDT_REG CCM_PCCR1
209#define CCM_PCCR_CSPI3_OFFSET 23
210#define CCM_PCCR_CSPI3_REG CCM_PCCR1
211
212#define CCM_PCCR_CSPI1_MASK (1 << CCM_PCCR_CSPI1_OFFSET)
213#define CCM_PCCR_CSPI2_MASK (1 << CCM_PCCR_CSPI2_OFFSET)
214#define CCM_PCCR_CSPI3_MASK (1 << CCM_PCCR_CSPI3_OFFSET)
215#define CCM_PCCR_DMA_MASK (1 << CCM_PCCR_DMA_OFFSET)
216#define CCM_PCCR_EMMA_MASK (1 << CCM_PCCR_EMMA_OFFSET)
217#define CCM_PCCR_GPIO_MASK (1 << CCM_PCCR_GPIO_OFFSET)
218#define CCM_PCCR_GPT1_MASK (1 << CCM_PCCR_GPT1_OFFSET)
219#define CCM_PCCR_GPT2_MASK (1 << CCM_PCCR_GPT2_OFFSET)
220#define CCM_PCCR_GPT3_MASK (1 << CCM_PCCR_GPT3_OFFSET)
221#define CCM_PCCR_HCLK_BROM_MASK (1 << CCM_PCCR_HCLK_BROM_OFFSET)
222#define CCM_PCCR_HCLK_CSI_MASK (1 << CCM_PCCR_HCLK_CSI_OFFSET)
223#define CCM_PCCR_HCLK_DMA_MASK (1 << CCM_PCCR_HCLK_DMA_OFFSET)
224#define CCM_PCCR_HCLK_EMMA_MASK (1 << CCM_PCCR_HCLK_EMMA_OFFSET)
225#define CCM_PCCR_HCLK_LCDC_MASK (1 << CCM_PCCR_HCLK_LCDC_OFFSET)
226#define CCM_PCCR_HCLK_SLCDC_MASK (1 << CCM_PCCR_HCLK_SLCDC_OFFSET)
227#define CCM_PCCR_HCLK_USBOTG_MASK (1 << CCM_PCCR_HCLK_USBOTG_OFFSET)
228#define CCM_PCCR_I2C1_MASK (1 << CCM_PCCR_I2C1_OFFSET)
229#define CCM_PCCR_KPP_MASK (1 << CCM_PCCR_KPP_OFFSET)
230#define CCM_PCCR_LCDC_MASK (1 << CCM_PCCR_LCDC_OFFSET)
231#define CCM_PCCR_NFC_MASK (1 << CCM_PCCR_NFC_OFFSET)
232#define CCM_PCCR_OWIRE_MASK (1 << CCM_PCCR_OWIRE_OFFSET)
233#define CCM_PCCR_PERCLK4_MASK (1 << CCM_PCCR_PERCLK4_OFFSET)
234#define CCM_PCCR_PWM_MASK (1 << CCM_PCCR_PWM_OFFSET)
235#define CCM_PCCR_RTC_MASK (1 << CCM_PCCR_RTC_OFFSET)
236#define CCM_PCCR_SDHC1_MASK (1 << CCM_PCCR_SDHC1_OFFSET)
237#define CCM_PCCR_SDHC2_MASK (1 << CCM_PCCR_SDHC2_OFFSET)
238#define CCM_PCCR_SLCDC_MASK (1 << CCM_PCCR_SLCDC_OFFSET)
239#define CCM_PCCR_SSI1_BAUD_MASK (1 << CCM_PCCR_SSI1_BAUD_OFFSET)
240#define CCM_PCCR_SSI1_IPG_MASK (1 << CCM_PCCR_SSI1_IPG_OFFSET)
241#define CCM_PCCR_SSI2_BAUD_MASK (1 << CCM_PCCR_SSI2_BAUD_OFFSET)
242#define CCM_PCCR_SSI2_IPG_MASK (1 << CCM_PCCR_SSI2_IPG_OFFSET)
243#define CCM_PCCR_UART1_MASK (1 << CCM_PCCR_UART1_OFFSET)
244#define CCM_PCCR_UART2_MASK (1 << CCM_PCCR_UART2_OFFSET)
245#define CCM_PCCR_UART3_MASK (1 << CCM_PCCR_UART3_OFFSET)
246#define CCM_PCCR_UART4_MASK (1 << CCM_PCCR_UART4_OFFSET)
247#define CCM_PCCR_USBOTG_MASK (1 << CCM_PCCR_USBOTG_OFFSET)
248#define CCM_PCCR_WDT_MASK (1 << CCM_PCCR_WDT_OFFSET)
249
250#define CCM_CCSR_32KSR (1 << 15)
251
252#define CCM_CCSR_CLKMODE1 (1 << 9)
253#define CCM_CCSR_CLKMODE0 (1 << 8)
254
255#define CCM_CCSR_CLKOSEL_OFFSET 0
256#define CCM_CCSR_CLKOSEL_MASK 0x1f
257
258#define SYS_FMCR 0x14 /* Functional Muxing Control Reg */
259#define SYS_CHIP_ID 0x00 /* The offset of CHIP ID register */
Holger Schurigaa3b0a62009-01-26 16:34:54 +0100260
261static int _clk_enable(struct clk *clk)
262{
263 u32 reg;
264
265 reg = __raw_readl(clk->enable_reg);
266 reg |= 1 << clk->enable_shift;
267 __raw_writel(reg, clk->enable_reg);
268 return 0;
269}
270
271static void _clk_disable(struct clk *clk)
272{
273 u32 reg;
274
275 reg = __raw_readl(clk->enable_reg);
276 reg &= ~(1 << clk->enable_shift);
277 __raw_writel(reg, clk->enable_reg);
278}
279
Martin Fuzzeya0895162009-06-06 16:36:44 +0200280static unsigned long _clk_generic_round_rate(struct clk *clk,
281 unsigned long rate,
282 u32 max_divisor)
283{
284 u32 div;
285 unsigned long parent_rate;
286
287 parent_rate = clk_get_rate(clk->parent);
288
289 div = parent_rate / rate;
290 if (parent_rate % rate)
291 div++;
292
293 if (div > max_divisor)
294 div = max_divisor;
295
296 return parent_rate / div;
297}
298
Holger Schurigaa3b0a62009-01-26 16:34:54 +0100299static int _clk_spll_enable(struct clk *clk)
300{
301 u32 reg;
302
303 reg = __raw_readl(CCM_CSCR);
304 reg |= CCM_CSCR_SPEN;
305 __raw_writel(reg, CCM_CSCR);
306
307 while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0)
308 ;
309 return 0;
310}
311
312static void _clk_spll_disable(struct clk *clk)
313{
314 u32 reg;
315
316 reg = __raw_readl(CCM_CSCR);
317 reg &= ~CCM_CSCR_SPEN;
318 __raw_writel(reg, CCM_CSCR);
319}
320
321
322#define CSCR() (__raw_readl(CCM_CSCR))
323#define PCDR0() (__raw_readl(CCM_PCDR0))
324#define PCDR1() (__raw_readl(CCM_PCDR1))
325
326static unsigned long _clk_perclkx_round_rate(struct clk *clk,
327 unsigned long rate)
328{
Martin Fuzzeya0895162009-06-06 16:36:44 +0200329 return _clk_generic_round_rate(clk, rate, 64);
Holger Schurigaa3b0a62009-01-26 16:34:54 +0100330}
331
332static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
333{
334 u32 reg;
335 u32 div;
336 unsigned long parent_rate;
337
338 parent_rate = clk_get_rate(clk->parent);
339
340 if (clk->id < 0 || clk->id > 3)
341 return -EINVAL;
342
343 div = parent_rate / rate;
344 if (div > 64 || div < 1 || ((parent_rate / div) != rate))
345 return -EINVAL;
346 div--;
347
348 reg =
349 __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK <<
350 (clk->id << 3));
351 reg |= div << (clk->id << 3);
352 __raw_writel(reg, CCM_PCDR1);
353
354 return 0;
355}
356
357static unsigned long _clk_usb_recalc(struct clk *clk)
358{
359 unsigned long usb_pdf;
360 unsigned long parent_rate;
361
362 parent_rate = clk_get_rate(clk->parent);
363
364 usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET;
365
366 return parent_rate / (usb_pdf + 1U);
367}
368
Martin Fuzzeya0895162009-06-06 16:36:44 +0200369static unsigned long _clk_usb_round_rate(struct clk *clk,
370 unsigned long rate)
371{
372 return _clk_generic_round_rate(clk, rate, 8);
373}
374
375static int _clk_usb_set_rate(struct clk *clk, unsigned long rate)
376{
377 u32 reg;
378 u32 div;
379 unsigned long parent_rate;
380
381 parent_rate = clk_get_rate(clk->parent);
382
383 div = parent_rate / rate;
384 if (div > 8 || div < 1 || ((parent_rate / div) != rate))
385 return -EINVAL;
386 div--;
387
388 reg = CSCR() & ~CCM_CSCR_USB_MASK;
389 reg |= div << CCM_CSCR_USB_OFFSET;
390 __raw_writel(reg, CCM_CSCR);
391
392 return 0;
393}
394
Holger Schurigaa3b0a62009-01-26 16:34:54 +0100395static unsigned long _clk_ssix_recalc(struct clk *clk, unsigned long pdf)
396{
397 unsigned long parent_rate;
398
399 parent_rate = clk_get_rate(clk->parent);
400
401 pdf = (pdf < 2) ? 124UL : pdf; /* MX21 & MX27 TO1 */
402
403 return 2UL * parent_rate / pdf;
404}
405
406static unsigned long _clk_ssi1_recalc(struct clk *clk)
407{
408 return _clk_ssix_recalc(clk,
409 (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK)
410 >> CCM_PCDR0_SSI1BAUDDIV_OFFSET);
411}
412
413static unsigned long _clk_ssi2_recalc(struct clk *clk)
414{
415 return _clk_ssix_recalc(clk,
416 (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >>
417 CCM_PCDR0_SSI2BAUDDIV_OFFSET);
418}
419
420static unsigned long _clk_nfc_recalc(struct clk *clk)
421{
422 unsigned long nfc_pdf;
423 unsigned long parent_rate;
424
425 parent_rate = clk_get_rate(clk->parent);
426
427 nfc_pdf = (PCDR0() & CCM_PCDR0_NFCDIV_MASK)
428 >> CCM_PCDR0_NFCDIV_OFFSET;
429
430 return parent_rate / (nfc_pdf + 1);
431}
432
433static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
434{
435 return clk->parent->round_rate(clk->parent, rate);
436}
437
438static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
439{
440 return clk->parent->set_rate(clk->parent, rate);
441}
442
443static unsigned long external_high_reference; /* in Hz */
444
445static unsigned long get_high_reference_clock_rate(struct clk *clk)
446{
447 return external_high_reference;
448}
449
450/*
451 * the high frequency external clock reference
452 * Default case is 26MHz.
453 */
454static struct clk ckih_clk = {
455 .get_rate = get_high_reference_clock_rate,
456};
457
458static unsigned long external_low_reference; /* in Hz */
459
460static unsigned long get_low_reference_clock_rate(struct clk *clk)
461{
462 return external_low_reference;
463}
464
465/*
466 * the low frequency external clock reference
467 * Default case is 32.768kHz.
468 */
469static struct clk ckil_clk = {
470 .get_rate = get_low_reference_clock_rate,
471};
472
473
474static unsigned long _clk_fpm_recalc(struct clk *clk)
475{
476 return clk_get_rate(clk->parent) * 512;
477}
478
479/* Output of frequency pre multiplier */
480static struct clk fpm_clk = {
481 .parent = &ckil_clk,
482 .get_rate = _clk_fpm_recalc,
483};
484
485static unsigned long get_mpll_clk(struct clk *clk)
486{
487 uint32_t reg;
488 unsigned long ref_clk;
489 unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
490 unsigned long long temp;
491
492 ref_clk = clk_get_rate(clk->parent);
493
494 reg = __raw_readl(CCM_MPCTL0);
495 pdf = (reg & CCM_MPCTL0_PD_MASK) >> CCM_MPCTL0_PD_OFFSET;
496 mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET;
497 mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET;
498 mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET;
499
500 mfi = (mfi <= 5) ? 5 : mfi;
501 temp = 2LL * ref_clk * mfn;
502 do_div(temp, mfd + 1);
503 temp = 2LL * ref_clk * mfi + temp;
504 do_div(temp, pdf + 1);
505
506 return (unsigned long)temp;
507}
508
509static struct clk mpll_clk = {
510 .parent = &ckih_clk,
511 .get_rate = get_mpll_clk,
512};
513
514static unsigned long _clk_fclk_get_rate(struct clk *clk)
515{
516 unsigned long parent_rate;
517 u32 div;
518
519 div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET;
520 parent_rate = clk_get_rate(clk->parent);
521
522 return parent_rate / (div+1);
523}
524
525static struct clk fclk_clk = {
526 .parent = &mpll_clk,
527 .get_rate = _clk_fclk_get_rate
528};
529
530static unsigned long get_spll_clk(struct clk *clk)
531{
532 uint32_t reg;
533 unsigned long ref_clk;
534 unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
535 unsigned long long temp;
536
537 ref_clk = clk_get_rate(clk->parent);
538
539 reg = __raw_readl(CCM_SPCTL0);
540 pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET;
541 mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET;
542 mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET;
543 mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET;
544
545 mfi = (mfi <= 5) ? 5 : mfi;
546 temp = 2LL * ref_clk * mfn;
547 do_div(temp, mfd + 1);
548 temp = 2LL * ref_clk * mfi + temp;
549 do_div(temp, pdf + 1);
550
551 return (unsigned long)temp;
552}
553
554static struct clk spll_clk = {
555 .parent = &ckih_clk,
556 .get_rate = get_spll_clk,
557 .enable = _clk_spll_enable,
558 .disable = _clk_spll_disable,
559};
560
561static unsigned long get_hclk_clk(struct clk *clk)
562{
563 unsigned long rate;
564 unsigned long bclk_pdf;
565
566 bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK)
567 >> CCM_CSCR_BCLK_OFFSET;
568
569 rate = clk_get_rate(clk->parent);
570 return rate / (bclk_pdf + 1);
571}
572
573static struct clk hclk_clk = {
574 .parent = &fclk_clk,
575 .get_rate = get_hclk_clk,
576};
577
578static unsigned long get_ipg_clk(struct clk *clk)
579{
580 unsigned long rate;
581 unsigned long ipg_pdf;
582
583 ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET;
584
585 rate = clk_get_rate(clk->parent);
586 return rate / (ipg_pdf + 1);
587}
588
589static struct clk ipg_clk = {
590 .parent = &hclk_clk,
591 .get_rate = get_ipg_clk,
592};
593
594static unsigned long _clk_perclkx_recalc(struct clk *clk)
595{
596 unsigned long perclk_pdf;
597 unsigned long parent_rate;
598
599 parent_rate = clk_get_rate(clk->parent);
600
601 if (clk->id < 0 || clk->id > 3)
602 return 0;
603
604 perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK;
605
606 return parent_rate / (perclk_pdf + 1);
607}
608
609static struct clk per_clk[] = {
610 {
611 .id = 0,
612 .parent = &mpll_clk,
613 .get_rate = _clk_perclkx_recalc,
614 }, {
615 .id = 1,
616 .parent = &mpll_clk,
617 .get_rate = _clk_perclkx_recalc,
618 }, {
619 .id = 2,
620 .parent = &mpll_clk,
621 .round_rate = _clk_perclkx_round_rate,
622 .set_rate = _clk_perclkx_set_rate,
623 .get_rate = _clk_perclkx_recalc,
624 /* Enable/Disable done via lcd_clkc[1] */
625 }, {
626 .id = 3,
627 .parent = &mpll_clk,
628 .round_rate = _clk_perclkx_round_rate,
629 .set_rate = _clk_perclkx_set_rate,
630 .get_rate = _clk_perclkx_recalc,
631 /* Enable/Disable done via csi_clk[1] */
632 },
633};
634
635static struct clk uart_ipg_clk[];
636
637static struct clk uart_clk[] = {
638 {
639 .id = 0,
640 .parent = &per_clk[0],
641 .secondary = &uart_ipg_clk[0],
642 }, {
643 .id = 1,
644 .parent = &per_clk[0],
645 .secondary = &uart_ipg_clk[1],
646 }, {
647 .id = 2,
648 .parent = &per_clk[0],
649 .secondary = &uart_ipg_clk[2],
650 }, {
651 .id = 3,
652 .parent = &per_clk[0],
653 .secondary = &uart_ipg_clk[3],
654 },
655};
656
657static struct clk uart_ipg_clk[] = {
658 {
659 .id = 0,
660 .parent = &ipg_clk,
661 .enable = _clk_enable,
662 .enable_reg = CCM_PCCR_UART1_REG,
663 .enable_shift = CCM_PCCR_UART1_OFFSET,
664 .disable = _clk_disable,
665 }, {
666 .id = 1,
667 .parent = &ipg_clk,
668 .enable = _clk_enable,
669 .enable_reg = CCM_PCCR_UART2_REG,
670 .enable_shift = CCM_PCCR_UART2_OFFSET,
671 .disable = _clk_disable,
672 }, {
673 .id = 2,
674 .parent = &ipg_clk,
675 .enable = _clk_enable,
676 .enable_reg = CCM_PCCR_UART3_REG,
677 .enable_shift = CCM_PCCR_UART3_OFFSET,
678 .disable = _clk_disable,
679 }, {
680 .id = 3,
681 .parent = &ipg_clk,
682 .enable = _clk_enable,
683 .enable_reg = CCM_PCCR_UART4_REG,
684 .enable_shift = CCM_PCCR_UART4_OFFSET,
685 .disable = _clk_disable,
686 },
687};
688
689static struct clk gpt_ipg_clk[];
690
691static struct clk gpt_clk[] = {
692 {
693 .id = 0,
694 .parent = &per_clk[0],
695 .secondary = &gpt_ipg_clk[0],
696 }, {
697 .id = 1,
698 .parent = &per_clk[0],
699 .secondary = &gpt_ipg_clk[1],
700 }, {
701 .id = 2,
702 .parent = &per_clk[0],
703 .secondary = &gpt_ipg_clk[2],
704 },
705};
706
707static struct clk gpt_ipg_clk[] = {
708 {
709 .id = 0,
710 .parent = &ipg_clk,
711 .enable = _clk_enable,
712 .enable_reg = CCM_PCCR_GPT1_REG,
713 .enable_shift = CCM_PCCR_GPT1_OFFSET,
714 .disable = _clk_disable,
715 }, {
716 .id = 1,
717 .parent = &ipg_clk,
718 .enable = _clk_enable,
719 .enable_reg = CCM_PCCR_GPT2_REG,
720 .enable_shift = CCM_PCCR_GPT2_OFFSET,
721 .disable = _clk_disable,
722 }, {
723 .id = 2,
724 .parent = &ipg_clk,
725 .enable = _clk_enable,
726 .enable_reg = CCM_PCCR_GPT3_REG,
727 .enable_shift = CCM_PCCR_GPT3_OFFSET,
728 .disable = _clk_disable,
729 },
730};
731
732static struct clk pwm_clk[] = {
733 {
734 .parent = &per_clk[0],
735 .secondary = &pwm_clk[1],
736 }, {
737 .parent = &ipg_clk,
738 .enable = _clk_enable,
739 .enable_reg = CCM_PCCR_PWM_REG,
740 .enable_shift = CCM_PCCR_PWM_OFFSET,
741 .disable = _clk_disable,
742 },
743};
744
745static struct clk sdhc_ipg_clk[];
746
747static struct clk sdhc_clk[] = {
748 {
749 .id = 0,
750 .parent = &per_clk[1],
751 .secondary = &sdhc_ipg_clk[0],
752 }, {
753 .id = 1,
754 .parent = &per_clk[1],
755 .secondary = &sdhc_ipg_clk[1],
756 },
757};
758
759static struct clk sdhc_ipg_clk[] = {
760 {
761 .id = 0,
762 .parent = &ipg_clk,
763 .enable = _clk_enable,
764 .enable_reg = CCM_PCCR_SDHC1_REG,
765 .enable_shift = CCM_PCCR_SDHC1_OFFSET,
766 .disable = _clk_disable,
767 }, {
768 .id = 1,
769 .parent = &ipg_clk,
770 .enable = _clk_enable,
771 .enable_reg = CCM_PCCR_SDHC2_REG,
772 .enable_shift = CCM_PCCR_SDHC2_OFFSET,
773 .disable = _clk_disable,
774 },
775};
776
777static struct clk cspi_ipg_clk[];
778
779static struct clk cspi_clk[] = {
780 {
781 .id = 0,
782 .parent = &per_clk[1],
783 .secondary = &cspi_ipg_clk[0],
784 }, {
785 .id = 1,
786 .parent = &per_clk[1],
787 .secondary = &cspi_ipg_clk[1],
788 }, {
789 .id = 2,
790 .parent = &per_clk[1],
791 .secondary = &cspi_ipg_clk[2],
792 },
793};
794
795static struct clk cspi_ipg_clk[] = {
796 {
797 .id = 0,
798 .parent = &ipg_clk,
799 .enable = _clk_enable,
800 .enable_reg = CCM_PCCR_CSPI1_REG,
801 .enable_shift = CCM_PCCR_CSPI1_OFFSET,
802 .disable = _clk_disable,
803 }, {
804 .id = 1,
805 .parent = &ipg_clk,
806 .enable = _clk_enable,
807 .enable_reg = CCM_PCCR_CSPI2_REG,
808 .enable_shift = CCM_PCCR_CSPI2_OFFSET,
809 .disable = _clk_disable,
810 }, {
811 .id = 3,
812 .parent = &ipg_clk,
813 .enable = _clk_enable,
814 .enable_reg = CCM_PCCR_CSPI3_REG,
815 .enable_shift = CCM_PCCR_CSPI3_OFFSET,
816 .disable = _clk_disable,
817 },
818};
819
820static struct clk lcdc_clk[] = {
821 {
822 .parent = &per_clk[2],
823 .secondary = &lcdc_clk[1],
824 .round_rate = _clk_parent_round_rate,
825 .set_rate = _clk_parent_set_rate,
826 }, {
827 .parent = &ipg_clk,
828 .secondary = &lcdc_clk[2],
829 .enable = _clk_enable,
830 .enable_reg = CCM_PCCR_LCDC_REG,
831 .enable_shift = CCM_PCCR_LCDC_OFFSET,
832 .disable = _clk_disable,
833 }, {
834 .parent = &hclk_clk,
835 .enable = _clk_enable,
836 .enable_reg = CCM_PCCR_HCLK_LCDC_REG,
837 .enable_shift = CCM_PCCR_HCLK_LCDC_OFFSET,
838 .disable = _clk_disable,
839 },
840};
841
842static struct clk csi_clk[] = {
843 {
844 .parent = &per_clk[3],
845 .secondary = &csi_clk[1],
846 .round_rate = _clk_parent_round_rate,
847 .set_rate = _clk_parent_set_rate,
848 }, {
849 .parent = &hclk_clk,
850 .enable = _clk_enable,
851 .enable_reg = CCM_PCCR_HCLK_CSI_REG,
852 .enable_shift = CCM_PCCR_HCLK_CSI_OFFSET,
853 .disable = _clk_disable,
854 },
855};
856
857static struct clk usb_clk[] = {
858 {
859 .parent = &spll_clk,
Martin Fuzzeya0895162009-06-06 16:36:44 +0200860 .secondary = &usb_clk[1],
Holger Schurigaa3b0a62009-01-26 16:34:54 +0100861 .get_rate = _clk_usb_recalc,
862 .enable = _clk_enable,
863 .enable_reg = CCM_PCCR_USBOTG_REG,
864 .enable_shift = CCM_PCCR_USBOTG_OFFSET,
865 .disable = _clk_disable,
Martin Fuzzeya0895162009-06-06 16:36:44 +0200866 .round_rate = _clk_usb_round_rate,
867 .set_rate = _clk_usb_set_rate,
Holger Schurigaa3b0a62009-01-26 16:34:54 +0100868 }, {
869 .parent = &hclk_clk,
870 .enable = _clk_enable,
871 .enable_reg = CCM_PCCR_HCLK_USBOTG_REG,
872 .enable_shift = CCM_PCCR_HCLK_USBOTG_OFFSET,
873 .disable = _clk_disable,
874 }
875};
876
877static struct clk ssi_ipg_clk[];
878
879static struct clk ssi_clk[] = {
880 {
881 .id = 0,
882 .parent = &mpll_clk,
883 .secondary = &ssi_ipg_clk[0],
884 .get_rate = _clk_ssi1_recalc,
885 .enable = _clk_enable,
886 .enable_reg = CCM_PCCR_SSI1_BAUD_REG,
887 .enable_shift = CCM_PCCR_SSI1_BAUD_OFFSET,
888 .disable = _clk_disable,
889 }, {
890 .id = 1,
891 .parent = &mpll_clk,
892 .secondary = &ssi_ipg_clk[1],
893 .get_rate = _clk_ssi2_recalc,
894 .enable = _clk_enable,
895 .enable_reg = CCM_PCCR_SSI2_BAUD_REG,
896 .enable_shift = CCM_PCCR_SSI2_BAUD_OFFSET,
897 .disable = _clk_disable,
898 },
899};
900
901static struct clk ssi_ipg_clk[] = {
902 {
903 .id = 0,
904 .parent = &ipg_clk,
905 .enable = _clk_enable,
906 .enable_reg = CCM_PCCR_SSI1_REG,
907 .enable_shift = CCM_PCCR_SSI1_IPG_OFFSET,
908 .disable = _clk_disable,
909 }, {
910 .id = 1,
911 .parent = &ipg_clk,
912 .enable = _clk_enable,
913 .enable_reg = CCM_PCCR_SSI2_REG,
914 .enable_shift = CCM_PCCR_SSI2_IPG_OFFSET,
915 .disable = _clk_disable,
916 },
917};
918
919
920static struct clk nfc_clk = {
921 .parent = &fclk_clk,
922 .get_rate = _clk_nfc_recalc,
923 .enable = _clk_enable,
924 .enable_reg = CCM_PCCR_NFC_REG,
925 .enable_shift = CCM_PCCR_NFC_OFFSET,
926 .disable = _clk_disable,
927};
928
929static struct clk dma_clk[] = {
930 {
931 .parent = &hclk_clk,
932 .enable = _clk_enable,
933 .enable_reg = CCM_PCCR_DMA_REG,
934 .enable_shift = CCM_PCCR_DMA_OFFSET,
935 .disable = _clk_disable,
936 .secondary = &dma_clk[1],
937 }, {
938 .enable = _clk_enable,
939 .enable_reg = CCM_PCCR_HCLK_DMA_REG,
940 .enable_shift = CCM_PCCR_HCLK_DMA_OFFSET,
941 .disable = _clk_disable,
942 },
943};
944
945static struct clk brom_clk = {
946 .parent = &hclk_clk,
947 .enable = _clk_enable,
948 .enable_reg = CCM_PCCR_HCLK_BROM_REG,
949 .enable_shift = CCM_PCCR_HCLK_BROM_OFFSET,
950 .disable = _clk_disable,
951};
952
953static struct clk emma_clk[] = {
954 {
955 .parent = &hclk_clk,
956 .enable = _clk_enable,
957 .enable_reg = CCM_PCCR_EMMA_REG,
958 .enable_shift = CCM_PCCR_EMMA_OFFSET,
959 .disable = _clk_disable,
960 .secondary = &emma_clk[1],
961 }, {
962 .enable = _clk_enable,
963 .enable_reg = CCM_PCCR_HCLK_EMMA_REG,
964 .enable_shift = CCM_PCCR_HCLK_EMMA_OFFSET,
965 .disable = _clk_disable,
966 }
967};
968
969static struct clk slcdc_clk[] = {
970 {
971 .parent = &hclk_clk,
972 .enable = _clk_enable,
973 .enable_reg = CCM_PCCR_SLCDC_REG,
974 .enable_shift = CCM_PCCR_SLCDC_OFFSET,
975 .disable = _clk_disable,
976 .secondary = &slcdc_clk[1],
977 }, {
978 .enable = _clk_enable,
979 .enable_reg = CCM_PCCR_HCLK_SLCDC_REG,
980 .enable_shift = CCM_PCCR_HCLK_SLCDC_OFFSET,
981 .disable = _clk_disable,
982 }
983};
984
985static struct clk wdog_clk = {
986 .parent = &ipg_clk,
987 .enable = _clk_enable,
988 .enable_reg = CCM_PCCR_WDT_REG,
989 .enable_shift = CCM_PCCR_WDT_OFFSET,
990 .disable = _clk_disable,
991};
992
993static struct clk gpio_clk = {
994 .parent = &ipg_clk,
995 .enable = _clk_enable,
996 .enable_reg = CCM_PCCR_GPIO_REG,
997 .enable_shift = CCM_PCCR_GPIO_OFFSET,
998 .disable = _clk_disable,
999};
1000
1001static struct clk i2c_clk = {
1002 .id = 0,
1003 .parent = &ipg_clk,
1004 .enable = _clk_enable,
1005 .enable_reg = CCM_PCCR_I2C1_REG,
1006 .enable_shift = CCM_PCCR_I2C1_OFFSET,
1007 .disable = _clk_disable,
1008};
1009
1010static struct clk kpp_clk = {
1011 .parent = &ipg_clk,
1012 .enable = _clk_enable,
1013 .enable_reg = CCM_PCCR_KPP_REG,
1014 .enable_shift = CCM_PCCR_KPP_OFFSET,
1015 .disable = _clk_disable,
1016};
1017
1018static struct clk owire_clk = {
1019 .parent = &ipg_clk,
1020 .enable = _clk_enable,
1021 .enable_reg = CCM_PCCR_OWIRE_REG,
1022 .enable_shift = CCM_PCCR_OWIRE_OFFSET,
1023 .disable = _clk_disable,
1024};
1025
1026static struct clk rtc_clk = {
1027 .parent = &ipg_clk,
1028 .enable = _clk_enable,
1029 .enable_reg = CCM_PCCR_RTC_REG,
1030 .enable_shift = CCM_PCCR_RTC_OFFSET,
1031 .disable = _clk_disable,
1032};
1033
1034static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
1035{
Martin Fuzzeya0895162009-06-06 16:36:44 +02001036 return _clk_generic_round_rate(clk, rate, 8);
Holger Schurigaa3b0a62009-01-26 16:34:54 +01001037}
1038
1039static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
1040{
1041 u32 reg;
1042 u32 div;
1043 unsigned long parent_rate;
1044
1045 parent_rate = clk_get_rate(clk->parent);
1046
1047 div = parent_rate / rate;
1048
1049 if (div > 8 || div < 1 || ((parent_rate / div) != rate))
1050 return -EINVAL;
1051 div--;
1052
1053 reg = __raw_readl(CCM_PCDR0);
1054
1055 if (clk->parent == &usb_clk[0]) {
1056 reg &= ~CCM_PCDR0_48MDIV_MASK;
1057 reg |= div << CCM_PCDR0_48MDIV_OFFSET;
1058 }
1059 __raw_writel(reg, CCM_PCDR0);
1060
1061 return 0;
1062}
1063
1064static unsigned long _clk_clko_recalc(struct clk *clk)
1065{
1066 u32 div = 0;
1067 unsigned long parent_rate;
1068
1069 parent_rate = clk_get_rate(clk->parent);
1070
1071 if (clk->parent == &usb_clk[0]) /* 48M */
1072 div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_48MDIV_MASK
1073 >> CCM_PCDR0_48MDIV_OFFSET;
1074 div++;
1075
1076 return parent_rate / div;
1077}
1078
1079static struct clk clko_clk;
1080
1081static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
1082{
1083 u32 reg;
1084
1085 reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK;
1086
1087 if (parent == &ckil_clk)
1088 reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET;
1089 else if (parent == &fpm_clk)
1090 reg |= 1 << CCM_CCSR_CLKOSEL_OFFSET;
1091 else if (parent == &ckih_clk)
1092 reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET;
1093 else if (parent == mpll_clk.parent)
1094 reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET;
1095 else if (parent == spll_clk.parent)
1096 reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET;
1097 else if (parent == &mpll_clk)
1098 reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET;
1099 else if (parent == &spll_clk)
1100 reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET;
1101 else if (parent == &fclk_clk)
1102 reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET;
1103 else if (parent == &hclk_clk)
1104 reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET;
1105 else if (parent == &ipg_clk)
1106 reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET;
1107 else if (parent == &per_clk[0])
1108 reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET;
1109 else if (parent == &per_clk[1])
1110 reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET;
1111 else if (parent == &per_clk[2])
1112 reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET;
1113 else if (parent == &per_clk[3])
1114 reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET;
1115 else if (parent == &ssi_clk[0])
1116 reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET;
1117 else if (parent == &ssi_clk[1])
1118 reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET;
1119 else if (parent == &nfc_clk)
1120 reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET;
1121 else if (parent == &usb_clk[0])
1122 reg |= 0x14 << CCM_CCSR_CLKOSEL_OFFSET;
1123 else if (parent == &clko_clk)
1124 reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET;
1125 else
1126 return -EINVAL;
1127
1128 __raw_writel(reg, CCM_CCSR);
1129
1130 return 0;
1131}
1132
1133static struct clk clko_clk = {
1134 .get_rate = _clk_clko_recalc,
1135 .set_rate = _clk_clko_set_rate,
1136 .round_rate = _clk_clko_round_rate,
1137 .set_parent = _clk_clko_set_parent,
1138};
1139
1140
1141#define _REGISTER_CLOCK(d, n, c) \
1142 { \
1143 .dev_id = d, \
1144 .con_id = n, \
1145 .clk = &c, \
1146 },
Rabin Vincent6b4bfb82009-05-26 22:31:46 +05301147static struct clk_lookup lookups[] = {
Holger Schurigaa3b0a62009-01-26 16:34:54 +01001148/* It's unlikely that any driver wants one of them directly:
1149 _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
1150 _REGISTER_CLOCK(NULL, "ckil", ckil_clk)
1151 _REGISTER_CLOCK(NULL, "fpm", fpm_clk)
1152 _REGISTER_CLOCK(NULL, "mpll", mpll_clk)
1153 _REGISTER_CLOCK(NULL, "spll", spll_clk)
1154 _REGISTER_CLOCK(NULL, "fclk", fclk_clk)
1155 _REGISTER_CLOCK(NULL, "hclk", hclk_clk)
1156 _REGISTER_CLOCK(NULL, "ipg", ipg_clk)
1157*/
1158 _REGISTER_CLOCK(NULL, "perclk1", per_clk[0])
1159 _REGISTER_CLOCK(NULL, "perclk2", per_clk[1])
1160 _REGISTER_CLOCK(NULL, "perclk3", per_clk[2])
1161 _REGISTER_CLOCK(NULL, "perclk4", per_clk[3])
1162 _REGISTER_CLOCK(NULL, "clko", clko_clk)
1163 _REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0])
1164 _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[1])
1165 _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[2])
1166 _REGISTER_CLOCK("imx-uart.3", NULL, uart_clk[3])
1167 _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[0])
1168 _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[1])
1169 _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[2])
1170 _REGISTER_CLOCK(NULL, "pwm", pwm_clk[0])
1171 _REGISTER_CLOCK(NULL, "sdhc1", sdhc_clk[0])
1172 _REGISTER_CLOCK(NULL, "sdhc2", sdhc_clk[1])
1173 _REGISTER_CLOCK(NULL, "cspi1", cspi_clk[0])
1174 _REGISTER_CLOCK(NULL, "cspi2", cspi_clk[1])
1175 _REGISTER_CLOCK(NULL, "cspi3", cspi_clk[2])
Holger Schurig289a6892009-03-31 12:16:59 +02001176 _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk[0])
Holger Schurigaa3b0a62009-01-26 16:34:54 +01001177 _REGISTER_CLOCK(NULL, "csi", csi_clk[0])
Martin Fuzzeya0895162009-06-06 16:36:44 +02001178 _REGISTER_CLOCK("imx21-hcd.0", NULL, usb_clk[0])
Holger Schurigaa3b0a62009-01-26 16:34:54 +01001179 _REGISTER_CLOCK(NULL, "ssi1", ssi_clk[0])
1180 _REGISTER_CLOCK(NULL, "ssi2", ssi_clk[1])
Holger Schurig289a6892009-03-31 12:16:59 +02001181 _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
Holger Schurigaa3b0a62009-01-26 16:34:54 +01001182 _REGISTER_CLOCK(NULL, "dma", dma_clk[0])
1183 _REGISTER_CLOCK(NULL, "brom", brom_clk)
1184 _REGISTER_CLOCK(NULL, "emma", emma_clk[0])
1185 _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk[0])
Holger Schurig289a6892009-03-31 12:16:59 +02001186 _REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
Holger Schurigaa3b0a62009-01-26 16:34:54 +01001187 _REGISTER_CLOCK(NULL, "gpio", gpio_clk)
Holger Schurig1b3c9bf2009-04-01 13:58:21 +02001188 _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
Holger Schurigaa3b0a62009-01-26 16:34:54 +01001189 _REGISTER_CLOCK("mxc-keypad", NULL, kpp_clk)
1190 _REGISTER_CLOCK(NULL, "owire", owire_clk)
1191 _REGISTER_CLOCK(NULL, "rtc", rtc_clk)
1192};
1193
1194/*
1195 * must be called very early to get information about the
1196 * available clock rate when the timer framework starts
1197 */
1198int __init mx21_clocks_init(unsigned long lref, unsigned long href)
1199{
1200 int i;
1201 u32 cscr;
1202
1203 external_low_reference = lref;
1204 external_high_reference = href;
1205
1206 /* detect clock reference for both system PLL */
1207 cscr = CSCR();
1208 if (cscr & CCM_CSCR_MCU)
1209 mpll_clk.parent = &ckih_clk;
1210 else
1211 mpll_clk.parent = &fpm_clk;
1212
1213 if (cscr & CCM_CSCR_SP)
1214 spll_clk.parent = &ckih_clk;
1215 else
1216 spll_clk.parent = &fpm_clk;
1217
1218 for (i = 0; i < ARRAY_SIZE(lookups); i++)
1219 clkdev_add(&lookups[i]);
1220
1221 /* Turn off all clock gates */
1222 __raw_writel(0, CCM_PCCR0);
1223 __raw_writel(CCM_PCCR_GPT1_MASK, CCM_PCCR1);
1224
1225 /* This turns of the serial PLL as well */
1226 spll_clk.disable(&spll_clk);
1227
1228 /* This will propagate to all children and init all the clock rates. */
1229 clk_enable(&per_clk[0]);
1230 clk_enable(&gpio_clk);
1231
Uwe Kleine-König97adeda2009-11-12 22:56:29 +01001232#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
Holger Schurigaa3b0a62009-01-26 16:34:54 +01001233 clk_enable(&uart_clk[0]);
1234#endif
1235
Sascha Hauer8db5d1a2009-05-25 12:21:38 +02001236 mxc_timer_init(&gpt_clk[0], IO_ADDRESS(GPT1_BASE_ADDR), MXC_INT_GPT1);
Holger Schurigaa3b0a62009-01-26 16:34:54 +01001237 return 0;
1238}