3 * Sascha Hauer, Pengutronix
5 * (C) Copyright 2009 Freescale Semiconductor, Inc.
7 * See file CREDITS for list of people who contributed to this
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 #include <asm/errno.h>
29 #include <asm/arch/imx-regs.h>
30 #include <asm/arch/crm_regs.h>
31 #include <asm/arch/clock.h>
40 struct mxc_pll_reg
*mxc_plls
[PLL_CLOCKS
] = {
41 [PLL1_CLOCK
] = (struct mxc_pll_reg
*)PLL1_BASE_ADDR
,
42 [PLL2_CLOCK
] = (struct mxc_pll_reg
*)PLL2_BASE_ADDR
,
43 [PLL3_CLOCK
] = (struct mxc_pll_reg
*)PLL3_BASE_ADDR
,
46 struct mxc_ccm_reg
*mxc_ccm
= (struct mxc_ccm_reg
*)MXC_CCM_BASE
;
49 * Calculate the frequency of this pll.
51 static u32
decode_pll(struct mxc_pll_reg
*pll
, u32 infreq
)
53 u32 mfi
, mfn
, mfd
, pd
;
55 mfn
= __raw_readl(&pll
->mfn
);
56 mfd
= __raw_readl(&pll
->mfd
) + 1;
57 mfi
= __raw_readl(&pll
->op
);
59 mfi
= (mfi
>> 4) & 0xF;
60 mfi
= (mfi
>= 5) ? mfi
: 5;
62 return ((4 * (infreq
/ 1000) * (mfi
* mfd
+ mfn
)) / (mfd
* pd
)) * 1000;
68 u32
get_mcu_main_clk(void)
72 reg
= (__raw_readl(&mxc_ccm
->cacrr
) & MXC_CCM_CACRR_ARM_PODF_MASK
) >>
73 MXC_CCM_CACRR_ARM_PODF_OFFSET
;
74 freq
= decode_pll(mxc_plls
[PLL1_CLOCK
], CONFIG_MX51_HCLK_FREQ
);
75 return freq
/ (reg
+ 1);
79 * Get the rate of peripheral's root clock.
81 static u32
get_periph_clk(void)
85 reg
= __raw_readl(&mxc_ccm
->cbcdr
);
86 if (!(reg
& MXC_CCM_CBCDR_PERIPH_CLK_SEL
))
87 return decode_pll(mxc_plls
[PLL2_CLOCK
], CONFIG_MX51_HCLK_FREQ
);
88 reg
= __raw_readl(&mxc_ccm
->cbcmr
);
89 switch ((reg
& MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK
) >>
90 MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET
) {
92 return decode_pll(mxc_plls
[PLL1_CLOCK
], CONFIG_MX51_HCLK_FREQ
);
94 return decode_pll(mxc_plls
[PLL3_CLOCK
], CONFIG_MX51_HCLK_FREQ
);
102 * Get the rate of ipg clock.
104 static u32
get_ipg_clk(void)
106 u32 ahb_podf
, ipg_podf
;
108 ahb_podf
= __raw_readl(&mxc_ccm
->cbcdr
);
109 ipg_podf
= (ahb_podf
& MXC_CCM_CBCDR_IPG_PODF_MASK
) >>
110 MXC_CCM_CBCDR_IPG_PODF_OFFSET
;
111 ahb_podf
= (ahb_podf
& MXC_CCM_CBCDR_AHB_PODF_MASK
) >>
112 MXC_CCM_CBCDR_AHB_PODF_OFFSET
;
113 return get_periph_clk() / ((ahb_podf
+ 1) * (ipg_podf
+ 1));
117 * Get the rate of ipg_per clock.
119 static u32
get_ipg_per_clk(void)
121 u32 pred1
, pred2
, podf
;
123 if (__raw_readl(&mxc_ccm
->cbcmr
) & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL
)
124 return get_ipg_clk();
125 /* Fixme: not handle what about lpm*/
126 podf
= __raw_readl(&mxc_ccm
->cbcdr
);
127 pred1
= (podf
& MXC_CCM_CBCDR_PERCLK_PRED1_MASK
) >>
128 MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET
;
129 pred2
= (podf
& MXC_CCM_CBCDR_PERCLK_PRED2_MASK
) >>
130 MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET
;
131 podf
= (podf
& MXC_CCM_CBCDR_PERCLK_PODF_MASK
) >>
132 MXC_CCM_CBCDR_PERCLK_PODF_OFFSET
;
134 return get_periph_clk() / ((pred1
+ 1) * (pred2
+ 1) * (podf
+ 1));
138 * Get the rate of uart clk.
140 static u32
get_uart_clk(void)
142 unsigned int freq
, reg
, pred
, podf
;
144 reg
= __raw_readl(&mxc_ccm
->cscmr1
);
145 switch ((reg
& MXC_CCM_CSCMR1_UART_CLK_SEL_MASK
) >>
146 MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET
) {
148 freq
= decode_pll(mxc_plls
[PLL1_CLOCK
],
149 CONFIG_MX51_HCLK_FREQ
);
152 freq
= decode_pll(mxc_plls
[PLL2_CLOCK
],
153 CONFIG_MX51_HCLK_FREQ
);
156 freq
= decode_pll(mxc_plls
[PLL3_CLOCK
],
157 CONFIG_MX51_HCLK_FREQ
);
163 reg
= __raw_readl(&mxc_ccm
->cscdr1
);
165 pred
= (reg
& MXC_CCM_CSCDR1_UART_CLK_PRED_MASK
) >>
166 MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET
;
168 podf
= (reg
& MXC_CCM_CSCDR1_UART_CLK_PODF_MASK
) >>
169 MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET
;
170 freq
/= (pred
+ 1) * (podf
+ 1);
176 * This function returns the low power audio clock.
181 u32 ccsr
= __raw_readl(&mxc_ccm
->ccsr
);
183 if (((ccsr
>> 9) & 1) == 0)
184 ret_val
= CONFIG_MX51_HCLK_FREQ
;
186 ret_val
= ((32768 * 1024));
192 * get cspi clock rate.
194 u32
imx_get_cspiclk(void)
196 u32 ret_val
= 0, pdf
, pre_pdf
, clk_sel
;
197 u32 cscmr1
= __raw_readl(&mxc_ccm
->cscmr1
);
198 u32 cscdr2
= __raw_readl(&mxc_ccm
->cscdr2
);
200 pre_pdf
= (cscdr2
& MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK
) \
201 >> MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET
;
202 pdf
= (cscdr2
& MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK
) \
203 >> MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET
;
204 clk_sel
= (cscmr1
& MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK
) \
205 >> MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET
;
209 ret_val
= decode_pll(mxc_plls
[PLL1_CLOCK
],
210 CONFIG_MX51_HCLK_FREQ
) /
211 ((pre_pdf
+ 1) * (pdf
+ 1));
214 ret_val
= decode_pll(mxc_plls
[PLL2_CLOCK
],
215 CONFIG_MX51_HCLK_FREQ
) /
216 ((pre_pdf
+ 1) * (pdf
+ 1));
219 ret_val
= decode_pll(mxc_plls
[PLL3_CLOCK
],
220 CONFIG_MX51_HCLK_FREQ
) /
221 ((pre_pdf
+ 1) * (pdf
+ 1));
224 ret_val
= get_lp_apm() / ((pre_pdf
+ 1) * (pdf
+ 1));
232 * The API of get mxc clockes.
234 unsigned int mxc_get_clock(enum mxc_clock clk
)
238 return get_mcu_main_clk();
242 return get_ipg_clk();
244 return get_ipg_per_clk();
246 return get_uart_clk();
248 return imx_get_cspiclk();
250 return decode_pll(mxc_plls
[PLL1_CLOCK
],
251 CONFIG_MX51_HCLK_FREQ
);
258 u32
imx_get_uartclk(void)
260 return get_uart_clk();
264 u32
imx_get_fecclk(void)
266 return mxc_get_clock(MXC_IPG_CLK
);
270 * Dump some core clockes.
272 int do_mx51_showclocks(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[])
276 freq
= decode_pll(mxc_plls
[PLL1_CLOCK
], CONFIG_MX51_HCLK_FREQ
);
277 printf("mx51 pll1: %dMHz\n", freq
/ 1000000);
278 freq
= decode_pll(mxc_plls
[PLL2_CLOCK
], CONFIG_MX51_HCLK_FREQ
);
279 printf("mx51 pll2: %dMHz\n", freq
/ 1000000);
280 freq
= decode_pll(mxc_plls
[PLL3_CLOCK
], CONFIG_MX51_HCLK_FREQ
);
281 printf("mx51 pll3: %dMHz\n", freq
/ 1000000);
282 printf("ipg clock : %dHz\n", mxc_get_clock(MXC_IPG_CLK
));
283 printf("ipg per clock : %dHz\n", mxc_get_clock(MXC_IPG_PERCLK
));
288 /***************************************************/
291 clockinfo
, CONFIG_SYS_MAXARGS
, 1, do_mx51_showclocks
,
292 "display mx51 clocks\n",