]> git.sur5r.net Git - u-boot/blob - arch/powerpc/cpu/mpc8xx/cpu.c
powerpc: Remove unneccessary #ifdefs in reginfo
[u-boot] / arch / powerpc / cpu / mpc8xx / cpu.c
1 /*
2  * (C) Copyright 2000-2002
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 /*
9  * m8xx.c
10  *
11  * CPU specific code
12  *
13  * written or collected and sometimes rewritten by
14  * Magnus Damm <damm@bitsmart.com>
15  *
16  * minor modifications by
17  * Wolfgang Denk <wd@denx.de>
18  */
19
20 #include <common.h>
21 #include <watchdog.h>
22 #include <command.h>
23 #include <mpc8xx.h>
24 #include <commproc.h>
25 #include <netdev.h>
26 #include <asm/cache.h>
27 #include <linux/compiler.h>
28 #include <asm/io.h>
29
30 #if defined(CONFIG_OF_LIBFDT)
31 #include <libfdt.h>
32 #include <fdt_support.h>
33 #endif
34
35 DECLARE_GLOBAL_DATA_PTR;
36
37 static char *cpu_warning = "\n         " \
38         "*** Warning: CPU Core has Silicon Bugs -- Check the Errata ***";
39
40 static int check_CPU(long clock, uint pvr, uint immr)
41 {
42         char *id_str =
43         NULL;
44         immap_t __iomem *immap = (immap_t __iomem *)(immr & 0xFFFF0000);
45         uint k, m;
46         char buf[32];
47         char pre = 'X';
48         char *mid = "xx";
49         char *suf;
50
51         /* the highest 16 bits should be 0x0050 for a 860 */
52
53         if ((pvr >> 16) != 0x0050)
54                 return -1;
55
56         k = (immr << 16) |
57             in_be16(&immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)]);
58         m = 0;
59         suf = "";
60
61         /*
62          * Some boards use sockets so different CPUs can be used.
63          * We have to check chip version in run time.
64          */
65         switch (k) {
66                 /* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */
67         case 0x08010004:                /* Rev. A.0 */
68                 suf = "A";
69                 /* fall through */
70         case 0x08000003:                /* Rev. 0.3 */
71                 pre = 'M'; m = 1;
72                 if (id_str == NULL)
73                         id_str =
74                 "PC866x"; /* Unknown chip from MPC866 family */
75                 break;
76         case 0x09000000:
77                 pre = 'M'; mid = suf = ""; m = 1;
78                 if (id_str == NULL)
79                         id_str = "PC885"; /* 870/875/880/885 */
80                 break;
81
82         default:
83                 suf = NULL;
84                 break;
85         }
86
87         if (id_str == NULL)
88                 id_str = "PC86x";       /* Unknown 86x chip */
89         if (suf)
90                 printf("%c%s%sZPnn%s", pre, id_str, mid, suf);
91         else
92                 printf("unknown M%s (0x%08x)", id_str, k);
93
94         printf(" at %s MHz: ", strmhz(buf, clock));
95
96         print_size(checkicache(), " I-Cache ");
97         print_size(checkdcache(), " D-Cache");
98
99         /* do we have a FEC (860T/P or 852/859/866/885)? */
100
101         out_be32(&immap->im_cpm.cp_fec.fec_addr_low, 0x12345678);
102         if (in_be32(&immap->im_cpm.cp_fec.fec_addr_low) == 0x12345678)
103                 printf(" FEC present");
104
105         if (!m)
106                 puts(cpu_warning);
107
108         putc('\n');
109
110         return 0;
111 }
112
113 /* ------------------------------------------------------------------------- */
114
115 int checkcpu(void)
116 {
117         ulong clock = gd->cpu_clk;
118         uint immr = get_immr(0);        /* Return full IMMR contents */
119         uint pvr = get_pvr();
120
121         puts("CPU:   ");
122
123         return check_CPU(clock, pvr, immr);
124 }
125
126 /* ------------------------------------------------------------------------- */
127 /* L1 i-cache                                                                */
128
129 int checkicache(void)
130 {
131         immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
132         memctl8xx_t __iomem *memctl = &immap->im_memctl;
133         u32 cacheon = rd_ic_cst() & IDC_ENABLED;
134         /* probe in flash memoryarea */
135         u32 k = in_be32(&memctl->memc_br0) & ~0x00007fff;
136         u32 m;
137         u32 lines = -1;
138
139         wr_ic_cst(IDC_UNALL);
140         wr_ic_cst(IDC_INVALL);
141         wr_ic_cst(IDC_DISABLE);
142         __asm__ volatile ("isync");
143
144         while (!((m = rd_ic_cst()) & IDC_CERR2)) {
145                 wr_ic_adr(k);
146                 wr_ic_cst(IDC_LDLCK);
147                 __asm__ volatile ("isync");
148
149                 lines++;
150                 k += 0x10;      /* the number of bytes in a cacheline */
151         }
152
153         wr_ic_cst(IDC_UNALL);
154         wr_ic_cst(IDC_INVALL);
155
156         if (cacheon)
157                 wr_ic_cst(IDC_ENABLE);
158         else
159                 wr_ic_cst(IDC_DISABLE);
160
161         __asm__ volatile ("isync");
162
163         return lines << 4;
164 };
165
166 /* ------------------------------------------------------------------------- */
167 /* L1 d-cache                                                                */
168 /* call with cache disabled                                                  */
169
170 int checkdcache(void)
171 {
172         immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
173         memctl8xx_t __iomem *memctl = &immap->im_memctl;
174         u32 cacheon = rd_dc_cst() & IDC_ENABLED;
175         /* probe in flash memoryarea */
176         u32 k = in_be32(&memctl->memc_br0) & ~0x00007fff;
177         u32 m;
178         u32 lines = -1;
179
180         wr_dc_cst(IDC_UNALL);
181         wr_dc_cst(IDC_INVALL);
182         wr_dc_cst(IDC_DISABLE);
183
184         while (!((m = rd_dc_cst()) & IDC_CERR2)) {
185                 wr_dc_adr(k);
186                 wr_dc_cst(IDC_LDLCK);
187                 lines++;
188                 k += 0x10;      /* the number of bytes in a cacheline */
189         }
190
191         wr_dc_cst(IDC_UNALL);
192         wr_dc_cst(IDC_INVALL);
193
194         if (cacheon)
195                 wr_dc_cst(IDC_ENABLE);
196         else
197                 wr_dc_cst(IDC_DISABLE);
198
199         return lines << 4;
200 };
201
202 /* ------------------------------------------------------------------------- */
203
204 void upmconfig(uint upm, uint *table, uint size)
205 {
206         uint i;
207         uint addr = 0;
208         immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
209         memctl8xx_t __iomem *memctl = &immap->im_memctl;
210
211         for (i = 0; i < size; i++) {
212                 out_be32(&memctl->memc_mdr, table[i]);          /* (16-15) */
213                 out_be32(&memctl->memc_mcr, addr | upm);        /* (16-16) */
214                 addr++;
215         }
216 }
217
218 /* ------------------------------------------------------------------------- */
219
220 int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
221 {
222         ulong msr, addr;
223
224         immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
225
226         /* Checkstop Reset enable */
227         setbits_be32(&immap->im_clkrst.car_plprcr, PLPRCR_CSR);
228
229         /* Interrupts and MMU off */
230         __asm__ volatile ("mtspr    81, 0");
231         __asm__ volatile ("mfmsr    %0" : "=r" (msr));
232
233         msr &= ~0x1030;
234         __asm__ volatile ("mtmsr    %0" : : "r" (msr));
235
236         /*
237          * Trying to execute the next instruction at a non-existing address
238          * should cause a machine check, resulting in reset
239          */
240 #ifdef CONFIG_SYS_RESET_ADDRESS
241         addr = CONFIG_SYS_RESET_ADDRESS;
242 #else
243         /*
244          * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address,
245          * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid address.
246          * Better pick an address known to be invalid on your system and assign
247          * it to CONFIG_SYS_RESET_ADDRESS.
248          * "(ulong)-1" used to be a good choice for many systems...
249          */
250         addr = CONFIG_SYS_MONITOR_BASE - sizeof(ulong);
251 #endif
252         ((void (*)(void)) addr)();
253         return 1;
254 }
255
256 /* ------------------------------------------------------------------------- */
257
258 /*
259  * Get timebase clock frequency (like cpu_clk in Hz)
260  *
261  * See sections 14.2 and 14.6 of the User's Manual
262  */
263 unsigned long get_tbclk(void)
264 {
265         uint immr = get_immr(0);        /* Return full IMMR contents */
266         immap_t __iomem *immap = (immap_t __iomem *)(immr & 0xFFFF0000);
267         ulong oscclk, factor, pll;
268
269         if (in_be32(&immap->im_clkrst.car_sccr) & SCCR_TBS)
270                 return gd->cpu_clk / 16;
271
272         pll = in_be32(&immap->im_clkrst.car_plprcr);
273
274 #define PLPRCR_val(a) ((pll & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT)
275
276         /*
277          * For newer PQ1 chips (MPC866/87x/88x families), PLL multiplication
278          * factor is calculated as follows:
279          *
280          *                   MFN
281          *           MFI + -------
282          *                 MFD + 1
283          * factor =  -----------------
284          *           (PDF + 1) * 2^S
285          *
286          */
287         factor = (PLPRCR_val(MFI) + PLPRCR_val(MFN) / (PLPRCR_val(MFD) + 1)) /
288                  (PLPRCR_val(PDF) + 1) / (1 << PLPRCR_val(S));
289
290         oscclk = gd->cpu_clk / factor;
291
292         if ((in_be32(&immap->im_clkrst.car_sccr) & SCCR_RTSEL) == 0 ||
293             factor > 2)
294                 return oscclk / 4;
295
296         return oscclk / 16;
297 }
298
299 /* ------------------------------------------------------------------------- */
300
301 #if defined(CONFIG_WATCHDOG)
302 void watchdog_reset(void)
303 {
304         int re_enable = disable_interrupts();
305
306         reset_8xx_watchdog((immap_t __iomem *)CONFIG_SYS_IMMR);
307         if (re_enable)
308                 enable_interrupts();
309 }
310 #endif /* CONFIG_WATCHDOG */
311
312 #if defined(CONFIG_WATCHDOG)
313
314 void reset_8xx_watchdog(immap_t __iomem *immr)
315 {
316         /*
317          * All other boards use the MPC8xx Internal Watchdog
318          */
319         out_be16(&immr->im_siu_conf.sc_swsr, 0x556c);   /* write magic1 */
320         out_be16(&immr->im_siu_conf.sc_swsr, 0xaa39);   /* write magic2 */
321 }
322 #endif /* CONFIG_WATCHDOG */
323
324 /*
325  * Initializes on-chip ethernet controllers.
326  * to override, implement board_eth_init()
327  */
328 int cpu_eth_init(bd_t *bis)
329 {
330 #if defined(CONFIG_MPC8XX_FEC)
331         fec_initialize(bis);
332 #endif
333         return 0;
334 }