Add support for STX GP3SSA (stxssa) Board with 4 MiB flash.
[platform/kernel/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_MPC834X)
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 #if !defined(CONFIG_MPC832X)
111         u32 i2c2_clk;
112 #endif
113         u32 enc_clk;
114         u32 lbiu_clk;
115         u32 lclk_clk;
116         u32 ddr_clk;
117 #if defined(CONFIG_MPC8360)
118         u32 ddr_sec_clk;
119 #endif
120 #if defined(CONFIG_MPC8360) || defined(CONFIG_MPC832X)
121         u32 qepmf;
122         u32 qepdf;
123         u32 qe_clk;
124         u32 brg_clk;
125 #endif
126
127         if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im)
128                 return -1;
129
130         clkin_div = ((im->clk.spmr & SPMR_CKID) >> SPMR_CKID_SHIFT);
131
132         if (im->reset.rcwh & HRCWH_PCI_HOST) {
133 #if defined(CONFIG_83XX_CLKIN)
134                 pci_sync_in = CONFIG_83XX_CLKIN / (1 + clkin_div);
135 #else
136                 pci_sync_in = 0xDEADBEEF;
137 #endif
138         } else {
139 #if defined(CONFIG_83XX_PCICLK)
140                 pci_sync_in = CONFIG_83XX_PCICLK;
141 #else
142                 pci_sync_in = 0xDEADBEEF;
143 #endif
144         }
145
146         spmf = ((im->reset.rcwl & HRCWL_SPMF) >> HRCWL_SPMF_SHIFT);
147         csb_clk = pci_sync_in * (1 + clkin_div) * spmf;
148
149         sccr = im->clk.sccr;
150
151 #if defined(CONFIG_MPC834X)
152         switch ((sccr & SCCR_TSEC1CM) >> SCCR_TSEC1CM_SHIFT) {
153         case 0:
154                 tsec1_clk = 0;
155                 break;
156         case 1:
157                 tsec1_clk = csb_clk;
158                 break;
159         case 2:
160                 tsec1_clk = csb_clk / 2;
161                 break;
162         case 3:
163                 tsec1_clk = csb_clk / 3;
164                 break;
165         default:
166                 /* unkown SCCR_TSEC1CM value */
167                 return -4;
168         }
169
170         switch ((sccr & SCCR_TSEC2CM) >> SCCR_TSEC2CM_SHIFT) {
171         case 0:
172                 tsec2_clk = 0;
173                 break;
174         case 1:
175                 tsec2_clk = csb_clk;
176                 break;
177         case 2:
178                 tsec2_clk = csb_clk / 2;
179                 break;
180         case 3:
181                 tsec2_clk = csb_clk / 3;
182                 break;
183         default:
184                 /* unkown SCCR_TSEC2CM value */
185                 return -5;
186         }
187
188         i2c1_clk = tsec2_clk;
189
190         switch ((sccr & SCCR_USBMPHCM) >> SCCR_USBMPHCM_SHIFT) {
191         case 0:
192                 usbmph_clk = 0;
193                 break;
194         case 1:
195                 usbmph_clk = csb_clk;
196                 break;
197         case 2:
198                 usbmph_clk = csb_clk / 2;
199                 break;
200         case 3:
201                 usbmph_clk = csb_clk / 3;
202                 break;
203         default:
204                 /* unkown SCCR_USBMPHCM value */
205                 return -7;
206         }
207
208         switch ((sccr & SCCR_USBDRCM) >> SCCR_USBDRCM_SHIFT) {
209         case 0:
210                 usbdr_clk = 0;
211                 break;
212         case 1:
213                 usbdr_clk = csb_clk;
214                 break;
215         case 2:
216                 usbdr_clk = csb_clk / 2;
217                 break;
218         case 3:
219                 usbdr_clk = csb_clk / 3;
220                 break;
221         default:
222                 /* unkown SCCR_USBDRCM value */
223                 return -8;
224         }
225
226         if (usbmph_clk != 0 && usbdr_clk != 0 && usbmph_clk != usbdr_clk) {
227                 /* if USB MPH clock is not disabled and
228                  * USB DR clock is not disabled then
229                  * USB MPH & USB DR must have the same rate
230                  */
231                 return -9;
232         }
233 #endif
234 #if defined(CONFIG_MPC8360) || defined(CONFIG_MPC832X)
235         i2c1_clk = csb_clk;
236 #endif
237 #if !defined(CONFIG_MPC832X)
238         i2c2_clk = csb_clk;     /* i2c-2 clk is equal to csb clk */
239 #endif
240
241         switch ((sccr & SCCR_ENCCM) >> SCCR_ENCCM_SHIFT) {
242         case 0:
243                 enc_clk = 0;
244                 break;
245         case 1:
246                 enc_clk = csb_clk;
247                 break;
248         case 2:
249                 enc_clk = csb_clk / 2;
250                 break;
251         case 3:
252                 enc_clk = csb_clk / 3;
253                 break;
254         default:
255                 /* unkown SCCR_ENCCM value */
256                 return -6;
257         }
258
259         lbiu_clk = csb_clk *
260                    (1 + ((im->reset.rcwl & HRCWL_LBIUCM) >> HRCWL_LBIUCM_SHIFT));
261         lcrr = (im->lbus.lcrr & LCRR_CLKDIV) >> LCRR_CLKDIV_SHIFT;
262         switch (lcrr) {
263         case 2:
264         case 4:
265         case 8:
266                 lclk_clk = lbiu_clk / lcrr;
267                 break;
268         default:
269                 /* unknown lcrr */
270                 return -10;
271         }
272
273         ddr_clk = csb_clk *
274                   (1 + ((im->reset.rcwl & HRCWL_DDRCM) >> HRCWL_DDRCM_SHIFT));
275         corepll = (im->reset.rcwl & HRCWL_COREPLL) >> HRCWL_COREPLL_SHIFT;
276 #if defined(CONFIG_MPC8360)
277         ddr_sec_clk = csb_clk * (1 +
278                        ((im->reset.rcwl & HRCWL_LBIUCM) >> HRCWL_LBIUCM_SHIFT));
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) || defined(CONFIG_MPC832X)
310         qepmf = (im->reset.rcwl & HRCWL_CEPMF) >> HRCWL_CEPMF_SHIFT;
311         qepdf = (im->reset.rcwl & HRCWL_CEPDF) >> HRCWL_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_MPC834X)
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 #if !defined(CONFIG_MPC832X)
326         gd->i2c2_clk = i2c2_clk;
327 #endif
328         gd->enc_clk = enc_clk;
329         gd->lbiu_clk = lbiu_clk;
330         gd->lclk_clk = lclk_clk;
331         gd->ddr_clk = ddr_clk;
332 #if defined(CONFIG_MPC8360)
333         gd->ddr_sec_clk = ddr_sec_clk;
334 #endif
335 #if defined(CONFIG_MPC8360) || defined(CONFIG_MPC832X)
336         gd->qe_clk = qe_clk;
337         gd->brg_clk = brg_clk;
338 #endif
339         gd->cpu_clk = gd->core_clk;
340         gd->bus_clk = gd->csb_clk;
341         return 0;
342
343 }
344
345 /********************************************
346  * get_bus_freq
347  * return system bus freq in Hz
348  *********************************************/
349 ulong get_bus_freq(ulong dummy)
350 {
351         return gd->csb_clk;
352 }
353
354 int print_clock_conf(void)
355 {
356         printf("Clock configuration:\n");
357         printf("  Coherent System Bus: %4d MHz\n", gd->csb_clk / 1000000);
358         printf("  Core:                %4d MHz\n", gd->core_clk / 1000000);
359 #if defined(CONFIG_MPC8360) || defined(CONFIG_MPC832X)
360         printf("  QE:                  %4d MHz\n", gd->qe_clk / 1000000);
361         printf("  BRG:                 %4d MHz\n", gd->brg_clk / 1000000);
362 #endif
363         printf("  Local Bus Controller:%4d MHz\n", gd->lbiu_clk / 1000000);
364         printf("  Local Bus:           %4d MHz\n", gd->lclk_clk / 1000000);
365         printf("  DDR:                 %4d MHz\n", gd->ddr_clk / 1000000);
366 #if defined(CONFIG_MPC8360)
367         printf("  DDR Secondary:       %4d MHz\n", gd->ddr_sec_clk / 1000000);
368 #endif
369         printf("  SEC:                 %4d MHz\n", gd->enc_clk / 1000000);
370         printf("  I2C1:                %4d MHz\n", gd->i2c1_clk / 1000000);
371 #if !defined(CONFIG_MPC832X)
372         printf("  I2C2:                %4d MHz\n", gd->i2c2_clk / 1000000);
373 #endif
374 #if defined(CONFIG_MPC834X)
375         printf("  TSEC1:               %4d MHz\n", gd->tsec1_clk / 1000000);
376         printf("  TSEC2:               %4d MHz\n", gd->tsec2_clk / 1000000);
377         printf("  USB MPH:             %4d MHz\n", gd->usbmph_clk / 1000000);
378         printf("  USB DR:              %4d MHz\n", gd->usbdr_clk / 1000000);
379 #endif
380         return 0;
381 }