diff options
Diffstat (limited to 'arch/powerpc/cpu/mpc824x/cpu.c')
-rw-r--r-- | arch/powerpc/cpu/mpc824x/cpu.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/arch/powerpc/cpu/mpc824x/cpu.c b/arch/powerpc/cpu/mpc824x/cpu.c new file mode 100644 index 0000000..08f6a94 --- /dev/null +++ b/arch/powerpc/cpu/mpc824x/cpu.c @@ -0,0 +1,280 @@ +/* + * (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 CONFIG_SYS_RESET_ADDRESS + addr = CONFIG_SYS_RESET_ADDRESS; +#else + /* + * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address, + * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid + * address. Better pick an address known to be invalid on + * your system and assign it to CONFIG_SYS_RESET_ADDRESS. + * "(ulong)-1" used to be a good choice for many systems... + */ + addr = CONFIG_SYS_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; +} + +/* ------------------------------------------------------------------------- */ |