blob: 272656a361d7b154643f93c28a599d7c95b3480a [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 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
Stefan Kristiansson272f84b2011-11-26 19:04:51 +00006 */
7
8#include <common.h>
9#include <asm/system.h>
10#include <asm/openrisc_exc.h>
11
12static volatile int illegal_instruction;
13
14static void illegal_instruction_handler(void)
15{
16 ulong *epcr = (ulong *)mfspr(SPR_EPCR_BASE);
17
18 /* skip over the illegal instruction */
19 mtspr(SPR_EPCR_BASE, (ulong)(++epcr));
20 illegal_instruction = 1;
21}
22
23static void checkinstructions(void)
24{
25 ulong ra = 1, rb = 1, rc;
26
27 exception_install_handler(EXC_ILLEGAL_INSTR,
28 illegal_instruction_handler);
29
30 illegal_instruction = 0;
31 asm volatile("l.mul %0,%1,%2" : "=r" (rc) : "r" (ra), "r" (rb));
32 printf(" Hardware multiplier: %s\n",
33 illegal_instruction ? "no" : "yes");
34
35 illegal_instruction = 0;
36 asm volatile("l.div %0,%1,%2" : "=r" (rc) : "r" (ra), "r" (rb));
37 printf(" Hardware divider: %s\n",
38 illegal_instruction ? "no" : "yes");
39
40 exception_free_handler(EXC_ILLEGAL_INSTR);
41}
42
43int checkcpu(void)
44{
45 ulong upr = mfspr(SPR_UPR);
46 ulong vr = mfspr(SPR_VR);
47 ulong iccfgr = mfspr(SPR_ICCFGR);
48 ulong dccfgr = mfspr(SPR_DCCFGR);
49 ulong immucfgr = mfspr(SPR_IMMUCFGR);
50 ulong dmmucfgr = mfspr(SPR_DMMUCFGR);
51 ulong cpucfgr = mfspr(SPR_CPUCFGR);
52 uint ver = (vr & SPR_VR_VER) >> 24;
53 uint rev = vr & SPR_VR_REV;
54 uint block_size;
55 uint ways;
56 uint sets;
57
58 printf("CPU: OpenRISC-%x00 (rev %d) @ %d MHz\n",
59 ver, rev, (CONFIG_SYS_CLK_FREQ / 1000000));
60
61 if (upr & SPR_UPR_DCP) {
62 block_size = (dccfgr & SPR_DCCFGR_CBS) ? 32 : 16;
63 ways = 1 << (dccfgr & SPR_DCCFGR_NCW);
64 printf(" D-Cache: %d bytes, %d bytes/line, %d way(s)\n",
65 checkdcache(), block_size, ways);
66 } else {
67 printf(" D-Cache: no\n");
68 }
69
70 if (upr & SPR_UPR_ICP) {
71 block_size = (iccfgr & SPR_ICCFGR_CBS) ? 32 : 16;
72 ways = 1 << (iccfgr & SPR_ICCFGR_NCW);
73 printf(" I-Cache: %d bytes, %d bytes/line, %d way(s)\n",
74 checkicache(), block_size, ways);
75 } else {
76 printf(" I-Cache: no\n");
77 }
78
79 if (upr & SPR_UPR_DMP) {
80 sets = 1 << ((dmmucfgr & SPR_DMMUCFGR_NTS) >> 2);
81 ways = (dmmucfgr & SPR_DMMUCFGR_NTW) + 1;
82 printf(" DMMU: %d sets, %d way(s)\n",
83 sets, ways);
84 } else {
85 printf(" DMMU: no\n");
86 }
87
88 if (upr & SPR_UPR_IMP) {
89 sets = 1 << ((immucfgr & SPR_IMMUCFGR_NTS) >> 2);
90 ways = (immucfgr & SPR_IMMUCFGR_NTW) + 1;
91 printf(" IMMU: %d sets, %d way(s)\n",
92 sets, ways);
93 } else {
94 printf(" IMMU: no\n");
95 }
96
97 printf(" MAC unit: %s\n",
98 (upr & SPR_UPR_MP) ? "yes" : "no");
99 printf(" Debug unit: %s\n",
100 (upr & SPR_UPR_DUP) ? "yes" : "no");
101 printf(" Performance counters: %s\n",
102 (upr & SPR_UPR_PCUP) ? "yes" : "no");
103 printf(" Power management: %s\n",
104 (upr & SPR_UPR_PMP) ? "yes" : "no");
105 printf(" Interrupt controller: %s\n",
106 (upr & SPR_UPR_PICP) ? "yes" : "no");
107 printf(" Timer: %s\n",
108 (upr & SPR_UPR_TTP) ? "yes" : "no");
109 printf(" Custom unit(s): %s\n",
110 (upr & SPR_UPR_CUP) ? "yes" : "no");
111
112 printf(" Supported instructions:\n");
113 printf(" ORBIS32: %s\n",
114 (cpucfgr & SPR_CPUCFGR_OB32S) ? "yes" : "no");
115 printf(" ORBIS64: %s\n",
116 (cpucfgr & SPR_CPUCFGR_OB64S) ? "yes" : "no");
117 printf(" ORFPX32: %s\n",
118 (cpucfgr & SPR_CPUCFGR_OF32S) ? "yes" : "no");
119 printf(" ORFPX64: %s\n",
120 (cpucfgr & SPR_CPUCFGR_OF64S) ? "yes" : "no");
121
122 checkinstructions();
123
124 return 0;
125}
126
127int cleanup_before_linux(void)
128{
129 disable_interrupts();
130 return 0;
131}
132
133extern void __reset(void);
134
135int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
136{
137 disable_interrupts();
Julius Baxter3874a372012-05-05 12:32:11 +0000138 /* Code the jump to __reset here as the compiler is prone to
139 emitting a bad jump instruction if the function is in flash */
140 __asm__("l.movhi r1,hi(__reset); \
Wolfgang Denk93e14592013-10-04 17:43:24 +0200141 l.ori r1,r1,lo(__reset); \
142 l.jr r1");
Stefan Kristiansson272f84b2011-11-26 19:04:51 +0000143 /* not reached, __reset does not return */
144 return 0;
145}