uboot/arch/openrisc/cpu/cpu.c
<<
>>
Prefs
   1/*
   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();
 154        /* 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");
 159        /* not reached, __reset does not return */
 160        return 0;
 161}
 162