uboot/arch/powerpc/cpu/mpc824x/cpu.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000 - 2002
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   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 <config.h>
  25#include <mpc824x.h>
  26#include <common.h>
  27#include <command.h>
  28
  29DECLARE_GLOBAL_DATA_PTR;
  30
  31int checkcpu (void)
  32{
  33        unsigned int pvr = get_pvr ();
  34        unsigned int version = pvr >> 16;
  35        unsigned char revision;
  36        ulong clock = gd->cpu_clk;
  37        char buf[32];
  38
  39        puts ("CPU:   ");
  40
  41        switch (version) {
  42        case CPU_TYPE_8240:
  43                puts ("MPC8240");
  44                break;
  45
  46        case CPU_TYPE_8245:
  47                puts ("MPC8245");
  48                break;
  49
  50        default:
  51                return -1;              /*not valid for this source */
  52        }
  53
  54        CONFIG_READ_BYTE (REVID, revision);
  55
  56        if (revision) {
  57                printf (" Revision %d.%d",
  58                        (revision & 0xf0) >> 4,
  59                        (revision & 0x0f));
  60        } else {
  61                return -1;              /* no valid CPU revision info */
  62        }
  63
  64        printf (" at %s MHz:", strmhz (buf, clock));
  65
  66        printf (" %u kB I-Cache", checkicache () >> 10);
  67        printf (" %u kB D-Cache", checkdcache () >> 10);
  68
  69        puts ("\n");
  70
  71        return 0;
  72}
  73
  74/* ------------------------------------------------------------------------- */
  75/* L1 i-cache                                                                */
  76
  77int checkicache (void)
  78{
  79         /*TODO*/
  80         return 128 * 4 * 32;
  81};
  82
  83/* ------------------------------------------------------------------------- */
  84/* L1 d-cache                                                                */
  85
  86int checkdcache (void)
  87{
  88         /*TODO*/
  89         return 128 * 4 * 32;
  90
  91};
  92
  93/*------------------------------------------------------------------- */
  94
  95int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  96{
  97        ulong msr, addr;
  98
  99        /* Interrupts and MMU off */
 100        __asm__ ("mtspr    81, 0");
 101
 102        /* Interrupts and MMU off */
 103        __asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
 104
 105        msr &= ~0x1030;
 106        __asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
 107
 108        /*
 109         * Trying to execute the next instruction at a non-existing address
 110         * should cause a machine check, resulting in reset
 111         */
 112#ifdef CONFIG_SYS_RESET_ADDRESS
 113        addr = CONFIG_SYS_RESET_ADDRESS;
 114#else
 115        /*
 116         * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address,
 117         * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid
 118         * address. Better pick an address known to be invalid on
 119         * your system and assign it to CONFIG_SYS_RESET_ADDRESS.
 120         * "(ulong)-1" used to be a good choice for many systems...
 121         */
 122        addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
 123#endif
 124        ((void (*)(void)) addr) ();
 125        return 1;
 126
 127}
 128
 129/* ------------------------------------------------------------------------- */
 130
 131/*
 132 * Get timebase clock frequency (like cpu_clk in Hz)
 133 * This is the sys_logic_clk (memory bus) divided by 4
 134 */
 135unsigned long get_tbclk (void)
 136{
 137        return ((get_bus_freq (0) + 2L) / 4L);
 138}
 139
 140/* ------------------------------------------------------------------------- */
 141
 142/*
 143 * The MPC824x has an integrated PCI controller known as the MPC107.
 144 * The following are MPC107 Bridge Controller and PCI Support functions
 145 *
 146 */
 147
 148/*
 149 *  This procedure reads a 32-bit address MPC107 register, and returns
 150 *  a 32 bit value.  It swaps the address to little endian before
 151 *  writing it to config address, and swaps the value to big endian
 152 *  before returning to the caller.
 153 */
 154unsigned int mpc824x_mpc107_getreg (unsigned int regNum)
 155{
 156        unsigned int temp;
 157
 158        /* swap the addr. to little endian */
 159        *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
 160        temp = *(volatile unsigned int *) CHRP_REG_DATA;
 161        return PCISWAP (temp);          /* swap the data upon return */
 162}
 163
 164/*
 165 *  This procedure writes a 32-bit address MPC107 register.  It swaps
 166 *  the address to little endian before writing it to config address.
 167 */
 168
 169void mpc824x_mpc107_setreg (unsigned int regNum, unsigned int regVal)
 170{
 171        /* swap the addr. to little endian */
 172        *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
 173        *(volatile unsigned int *) CHRP_REG_DATA = PCISWAP (regVal);
 174        return;
 175}
 176
 177
 178/*
 179 *  Write a byte (8 bits) to a memory location.
 180 */
 181void mpc824x_mpc107_write8 (unsigned int addr, unsigned char data)
 182{
 183        *(unsigned char *) addr = data;
 184        __asm__ ("sync");
 185}
 186
 187/*
 188 *  Write a word (16 bits) to a memory location after the value
 189 *  has been byte swapped (big to little endian or vice versa)
 190 */
 191
 192void mpc824x_mpc107_write16 (unsigned int address, unsigned short data)
 193{
 194        *(volatile unsigned short *) address = BYTE_SWAP_16_BIT (data);
 195        __asm__ ("sync");
 196}
 197
 198/*
 199 *  Write a long word (32 bits) to a memory location after the value
 200 *  has been byte swapped (big to little endian or vice versa)
 201 */
 202
 203void mpc824x_mpc107_write32 (unsigned int address, unsigned int data)
 204{
 205        *(volatile unsigned int *) address = LONGSWAP (data);
 206        __asm__ ("sync");
 207}
 208
 209/*
 210 *  Read a byte (8 bits) from a memory location.
 211 */
 212unsigned char mpc824x_mpc107_read8 (unsigned int addr)
 213{
 214        return *(volatile unsigned char *) addr;
 215}
 216
 217
 218/*
 219 *  Read a word (16 bits) from a memory location, and byte swap the
 220 *  value before returning to the caller.
 221 */
 222unsigned short mpc824x_mpc107_read16 (unsigned int address)
 223{
 224        unsigned short retVal;
 225
 226        retVal = BYTE_SWAP_16_BIT (*(unsigned short *) address);
 227        return retVal;
 228}
 229
 230
 231/*
 232 *  Read a long word (32 bits) from a memory location, and byte
 233 *  swap the value before returning to the caller.
 234 */
 235unsigned int mpc824x_mpc107_read32 (unsigned int address)
 236{
 237        unsigned int retVal;
 238
 239        retVal = LONGSWAP (*(unsigned int *) address);
 240        return (retVal);
 241}
 242
 243
 244/*
 245 *  Read a register in the Embedded Utilities Memory Block address
 246 *  space.
 247 *  Input: regNum - register number + utility base address.  Example,
 248 *         the base address of EPIC is 0x40000, the register number
 249 *         being passed is 0x40000+the address of the target register.
 250 *         (See epic.h for register addresses).
 251 *  Output:  The 32 bit little endian value of the register.
 252 */
 253
 254unsigned int mpc824x_eummbar_read (unsigned int regNum)
 255{
 256        unsigned int temp;
 257
 258        temp = *(volatile unsigned int *) (EUMBBAR_VAL + regNum);
 259        temp = PCISWAP (temp);
 260        return temp;
 261}
 262
 263
 264/*
 265 *  Write a value to a register in the Embedded Utilities Memory
 266 *  Block address space.
 267 *  Input: regNum - register number + utility base address.  Example,
 268 *                  the base address of EPIC is 0x40000, the register
 269 *                  number is 0x40000+the address of the target register.
 270 *                  (See epic.h for register addresses).
 271 *         regVal - value to be written to the register.
 272 */
 273
 274void mpc824x_eummbar_write (unsigned int regNum, unsigned int regVal)
 275{
 276        *(volatile unsigned int *) (EUMBBAR_VAL + regNum) = PCISWAP (regVal);
 277        return;
 278}
 279
 280/* ------------------------------------------------------------------------- */
 281