blob: 73ecc6f766ffd06d9adf3b82f485020efc60a59d [file] [log] [blame]
Stefan Kristiansson272f84b2011-11-26 19:04:51 +00001/*
2 * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
3 * (C) Copyright 2011, Julius Baxter <julius@opencores.org>
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#include <common.h>
25#include <asm/system.h>
26#include <asm/openrisc_exc.h>
27
28static volatile int illegal_instruction;
29
30static void illegal_instruction_handler(void)
31{
32 ulong *epcr = (ulong *)mfspr(SPR_EPCR_BASE);
33
34 /* skip over the illegal instruction */
35 mtspr(SPR_EPCR_BASE, (ulong)(++epcr));
36 illegal_instruction = 1;
37}
38
39static void checkinstructions(void)
40{
41 ulong ra = 1, rb = 1, rc;
42
43 exception_install_handler(EXC_ILLEGAL_INSTR,
44 illegal_instruction_handler);
45
46 illegal_instruction = 0;
47 asm volatile("l.mul %0,%1,%2" : "=r" (rc) : "r" (ra), "r" (rb));
48 printf(" Hardware multiplier: %s\n",
49 illegal_instruction ? "no" : "yes");
50
51 illegal_instruction = 0;
52 asm volatile("l.div %0,%1,%2" : "=r" (rc) : "r" (ra), "r" (rb));
53 printf(" Hardware divider: %s\n",
54 illegal_instruction ? "no" : "yes");
55
56 exception_free_handler(EXC_ILLEGAL_INSTR);
57}
58
59int checkcpu(void)
60{
61 ulong upr = mfspr(SPR_UPR);
62 ulong vr = mfspr(SPR_VR);
63 ulong iccfgr = mfspr(SPR_ICCFGR);
64 ulong dccfgr = mfspr(SPR_DCCFGR);
65 ulong immucfgr = mfspr(SPR_IMMUCFGR);
66 ulong dmmucfgr = mfspr(SPR_DMMUCFGR);
67 ulong cpucfgr = mfspr(SPR_CPUCFGR);
68 uint ver = (vr & SPR_VR_VER) >> 24;
69 uint rev = vr & SPR_VR_REV;
70 uint block_size;
71 uint ways;
72 uint sets;
73
74 printf("CPU: OpenRISC-%x00 (rev %d) @ %d MHz\n",
75 ver, rev, (CONFIG_SYS_CLK_FREQ / 1000000));
76
77 if (upr & SPR_UPR_DCP) {
78 block_size = (dccfgr & SPR_DCCFGR_CBS) ? 32 : 16;
79 ways = 1 << (dccfgr & SPR_DCCFGR_NCW);
80 printf(" D-Cache: %d bytes, %d bytes/line, %d way(s)\n",
81 checkdcache(), block_size, ways);
82 } else {
83 printf(" D-Cache: no\n");
84 }
85
86 if (upr & SPR_UPR_ICP) {
87 block_size = (iccfgr & SPR_ICCFGR_CBS) ? 32 : 16;
88 ways = 1 << (iccfgr & SPR_ICCFGR_NCW);
89 printf(" I-Cache: %d bytes, %d bytes/line, %d way(s)\n",
90 checkicache(), block_size, ways);
91 } else {
92 printf(" I-Cache: no\n");
93 }
94
95 if (upr & SPR_UPR_DMP) {
96 sets = 1 << ((dmmucfgr & SPR_DMMUCFGR_NTS) >> 2);
97 ways = (dmmucfgr & SPR_DMMUCFGR_NTW) + 1;
98 printf(" DMMU: %d sets, %d way(s)\n",
99 sets, ways);
100 } else {
101 printf(" DMMU: no\n");
102 }
103
104 if (upr & SPR_UPR_IMP) {
105 sets = 1 << ((immucfgr & SPR_IMMUCFGR_NTS) >> 2);
106 ways = (immucfgr & SPR_IMMUCFGR_NTW) + 1;
107 printf(" IMMU: %d sets, %d way(s)\n",
108 sets, ways);
109 } else {
110 printf(" IMMU: no\n");
111 }
112
113 printf(" MAC unit: %s\n",
114 (upr & SPR_UPR_MP) ? "yes" : "no");
115 printf(" Debug unit: %s\n",
116 (upr & SPR_UPR_DUP) ? "yes" : "no");
117 printf(" Performance counters: %s\n",
118 (upr & SPR_UPR_PCUP) ? "yes" : "no");
119 printf(" Power management: %s\n",
120 (upr & SPR_UPR_PMP) ? "yes" : "no");
121 printf(" Interrupt controller: %s\n",
122 (upr & SPR_UPR_PICP) ? "yes" : "no");
123 printf(" Timer: %s\n",
124 (upr & SPR_UPR_TTP) ? "yes" : "no");
125 printf(" Custom unit(s): %s\n",
126 (upr & SPR_UPR_CUP) ? "yes" : "no");
127
128 printf(" Supported instructions:\n");
129 printf(" ORBIS32: %s\n",
130 (cpucfgr & SPR_CPUCFGR_OB32S) ? "yes" : "no");
131 printf(" ORBIS64: %s\n",
132 (cpucfgr & SPR_CPUCFGR_OB64S) ? "yes" : "no");
133 printf(" ORFPX32: %s\n",
134 (cpucfgr & SPR_CPUCFGR_OF32S) ? "yes" : "no");
135 printf(" ORFPX64: %s\n",
136 (cpucfgr & SPR_CPUCFGR_OF64S) ? "yes" : "no");
137
138 checkinstructions();
139
140 return 0;
141}
142
143int cleanup_before_linux(void)
144{
145 disable_interrupts();
146 return 0;
147}
148
149extern void __reset(void);
150
151int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
152{
153 disable_interrupts();
Julius Baxter3874a372012-05-05 12:32:11 +0000154 /* Code the jump to __reset here as the compiler is prone to
155 emitting a bad jump instruction if the function is in flash */
156 __asm__("l.movhi r1,hi(__reset); \
157 l.ori r1,r1,lo(__reset); \
158 l.jr r1");
Stefan Kristiansson272f84b2011-11-26 19:04:51 +0000159 /* not reached, __reset does not return */
160 return 0;
161}