Merge with /home/hs/TQ/u-boot-dev
[oweals/u-boot.git] / cpu / mpc83xx / speed.c
1 /*
2  * (C) Copyright 2000-2002
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
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.
14  *
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.
19  *
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,
23  * MA 02111-1307 USA
24  */
25
26 #include <common.h>
27 #include <mpc83xx.h>
28 #include <asm/processor.h>
29
30 DECLARE_GLOBAL_DATA_PTR;
31
32 /* ----------------------------------------------------------------- */
33
34 typedef enum {
35         _unk,
36         _off,
37         _byp,
38         _x8,
39         _x4,
40         _x2,
41         _x1,
42         _1x,
43         _1_5x,
44         _2x,
45         _2_5x,
46         _3x
47 } mult_t;
48
49 typedef struct {
50         mult_t core_csb_ratio;
51         mult_t vco_divider;
52 } corecnf_t;
53
54 corecnf_t corecnf_tab[] = {
55         {_byp, _byp},           /* 0x00 */
56         {_byp, _byp},           /* 0x01 */
57         {_byp, _byp},           /* 0x02 */
58         {_byp, _byp},           /* 0x03 */
59         {_byp, _byp},           /* 0x04 */
60         {_byp, _byp},           /* 0x05 */
61         {_byp, _byp},           /* 0x06 */
62         {_byp, _byp},           /* 0x07 */
63         {_1x, _x2},             /* 0x08 */
64         {_1x, _x4},             /* 0x09 */
65         {_1x, _x8},             /* 0x0A */
66         {_1x, _x8},             /* 0x0B */
67         {_1_5x, _x2},           /* 0x0C */
68         {_1_5x, _x4},           /* 0x0D */
69         {_1_5x, _x8},           /* 0x0E */
70         {_1_5x, _x8},           /* 0x0F */
71         {_2x, _x2},             /* 0x10 */
72         {_2x, _x4},             /* 0x11 */
73         {_2x, _x8},             /* 0x12 */
74         {_2x, _x8},             /* 0x13 */
75         {_2_5x, _x2},           /* 0x14 */
76         {_2_5x, _x4},           /* 0x15 */
77         {_2_5x, _x8},           /* 0x16 */
78         {_2_5x, _x8},           /* 0x17 */
79         {_3x, _x2},             /* 0x18 */
80         {_3x, _x4},             /* 0x19 */
81         {_3x, _x8},             /* 0x1A */
82         {_3x, _x8},             /* 0x1B */
83 };
84
85 /* ----------------------------------------------------------------- */
86
87 /*
88  *
89  */
90 int get_clocks(void)
91 {
92         volatile immap_t *im = (immap_t *) CFG_IMMR;
93         u32 pci_sync_in;
94         u8 spmf;
95         u8 clkin_div;
96         u32 sccr;
97         u32 corecnf_tab_index;
98         u8 corepll;
99         u32 lcrr;
100
101         u32 csb_clk;
102 #if defined(CONFIG_MPC8349)
103         u32 tsec1_clk;
104         u32 tsec2_clk;
105         u32 usbmph_clk;
106         u32 usbdr_clk;
107 #endif
108         u32 core_clk;
109         u32 i2c1_clk;
110         u32 i2c2_clk;
111         u32 enc_clk;
112         u32 lbiu_clk;
113         u32 lclk_clk;
114         u32 ddr_clk;
115 #if defined (CONFIG_MPC8360)
116         u32 qepmf;
117         u32 qepdf;
118         u32 ddr_sec_clk;
119         u32 qe_clk;
120         u32 brg_clk;
121 #endif
122
123         if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im)
124                 return -1;
125
126         clkin_div = ((im->clk.spmr & SPMR_CKID) >> SPMR_CKID_SHIFT);
127
128         if (im->reset.rcwh & HRCWH_PCI_HOST) {
129 #if defined(CONFIG_83XX_CLKIN)
130                 pci_sync_in = CONFIG_83XX_CLKIN / (1 + clkin_div);
131 #else
132                 pci_sync_in = 0xDEADBEEF;
133 #endif
134         } else {
135 #if defined(CONFIG_83XX_PCICLK)
136                 pci_sync_in = CONFIG_83XX_PCICLK;
137 #else
138                 pci_sync_in = 0xDEADBEEF;
139 #endif
140         }
141
142         spmf = ((im->reset.rcwl & RCWL_SPMF) >> RCWL_SPMF_SHIFT);
143         csb_clk = pci_sync_in * (1 + clkin_div) * spmf;
144
145         sccr = im->clk.sccr;
146
147 #if defined(CONFIG_MPC8349)
148         switch ((sccr & SCCR_TSEC1CM) >> SCCR_TSEC1CM_SHIFT) {
149         case 0:
150                 tsec1_clk = 0;
151                 break;
152         case 1:
153                 tsec1_clk = csb_clk;
154                 break;
155         case 2:
156                 tsec1_clk = csb_clk / 2;
157                 break;
158         case 3:
159                 tsec1_clk = csb_clk / 3;
160                 break;
161         default:
162                 /* unkown SCCR_TSEC1CM value */
163                 return -4;
164         }
165
166         switch ((sccr & SCCR_TSEC2CM) >> SCCR_TSEC2CM_SHIFT) {
167         case 0:
168                 tsec2_clk = 0;
169                 break;
170         case 1:
171                 tsec2_clk = csb_clk;
172                 break;
173         case 2:
174                 tsec2_clk = csb_clk / 2;
175                 break;
176         case 3:
177                 tsec2_clk = csb_clk / 3;
178                 break;
179         default:
180                 /* unkown SCCR_TSEC2CM value */
181                 return -5;
182         }
183
184         i2c1_clk = tsec2_clk;
185
186         switch ((sccr & SCCR_USBMPHCM) >> SCCR_USBMPHCM_SHIFT) {
187         case 0:
188                 usbmph_clk = 0;
189                 break;
190         case 1:
191                 usbmph_clk = csb_clk;
192                 break;
193         case 2:
194                 usbmph_clk = csb_clk / 2;
195                 break;
196         case 3:
197                 usbmph_clk = csb_clk / 3;
198                 break;
199         default:
200                 /* unkown SCCR_USBMPHCM value */
201                 return -7;
202         }
203
204         switch ((sccr & SCCR_USBDRCM) >> SCCR_USBDRCM_SHIFT) {
205         case 0:
206                 usbdr_clk = 0;
207                 break;
208         case 1:
209                 usbdr_clk = csb_clk;
210                 break;
211         case 2:
212                 usbdr_clk = csb_clk / 2;
213                 break;
214         case 3:
215                 usbdr_clk = csb_clk / 3;
216                 break;
217         default:
218                 /* unkown SCCR_USBDRCM value */
219                 return -8;
220         }
221
222         if (usbmph_clk != 0 && usbdr_clk != 0 && usbmph_clk != usbdr_clk) {
223                 /* if USB MPH clock is not disabled and
224                  * USB DR clock is not disabled then
225                  * USB MPH & USB DR must have the same rate
226                  */
227                 return -9;
228         }
229 #endif
230 #if defined (CONFIG_MPC8360)
231         i2c1_clk = csb_clk;
232 #endif
233         i2c2_clk = csb_clk;     /* i2c-2 clk is equal to csb clk */
234
235         switch ((sccr & SCCR_ENCCM) >> SCCR_ENCCM_SHIFT) {
236         case 0:
237                 enc_clk = 0;
238                 break;
239         case 1:
240                 enc_clk = csb_clk;
241                 break;
242         case 2:
243                 enc_clk = csb_clk / 2;
244                 break;
245         case 3:
246                 enc_clk = csb_clk / 3;
247                 break;
248         default:
249                 /* unkown SCCR_ENCCM value */
250                 return -6;
251         }
252 #if defined(CONFIG_MPC8349) || defined(CONFIG_MPC8360)
253         lbiu_clk = csb_clk *
254                    (1 + ((im->reset.rcwl & RCWL_LBIUCM) >> RCWL_LBIUCM_SHIFT));
255 #else
256 #error Unknown MPC83xx chip
257 #endif
258         lcrr = (im->lbus.lcrr & LCRR_CLKDIV) >> LCRR_CLKDIV_SHIFT;
259         switch (lcrr) {
260         case 2:
261         case 4:
262         case 8:
263                 lclk_clk = lbiu_clk / lcrr;
264                 break;
265         default:
266                 /* unknown lcrr */
267                 return -10;
268         }
269 #if defined(CONFIG_MPC8349) || defined(CONFIG_MPC8360)
270         ddr_clk = csb_clk *
271                   (1 + ((im->reset.rcwl & RCWL_DDRCM) >> RCWL_DDRCM_SHIFT));
272         corepll = (im->reset.rcwl & RCWL_COREPLL) >> RCWL_COREPLL_SHIFT;
273 #if defined (CONFIG_MPC8360)
274         ddr_sec_clk = csb_clk * (1 +
275                        ((im->reset.rcwl & RCWL_LBIUCM) >> RCWL_LBIUCM_SHIFT));
276 #endif
277 #else
278 #error Unknown MPC83xx chip
279 #endif
280
281         corecnf_tab_index = ((corepll & 0x1F) << 2) | ((corepll & 0x60) >> 5);
282         if (corecnf_tab_index > (sizeof(corecnf_tab) / sizeof(corecnf_t))) {
283                 /* corecnf_tab_index is too high, possibly worng value */
284                 return -11;
285         }
286         switch (corecnf_tab[corecnf_tab_index].core_csb_ratio) {
287         case _byp:
288         case _x1:
289         case _1x:
290                 core_clk = csb_clk;
291                 break;
292         case _1_5x:
293                 core_clk = (3 * csb_clk) / 2;
294                 break;
295         case _2x:
296                 core_clk = 2 * csb_clk;
297                 break;
298         case _2_5x:
299                 core_clk = (5 * csb_clk) / 2;
300                 break;
301         case _3x:
302                 core_clk = 3 * csb_clk;
303                 break;
304         default:
305                 /* unkown core to csb ratio */
306                 return -12;
307         }
308
309 #if defined (CONFIG_MPC8360)
310         qepmf = (im->reset.rcwl & RCWL_CEPMF) >> RCWL_CEPMF_SHIFT;
311         qepdf = (im->reset.rcwl & RCWL_CEPDF) >> RCWL_CEPDF_SHIFT;
312         qe_clk = (pci_sync_in * qepmf) / (1 + qepdf);
313         brg_clk = qe_clk / 2;
314 #endif
315
316         gd->csb_clk = csb_clk;
317 #if defined(CONFIG_MPC8349)
318         gd->tsec1_clk = tsec1_clk;
319         gd->tsec2_clk = tsec2_clk;
320         gd->usbmph_clk = usbmph_clk;
321         gd->usbdr_clk = usbdr_clk;
322 #endif
323         gd->core_clk = core_clk;
324         gd->i2c1_clk = i2c1_clk;
325         gd->i2c2_clk = i2c2_clk;
326         gd->enc_clk = enc_clk;
327         gd->lbiu_clk = lbiu_clk;
328         gd->lclk_clk = lclk_clk;
329         gd->ddr_clk = ddr_clk;
330 #if defined (CONFIG_MPC8360)
331         gd->ddr_sec_clk = ddr_sec_clk;
332         gd->qe_clk = qe_clk;
333         gd->brg_clk = brg_clk;
334 #endif
335         gd->cpu_clk = gd->core_clk;
336         gd->bus_clk = gd->csb_clk;
337         return 0;
338
339 }
340
341 /********************************************
342  * get_bus_freq
343  * return system bus freq in Hz
344  *********************************************/
345 ulong get_bus_freq(ulong dummy)
346 {
347         return gd->csb_clk;
348 }
349
350 int print_clock_conf(void)
351 {
352         printf("Clock configuration:\n");
353         printf("  Coherent System Bus: %4d MHz\n", gd->csb_clk / 1000000);
354         printf("  Core:                %4d MHz\n", gd->core_clk / 1000000);
355 #if defined (CONFIG_MPC8360)
356         printf("  QE:                  %4d MHz\n", gd->qe_clk / 1000000);
357 #endif
358         printf("  Local Bus Controller:%4d MHz\n", gd->lbiu_clk / 1000000);
359         printf("  Local Bus:           %4d MHz\n", gd->lclk_clk / 1000000);
360         printf("  DDR:                 %4d MHz\n", gd->ddr_clk / 1000000);
361 #if defined (CONFIG_MPC8360)
362         printf("  DDR Secondary:       %4d MHz\n", gd->ddr_sec_clk / 1000000);
363 #endif
364         printf("  SEC:                 %4d MHz\n", gd->enc_clk / 1000000);
365         printf("  I2C1:                %4d MHz\n", gd->i2c1_clk / 1000000);
366         printf("  I2C2:                %4d MHz\n", gd->i2c2_clk / 1000000);
367 #if defined(CONFIG_MPC8349)
368         printf("  TSEC1:               %4d MHz\n", gd->tsec1_clk / 1000000);
369         printf("  TSEC2:               %4d MHz\n", gd->tsec2_clk / 1000000);
370         printf("  USB MPH:             %4d MHz\n", gd->usbmph_clk / 1000000);
371         printf("  USB DR:              %4d MHz\n", gd->usbdr_clk / 1000000);
372 #endif
373         return 0;
374 }