Moved mpc8641hpcn_board_reset() out of cpu/ into board/.
[platform/kernel/u-boot.git] / cpu / mpc86xx / cpu.c
1 /*
2  * Copyright 2004 Freescale Semiconductor
3  * Jeff Brown (jeffrey@freescale.com)
4  * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24
25 #include <common.h>
26 #include <watchdog.h>
27 #include <command.h>
28 #include <asm/cache.h>
29 #include <mpc86xx.h>
30
31 #if defined(CONFIG_OF_FLAT_TREE)
32 #include <ft_build.h>
33 #endif
34
35 #ifdef CONFIG_MPC8641HPCN
36 extern void mpc8641_reset_board(cmd_tbl_t *cmdtp, int flag,
37                                 int argc, char *argv[]);
38 #endif
39
40
41 int checkcpu (void)
42 {
43         sys_info_t sysinfo;
44         uint pvr, svr;
45         uint ver;
46         uint major, minor;
47         uint lcrr;              /* local bus clock ratio register */
48         uint clkdiv;            /* clock divider portion of lcrr */
49
50         puts("Freescale PowerPC\n");
51
52         pvr = get_pvr();
53         ver = PVR_VER(pvr);
54         major = PVR_MAJ(pvr);
55         minor = PVR_MIN(pvr);
56
57         puts("CPU:\n");
58
59         printf("    Core: ");
60
61         switch (ver) {
62         case PVR_VER(PVR_86xx):
63             puts("E600");
64             break;
65         default:
66             puts("Unknown");
67             break;
68         }
69         printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr);
70
71         svr = get_svr();
72         ver = SVR_VER(svr);
73         major = SVR_MAJ(svr);
74         minor = SVR_MIN(svr);
75
76         puts("    System: ");
77         switch (ver) {
78         case SVR_8641:
79                 puts("8641");
80                 break;
81         case SVR_8641D:
82                 puts("8641D");
83                 break;
84         default:
85                 puts("Unknown");
86                 break;
87         }
88         printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
89
90         get_sys_info(&sysinfo);
91
92         puts("    Clocks: ");
93         printf("CPU:%4lu MHz, ", sysinfo.freqProcessor / 1000000);
94         printf("MPX:%4lu MHz, ", sysinfo.freqSystemBus / 1000000);
95         printf("DDR:%4lu MHz, ", sysinfo.freqSystemBus / 2000000);
96
97 #if defined(CFG_LBC_LCRR)
98         lcrr = CFG_LBC_LCRR;
99 #else
100         {
101             volatile immap_t *immap = (immap_t *)CFG_IMMR;
102             volatile ccsr_lbc_t *lbc= &immap->im_lbc;
103
104             lcrr = lbc->lcrr;
105         }
106 #endif
107         clkdiv = lcrr & 0x0f;
108         if (clkdiv == 2 || clkdiv == 4 || clkdiv == 8) {
109                 printf("LBC:%4lu MHz\n",
110                        sysinfo.freqSystemBus / 1000000 / clkdiv);
111         } else {
112                 printf("    LBC: unknown (lcrr: 0x%08x)\n", lcrr);
113         }
114
115         printf("    L2: ");
116         if (get_l2cr() & 0x80000000)
117                 printf("Enabled\n");
118         else
119                 printf("Disabled\n");
120
121         return 0;
122 }
123
124
125 static inline void
126 soft_restart(unsigned long addr)
127 {
128
129 #ifndef CONFIG_MPC8641HPCN
130
131         /* SRR0 has system reset vector, SRR1 has default MSR value */
132         /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
133
134         __asm__ __volatile__ ("mtspr    26, %0"         :: "r" (addr));
135         __asm__ __volatile__ ("li       4, (1 << 6)"    ::: "r4");
136         __asm__ __volatile__ ("mtspr    27, 4");
137         __asm__ __volatile__ ("rfi");
138
139 #else /* CONFIG_MPC8641HPCN */
140         out8(PIXIS_BASE+PIXIS_RST,0);
141 #endif /* !CONFIG_MPC8641HPCN */
142         while(1);       /* not reached */
143 }
144
145
146 /*
147  * No generic way to do board reset. Simply call soft_reset.
148  */
149 void
150 do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
151 {
152         ulong addr;
153
154 #ifdef CFG_RESET_ADDRESS
155         addr = CFG_RESET_ADDRESS;
156 #else
157         /*
158          * note: when CFG_MONITOR_BASE points to a RAM address,
159          * CFG_MONITOR_BASE - sizeof (ulong) is usually a valid
160          * address. Better pick an address known to be invalid on your
161          * system and assign it to CFG_RESET_ADDRESS.
162          */
163         addr = CFG_MONITOR_BASE - sizeof (ulong);
164 #endif
165
166 #ifndef CONFIG_MPC8641HPCN
167
168         /* flush and disable I/D cache */
169         __asm__ __volatile__ ("mfspr    3, 1008"        ::: "r3");
170         __asm__ __volatile__ ("ori      5, 5, 0xcc00"   ::: "r5");
171         __asm__ __volatile__ ("ori      4, 3, 0xc00"    ::: "r4");
172         __asm__ __volatile__ ("andc     5, 3, 5"        ::: "r5");
173         __asm__ __volatile__ ("sync");
174         __asm__ __volatile__ ("mtspr    1008, 4");
175         __asm__ __volatile__ ("isync");
176         __asm__ __volatile__ ("sync");
177         __asm__ __volatile__ ("mtspr    1008, 5");
178         __asm__ __volatile__ ("isync");
179         __asm__ __volatile__ ("sync");
180
181         soft_restart(addr);
182
183 #else /* CONFIG_MPC8641HPCN */
184
185         mpc8641_reset_board(cmdtp, flag, argc, argv);
186
187 #endif /* !CONFIG_MPC8641HPCN */
188
189         while(1);       /* not reached */
190 }
191
192
193 /*
194  * Get timebase clock frequency
195  */
196 unsigned long get_tbclk(void)
197 {
198         sys_info_t  sys_info;
199
200         get_sys_info(&sys_info);
201         return (sys_info.freqSystemBus + 3L) / 4L;
202 }
203
204
205 #if defined(CONFIG_WATCHDOG)
206 void
207 watchdog_reset(void)
208 {
209 }
210 #endif  /* CONFIG_WATCHDOG */
211
212
213 #if defined(CONFIG_DDR_ECC)
214 void dma_init(void)
215 {
216         volatile immap_t *immap = (immap_t *)CFG_IMMR;
217         volatile ccsr_dma_t *dma = &immap->im_dma;
218
219         dma->satr0 = 0x00040000;
220         dma->datr0 = 0x00040000;
221         asm("sync; isync");
222 }
223
224 uint dma_check(void)
225 {
226         volatile immap_t *immap = (immap_t *)CFG_IMMR;
227         volatile ccsr_dma_t *dma = &immap->im_dma;
228         volatile uint status = dma->sr0;
229
230         /* While the channel is busy, spin */
231         while((status & 4) == 4) {
232                 status = dma->sr0;
233         }
234
235         if (status != 0) {
236                 printf ("DMA Error: status = %x\n", status);
237         }
238         return status;
239 }
240
241 int dma_xfer(void *dest, uint count, void *src)
242 {
243         volatile immap_t *immap = (immap_t *)CFG_IMMR;
244         volatile ccsr_dma_t *dma = &immap->im_dma;
245
246         dma->dar0 = (uint) dest;
247         dma->sar0 = (uint) src;
248         dma->bcr0 = count;
249         dma->mr0 = 0xf000004;
250         asm("sync;isync");
251         dma->mr0 = 0xf000005;
252         asm("sync;isync");
253         return dma_check();
254 }
255
256 #endif  /* CONFIG_DDR_ECC */
257
258
259 #ifdef CONFIG_OF_FLAT_TREE
260 void ft_cpu_setup(void *blob, bd_t *bd)
261 {
262         u32 *p;
263         ulong clock;
264         int len;
265
266         clock = bd->bi_busfreq;
267         p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
268         if (p != NULL)
269                 *p = cpu_to_be32(clock);
270
271         p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len);
272         if (p != NULL)
273                 *p = cpu_to_be32(clock);
274
275         p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len);
276         if (p != NULL)
277                 *p = cpu_to_be32(clock);
278
279 #if defined(CONFIG_MPC86XX_TSEC1)
280         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/address", &len);
281         memcpy(p, bd->bi_enetaddr, 6);
282 #endif
283
284 #if defined(CONFIG_MPC86XX_TSEC2)
285         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/address", &len);
286         memcpy(p, bd->bi_enet1addr, 6);
287 #endif
288
289 #if defined(CONFIG_MPC86XX_TSEC3)
290         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@26000/address", &len);
291         memcpy(p, bd->bi_enet2addr, 6);
292 #endif
293
294 #if defined(CONFIG_MPC86XX_TSEC4)
295         p = ft_get_prop(blob, "/" OF_SOC "/ethernet@27000/address", &len);
296          memcpy(p, bd->bi_enet3addr, 6);
297 #endif
298
299 }
300 #endif