]>
Commit | Line | Data |
---|---|---|
1dc4da74 IY |
1 | /* |
2 | * Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org> | |
3 | * Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com> | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU General Public License as | |
7 | * published by the Free Software Foundation; either version 2 of | |
8 | * the License, or (at your option) any later version. | |
9 | * | |
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., 59 Temple Place, Suite 330, Boston, | |
18 | * MA 02111-1307 USA | |
19 | */ | |
20 | ||
21 | #include <common.h> | |
22 | #include <div64.h> | |
0b23fb36 | 23 | #include <netdev.h> |
1dc4da74 IY |
24 | #include <asm/io.h> |
25 | #include <asm/arch/imx-regs.h> | |
ba3dbaf2 IY |
26 | #ifdef CONFIG_MXC_MMC |
27 | #include <asm/arch/mxcmmc.h> | |
28 | #endif | |
1dc4da74 IY |
29 | |
30 | /* | |
31 | * get the system pll clock in Hz | |
32 | * | |
33 | * mfi + mfn / (mfd +1) | |
34 | * f = 2 * f_ref * -------------------- | |
35 | * pd + 1 | |
36 | */ | |
37 | unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref) | |
38 | { | |
39 | unsigned int mfi = (pll >> 10) & 0xf; | |
40 | unsigned int mfn = pll & 0x3ff; | |
41 | unsigned int mfd = (pll >> 16) & 0x3ff; | |
42 | unsigned int pd = (pll >> 26) & 0xf; | |
43 | ||
44 | mfi = mfi <= 5 ? 5 : mfi; | |
45 | ||
46 | return lldiv(2 * (u64)f_ref * (mfi * (mfd + 1) + mfn), | |
47 | (mfd + 1) * (pd + 1)); | |
48 | } | |
49 | ||
50 | static ulong clk_in_32k(void) | |
51 | { | |
52 | return 1024 * CONFIG_MX27_CLK32; | |
53 | } | |
54 | ||
55 | static ulong clk_in_26m(void) | |
56 | { | |
57 | struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; | |
58 | ||
59 | if (readl(&pll->cscr) & CSCR_OSC26M_DIV1P5) { | |
60 | /* divide by 1.5 */ | |
61 | return 26000000 * 2 / 3; | |
62 | } else { | |
63 | return 26000000; | |
64 | } | |
65 | } | |
66 | ||
67 | ulong imx_get_mpllclk(void) | |
68 | { | |
69 | struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; | |
70 | ulong cscr = readl(&pll->cscr); | |
71 | ulong fref; | |
72 | ||
73 | if (cscr & CSCR_MCU_SEL) | |
74 | fref = clk_in_26m(); | |
75 | else | |
76 | fref = clk_in_32k(); | |
77 | ||
78 | return imx_decode_pll(readl(&pll->mpctl0), fref); | |
79 | } | |
80 | ||
81 | ulong imx_get_armclk(void) | |
82 | { | |
83 | struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; | |
84 | ulong cscr = readl(&pll->cscr); | |
85 | ulong fref = imx_get_mpllclk(); | |
86 | ulong div; | |
87 | ||
88 | if (!(cscr & CSCR_ARM_SRC_MPLL)) | |
89 | fref = lldiv((fref * 2), 3); | |
90 | ||
91 | div = ((cscr >> 12) & 0x3) + 1; | |
92 | ||
93 | return lldiv(fref, div); | |
94 | } | |
95 | ||
96 | ulong imx_get_ahbclk(void) | |
97 | { | |
98 | struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; | |
99 | ulong cscr = readl(&pll->cscr); | |
100 | ulong fref = imx_get_mpllclk(); | |
101 | ulong div; | |
102 | ||
103 | div = ((cscr >> 8) & 0x3) + 1; | |
104 | ||
105 | return lldiv(fref * 2, 3 * div); | |
106 | } | |
107 | ||
108 | ulong imx_get_spllclk(void) | |
109 | { | |
110 | struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; | |
111 | ulong cscr = readl(&pll->cscr); | |
112 | ulong fref; | |
113 | ||
114 | if (cscr & CSCR_SP_SEL) | |
115 | fref = clk_in_26m(); | |
116 | else | |
117 | fref = clk_in_32k(); | |
118 | ||
119 | return imx_decode_pll(readl(&pll->spctl0), fref); | |
120 | } | |
121 | ||
122 | static ulong imx_decode_perclk(ulong div) | |
123 | { | |
124 | return lldiv((imx_get_mpllclk() * 2), (div * 3)); | |
125 | } | |
126 | ||
127 | ulong imx_get_perclk1(void) | |
128 | { | |
129 | struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; | |
130 | ||
131 | return imx_decode_perclk((readl(&pll->pcdr1) & 0x3f) + 1); | |
132 | } | |
133 | ||
134 | ulong imx_get_perclk2(void) | |
135 | { | |
136 | struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; | |
137 | ||
138 | return imx_decode_perclk(((readl(&pll->pcdr1) >> 8) & 0x3f) + 1); | |
139 | } | |
140 | ||
141 | ulong imx_get_perclk3(void) | |
142 | { | |
143 | struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; | |
144 | ||
145 | return imx_decode_perclk(((readl(&pll->pcdr1) >> 16) & 0x3f) + 1); | |
146 | } | |
147 | ||
148 | ulong imx_get_perclk4(void) | |
149 | { | |
150 | struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; | |
151 | ||
152 | return imx_decode_perclk(((readl(&pll->pcdr1) >> 24) & 0x3f) + 1); | |
153 | } | |
154 | ||
155 | #if defined(CONFIG_DISPLAY_CPUINFO) | |
156 | int print_cpuinfo (void) | |
157 | { | |
158 | char buf[32]; | |
159 | ||
160 | printf("CPU: Freescale i.MX27 at %s MHz\n\n", | |
161 | strmhz(buf, imx_get_mpllclk())); | |
162 | return 0; | |
163 | } | |
164 | #endif | |
165 | ||
0b23fb36 IY |
166 | int cpu_eth_init(bd_t *bis) |
167 | { | |
168 | #if defined(CONFIG_FEC_MXC) | |
cb17b92d JR |
169 | struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; |
170 | ||
171 | /* enable FEC clock */ | |
172 | writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1); | |
173 | writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0); | |
0b23fb36 IY |
174 | return fecmxc_initialize(bis); |
175 | #else | |
176 | return 0; | |
177 | #endif | |
178 | } | |
179 | ||
ba3dbaf2 IY |
180 | /* |
181 | * Initializes on-chip MMC controllers. | |
182 | * to override, implement board_mmc_init() | |
183 | */ | |
184 | int cpu_mmc_init(bd_t *bis) | |
185 | { | |
186 | #ifdef CONFIG_MXC_MMC | |
187 | return mxc_mmc_init(bis); | |
188 | #else | |
189 | return 0; | |
190 | #endif | |
191 | } | |
192 | ||
1dc4da74 IY |
193 | void imx_gpio_mode(int gpio_mode) |
194 | { | |
195 | struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE; | |
196 | unsigned int pin = gpio_mode & GPIO_PIN_MASK; | |
197 | unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; | |
198 | unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT; | |
199 | unsigned int aout = (gpio_mode & GPIO_AOUT_MASK) >> GPIO_AOUT_SHIFT; | |
200 | unsigned int bout = (gpio_mode & GPIO_BOUT_MASK) >> GPIO_BOUT_SHIFT; | |
201 | unsigned int tmp; | |
202 | ||
203 | /* Pullup enable */ | |
204 | if (gpio_mode & GPIO_PUEN) { | |
205 | writel(readl(®s->port[port].puen) | (1 << pin), | |
206 | ®s->port[port].puen); | |
207 | } else { | |
208 | writel(readl(®s->port[port].puen) & ~(1 << pin), | |
209 | ®s->port[port].puen); | |
210 | } | |
211 | ||
212 | /* Data direction */ | |
213 | if (gpio_mode & GPIO_OUT) { | |
214 | writel(readl(®s->port[port].ddir) | 1 << pin, | |
215 | ®s->port[port].ddir); | |
216 | } else { | |
217 | writel(readl(®s->port[port].ddir) & ~(1 << pin), | |
218 | ®s->port[port].ddir); | |
219 | } | |
220 | ||
221 | /* Primary / alternate function */ | |
222 | if (gpio_mode & GPIO_AF) { | |
223 | writel(readl(®s->port[port].gpr) | (1 << pin), | |
224 | ®s->port[port].gpr); | |
225 | } else { | |
226 | writel(readl(®s->port[port].gpr) & ~(1 << pin), | |
227 | ®s->port[port].gpr); | |
228 | } | |
229 | ||
230 | /* use as gpio? */ | |
231 | if (!(gpio_mode & (GPIO_PF | GPIO_AF))) { | |
232 | writel(readl(®s->port[port].gius) | (1 << pin), | |
233 | ®s->port[port].gius); | |
234 | } else { | |
235 | writel(readl(®s->port[port].gius) & ~(1 << pin), | |
236 | ®s->port[port].gius); | |
237 | } | |
238 | ||
239 | /* Output / input configuration */ | |
240 | if (pin < 16) { | |
241 | tmp = readl(®s->port[port].ocr1); | |
242 | tmp &= ~(3 << (pin * 2)); | |
243 | tmp |= (ocr << (pin * 2)); | |
244 | writel(tmp, ®s->port[port].ocr1); | |
245 | ||
246 | writel(readl(®s->port[port].iconfa1) & ~(3 << (pin * 2)), | |
247 | ®s->port[port].iconfa1); | |
248 | writel(readl(®s->port[port].iconfa1) | aout << (pin * 2), | |
249 | ®s->port[port].iconfa1); | |
250 | writel(readl(®s->port[port].iconfb1) & ~(3 << (pin * 2)), | |
251 | ®s->port[port].iconfb1); | |
252 | writel(readl(®s->port[port].iconfb1) | bout << (pin * 2), | |
253 | ®s->port[port].iconfb1); | |
254 | } else { | |
255 | pin -= 16; | |
256 | ||
257 | tmp = readl(®s->port[port].ocr2); | |
258 | tmp &= ~(3 << (pin * 2)); | |
259 | tmp |= (ocr << (pin * 2)); | |
260 | writel(tmp, ®s->port[port].ocr2); | |
261 | ||
262 | writel(readl(®s->port[port].iconfa2) & ~(3 << (pin * 2)), | |
263 | ®s->port[port].iconfa2); | |
264 | writel(readl(®s->port[port].iconfa2) | aout << (pin * 2), | |
265 | ®s->port[port].iconfa2); | |
266 | writel(readl(®s->port[port].iconfb2) & ~(3 << (pin * 2)), | |
267 | ®s->port[port].iconfb2); | |
268 | writel(readl(®s->port[port].iconfb2) | bout << (pin * 2), | |
269 | ®s->port[port].iconfb2); | |
270 | } | |
271 | } | |
10bc241d IY |
272 | |
273 | #ifdef CONFIG_MXC_UART | |
274 | void mx27_uart_init_pins(void) | |
275 | { | |
276 | int i; | |
277 | unsigned int mode[] = { | |
278 | PE12_PF_UART1_TXD, | |
279 | PE13_PF_UART1_RXD, | |
280 | }; | |
281 | ||
282 | for (i = 0; i < ARRAY_SIZE(mode); i++) | |
283 | imx_gpio_mode(mode[i]); | |
284 | ||
285 | } | |
286 | #endif /* CONFIG_MXC_UART */ | |
287 | ||
288 | #ifdef CONFIG_FEC_MXC | |
289 | void mx27_fec_init_pins(void) | |
290 | { | |
291 | int i; | |
292 | unsigned int mode[] = { | |
293 | PD0_AIN_FEC_TXD0, | |
294 | PD1_AIN_FEC_TXD1, | |
295 | PD2_AIN_FEC_TXD2, | |
296 | PD3_AIN_FEC_TXD3, | |
297 | PD4_AOUT_FEC_RX_ER, | |
298 | PD5_AOUT_FEC_RXD1, | |
299 | PD6_AOUT_FEC_RXD2, | |
300 | PD7_AOUT_FEC_RXD3, | |
301 | PD8_AF_FEC_MDIO, | |
302 | PD9_AIN_FEC_MDC | GPIO_PUEN, | |
303 | PD10_AOUT_FEC_CRS, | |
304 | PD11_AOUT_FEC_TX_CLK, | |
305 | PD12_AOUT_FEC_RXD0, | |
306 | PD13_AOUT_FEC_RX_DV, | |
307 | PD14_AOUT_FEC_CLR, | |
308 | PD15_AOUT_FEC_COL, | |
309 | PD16_AIN_FEC_TX_ER, | |
310 | PF23_AIN_FEC_TX_EN, | |
311 | }; | |
312 | ||
313 | for (i = 0; i < ARRAY_SIZE(mode); i++) | |
314 | imx_gpio_mode(mode[i]); | |
315 | } | |
316 | #endif /* CONFIG_FEC_MXC */ | |
317 | ||
318 | #ifdef CONFIG_MXC_MMC | |
319 | void mx27_sd2_init_pins(void) | |
320 | { | |
321 | int i; | |
322 | unsigned int mode[] = { | |
323 | PB4_PF_SD2_D0, | |
324 | PB5_PF_SD2_D1, | |
325 | PB6_PF_SD2_D2, | |
326 | PB7_PF_SD2_D3, | |
327 | PB8_PF_SD2_CMD, | |
328 | PB9_PF_SD2_CLK, | |
329 | }; | |
330 | ||
331 | for (i = 0; i < ARRAY_SIZE(mode); i++) | |
332 | imx_gpio_mode(mode[i]); | |
333 | ||
334 | } | |
335 | #endif /* CONFIG_MXC_MMC */ |