2 * Copyright (C) 2010 Freescale Semiconductor, Inc.
4 * See file CREDITS for list of people who contributed to this
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 #include <asm/errno.h>
25 #include <asm/arch/regs-clkctrl.h>
26 #include <asm/cache-cp15.h>
29 static u32 mx28_get_pclk(void)
31 const u32 xtal = 24, ref = 480;
32 u32 clkfrac, clkseq, clkctrl;
36 clkfrac = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_FRAC0);
37 clkseq = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_CLKSEQ);
38 clkctrl = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_CPU);
40 if (clkctrl & (BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN |
41 BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN)) {
42 /* No support of fractional divider calculation */
45 if (clkseq & BM_CLKCTRL_CLKSEQ_BYPASS_CPU) {
47 div = (clkctrl & BM_CLKCTRL_CPU_DIV_XTAL) >>
48 BP_CLKCTRL_CPU_DIV_XTAL;
52 frac = (clkfrac & BM_CLKCTRL_FRAC0_CPUFRAC) >>
53 BP_CLKCTRL_FRAC0_CPUFRAC;
54 div = (clkctrl & BM_CLKCTRL_CPU_DIV_CPU) >>
55 BP_CLKCTRL_CPU_DIV_CPU;
56 pclk = (ref * 18 / frac) / div;
63 static u32 mx28_get_hclk(void)
65 u32 clkctrl, div, hclk;
67 clkctrl = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_HBUS);
69 if (clkctrl & BM_CLKCTRL_HBUS_DIV_FRAC_EN) {
70 /* No support of fractional divider calculation */
73 div = (clkctrl & BM_CLKCTRL_HBUS_DIV) >>
75 hclk = mx28_get_pclk() / div;
81 static u32 mx28_get_emiclk(void)
83 const u32 xtal = 24, ref = 480;
84 u32 clkfrac, clkseq, clkctrl;
88 clkfrac = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_FRAC0);
89 clkseq = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_CLKSEQ);
90 clkctrl = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_EMI);
92 if (clkseq & BM_CLKCTRL_CLKSEQ_BYPASS_EMI) {
94 div = (clkctrl & BM_CLKCTRL_EMI_DIV_XTAL) >>
95 BP_CLKCTRL_EMI_DIV_XTAL;
99 frac = (clkfrac & BM_CLKCTRL_FRAC0_EMIFRAC) >>
100 BP_CLKCTRL_FRAC0_EMIFRAC;
101 div = (clkctrl & BM_CLKCTRL_EMI_DIV_EMI) >>
102 BP_CLKCTRL_EMI_DIV_EMI;
103 emiclk = (ref * 18 / frac) / div;
108 static inline void __enable_gpmi_clk(void)
110 /* Clear bypass bit*/
111 REG_SET(REGS_CLKCTRL_BASE, HW_CLKCTRL_CLKSEQ,
112 BM_CLKCTRL_CLKSEQ_BYPASS_GPMI);
113 /* Set gpmi clock to ref_gpmi/12 */
114 REG_WR(REGS_CLKCTRL_BASE, HW_CLKCTRL_GPMI,
115 REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_GPMI) &
116 (~(BM_CLKCTRL_GPMI_DIV)) &
117 (~(BM_CLKCTRL_GPMI_CLKGATE)) |
120 static u32 mx28_get_gpmiclk(void)
122 const u32 xtal = 24, ref = 480;
123 u32 clkfrac, clkseq, clkctrl;
126 /* Enable gpmi clock */
129 clkfrac = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_FRAC1);
130 clkseq = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_CLKSEQ);
131 clkctrl = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_GPMI);
133 if (clkseq & BM_CLKCTRL_CLKSEQ_BYPASS_GPMI) {
135 div = (clkctrl & BM_CLKCTRL_GPMI_DIV) >>
137 gpmiclk = xtal / div;
140 frac = (clkfrac & BM_CLKCTRL_FRAC1_GPMIFRAC) >>
141 BP_CLKCTRL_FRAC1_GPMIFRAC;
142 div = (clkctrl & BM_CLKCTRL_GPMI_DIV) >>
144 gpmiclk = (ref * 18 / frac) / div;
149 u32 mxc_get_clock(enum mxc_clock clk)
153 return mx28_get_pclk() * 1000000;
155 return mx28_get_gpmiclk() * 1000000;
158 return mx28_get_hclk() * 1000000;
164 #if defined(CONFIG_ARCH_CPU_INIT)
165 int arch_cpu_init(void)
174 #if defined(CONFIG_DISPLAY_CPUINFO)
175 int print_cpuinfo(void)
177 printf("Freescale i.MX28 family\n");
178 printf("CPU: %d MHz\n", mx28_get_pclk());
179 printf("BUS: %d MHz\n", mx28_get_hclk());
180 printf("EMI: %d MHz\n", mx28_get_emiclk());
181 printf("GPMI: %d MHz\n", mx28_get_gpmiclk());
187 * Initializes on-chip ethernet controllers.
189 int cpu_eth_init(bd_t *bis)
192 #if defined(CONFIG_MXC_FEC)
193 rc = mxc_fec_initialize(bis);
195 /* Turn on ENET clocks */
196 REG_WR(REGS_CLKCTRL_BASE, HW_CLKCTRL_ENET,
197 REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_ENET) &
198 ~(BM_CLKCTRL_ENET_SLEEP | BM_CLKCTRL_ENET_DISABLE));
200 /* Set up ENET PLL for 50 MHz */
201 REG_SET(REGS_CLKCTRL_BASE, HW_CLKCTRL_PLL2CTRL0,
202 BM_CLKCTRL_PLL2CTRL0_POWER); /* Power on ENET PLL */
203 udelay(10); /* Wait 10 us */
204 REG_CLR(REGS_CLKCTRL_BASE, HW_CLKCTRL_PLL2CTRL0,
205 BM_CLKCTRL_PLL2CTRL0_CLKGATE); /* Gate on ENET PLL */
206 REG_WR(REGS_CLKCTRL_BASE, HW_CLKCTRL_ENET,
207 REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_ENET) |
208 BM_CLKCTRL_ENET_CLK_OUT_EN); /* Enable pad output */
210 /* Board level init */