| /* |
| * (C) Copyright 2000 - 2002 |
| * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
| * |
| * See file CREDITS for list of people who contributed to this |
| * project. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of |
| * the License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
| * MA 02111-1307 USA |
| */ |
| |
| #include <config.h> |
| #include <mpc824x.h> |
| #include <common.h> |
| #include <command.h> |
| |
| DECLARE_GLOBAL_DATA_PTR; |
| |
| int checkcpu (void) |
| { |
| unsigned int pvr = get_pvr (); |
| unsigned int version = pvr >> 16; |
| unsigned char revision; |
| ulong clock = gd->cpu_clk; |
| char buf[32]; |
| |
| puts ("CPU: "); |
| |
| switch (version) { |
| case CPU_TYPE_8240: |
| puts ("MPC8240"); |
| break; |
| |
| case CPU_TYPE_8245: |
| puts ("MPC8245"); |
| break; |
| |
| default: |
| return -1; /*not valid for this source */ |
| } |
| |
| CONFIG_READ_BYTE (REVID, revision); |
| |
| if (revision) { |
| printf (" Revision %d.%d", |
| (revision & 0xf0) >> 4, |
| (revision & 0x0f)); |
| } else { |
| return -1; /* no valid CPU revision info */ |
| } |
| |
| printf (" at %s MHz:", strmhz (buf, clock)); |
| |
| printf (" %u kB I-Cache", checkicache () >> 10); |
| printf (" %u kB D-Cache", checkdcache () >> 10); |
| |
| puts ("\n"); |
| |
| return 0; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| /* L1 i-cache */ |
| |
| int checkicache (void) |
| { |
| /*TODO*/ |
| return 128 * 4 * 32; |
| }; |
| |
| /* ------------------------------------------------------------------------- */ |
| /* L1 d-cache */ |
| |
| int checkdcache (void) |
| { |
| /*TODO*/ |
| return 128 * 4 * 32; |
| |
| }; |
| |
| /*------------------------------------------------------------------- */ |
| |
| int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
| { |
| ulong msr, addr; |
| |
| /* Interrupts and MMU off */ |
| __asm__ ("mtspr 81, 0"); |
| |
| /* Interrupts and MMU off */ |
| __asm__ __volatile__ ("mfmsr %0":"=r" (msr):); |
| |
| msr &= ~0x1030; |
| __asm__ __volatile__ ("mtmsr %0"::"r" (msr)); |
| |
| /* |
| * Trying to execute the next instruction at a non-existing address |
| * should cause a machine check, resulting in reset |
| */ |
| #ifdef CFG_RESET_ADDRESS |
| addr = CFG_RESET_ADDRESS; |
| #else |
| /* |
| * note: when CFG_MONITOR_BASE points to a RAM address, |
| * CFG_MONITOR_BASE - sizeof (ulong) is usually a valid |
| * address. Better pick an address known to be invalid on |
| * your system and assign it to CFG_RESET_ADDRESS. |
| * "(ulong)-1" used to be a good choice for many systems... |
| */ |
| addr = CFG_MONITOR_BASE - sizeof (ulong); |
| #endif |
| ((void (*)(void)) addr) (); |
| return 1; |
| |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* |
| * Get timebase clock frequency (like cpu_clk in Hz) |
| * This is the sys_logic_clk (memory bus) divided by 4 |
| */ |
| unsigned long get_tbclk (void) |
| { |
| return ((get_bus_freq (0) + 2L) / 4L); |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* |
| * The MPC824x has an integrated PCI controller known as the MPC107. |
| * The following are MPC107 Bridge Controller and PCI Support functions |
| * |
| */ |
| |
| /* |
| * This procedure reads a 32-bit address MPC107 register, and returns |
| * a 32 bit value. It swaps the address to little endian before |
| * writing it to config address, and swaps the value to big endian |
| * before returning to the caller. |
| */ |
| unsigned int mpc824x_mpc107_getreg (unsigned int regNum) |
| { |
| unsigned int temp; |
| |
| /* swap the addr. to little endian */ |
| *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum); |
| temp = *(volatile unsigned int *) CHRP_REG_DATA; |
| return PCISWAP (temp); /* swap the data upon return */ |
| } |
| |
| /* |
| * This procedure writes a 32-bit address MPC107 register. It swaps |
| * the address to little endian before writing it to config address. |
| */ |
| |
| void mpc824x_mpc107_setreg (unsigned int regNum, unsigned int regVal) |
| { |
| /* swap the addr. to little endian */ |
| *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum); |
| *(volatile unsigned int *) CHRP_REG_DATA = PCISWAP (regVal); |
| return; |
| } |
| |
| |
| /* |
| * Write a byte (8 bits) to a memory location. |
| */ |
| void mpc824x_mpc107_write8 (unsigned int addr, unsigned char data) |
| { |
| *(unsigned char *) addr = data; |
| __asm__ ("sync"); |
| } |
| |
| /* |
| * Write a word (16 bits) to a memory location after the value |
| * has been byte swapped (big to little endian or vice versa) |
| */ |
| |
| void mpc824x_mpc107_write16 (unsigned int address, unsigned short data) |
| { |
| *(volatile unsigned short *) address = BYTE_SWAP_16_BIT (data); |
| __asm__ ("sync"); |
| } |
| |
| /* |
| * Write a long word (32 bits) to a memory location after the value |
| * has been byte swapped (big to little endian or vice versa) |
| */ |
| |
| void mpc824x_mpc107_write32 (unsigned int address, unsigned int data) |
| { |
| *(volatile unsigned int *) address = LONGSWAP (data); |
| __asm__ ("sync"); |
| } |
| |
| /* |
| * Read a byte (8 bits) from a memory location. |
| */ |
| unsigned char mpc824x_mpc107_read8 (unsigned int addr) |
| { |
| return *(volatile unsigned char *) addr; |
| } |
| |
| |
| /* |
| * Read a word (16 bits) from a memory location, and byte swap the |
| * value before returning to the caller. |
| */ |
| unsigned short mpc824x_mpc107_read16 (unsigned int address) |
| { |
| unsigned short retVal; |
| |
| retVal = BYTE_SWAP_16_BIT (*(unsigned short *) address); |
| return retVal; |
| } |
| |
| |
| /* |
| * Read a long word (32 bits) from a memory location, and byte |
| * swap the value before returning to the caller. |
| */ |
| unsigned int mpc824x_mpc107_read32 (unsigned int address) |
| { |
| unsigned int retVal; |
| |
| retVal = LONGSWAP (*(unsigned int *) address); |
| return (retVal); |
| } |
| |
| |
| /* |
| * Read a register in the Embedded Utilities Memory Block address |
| * space. |
| * Input: regNum - register number + utility base address. Example, |
| * the base address of EPIC is 0x40000, the register number |
| * being passed is 0x40000+the address of the target register. |
| * (See epic.h for register addresses). |
| * Output: The 32 bit little endian value of the register. |
| */ |
| |
| unsigned int mpc824x_eummbar_read (unsigned int regNum) |
| { |
| unsigned int temp; |
| |
| temp = *(volatile unsigned int *) (EUMBBAR_VAL + regNum); |
| temp = PCISWAP (temp); |
| return temp; |
| } |
| |
| |
| /* |
| * Write a value to a register in the Embedded Utilities Memory |
| * Block address space. |
| * Input: regNum - register number + utility base address. Example, |
| * the base address of EPIC is 0x40000, the register |
| * number is 0x40000+the address of the target register. |
| * (See epic.h for register addresses). |
| * regVal - value to be written to the register. |
| */ |
| |
| void mpc824x_eummbar_write (unsigned int regNum, unsigned int regVal) |
| { |
| *(volatile unsigned int *) (EUMBBAR_VAL + regNum) = PCISWAP (regVal); |
| return; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |