Add mpc7448hpc2 (mpc7448 + tsi108) board associated code support.

mpc7448hpc2 board support high level code:tsi108 init + mpc7448hpc2.

Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
This commit is contained in:
roy zang 2006-11-02 18:59:15 +08:00 committed by Zang Tiefei
parent 27801b8ab1
commit 87c4db0969
2 changed files with 1151 additions and 0 deletions

View File

@ -0,0 +1,489 @@
/*
* (C) Copyright 2005 Freescale Semiconductor, Inc.
*
* Roy Zang <tie-fei.zang@freescale.com>
*
* 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
*
* modifications for the Tsi108 Emul Board by avb@Tundra
*/
/*
* board support/init functions for the
* Freescale MPC7448 HPC2 (High-Performance Computing 2 Platform).
*/
#include <common.h>
#include <74xx_7xx.h>
#if defined(CONFIG_OF_FLAT_TREE)
#include <ft_build.h>
extern void ft_cpu_setup(void *blob, bd_t *bd);
#endif
#undef DEBUG
extern void flush_data_cache(void);
extern void invalidate_l1_instruction_cache(void);
extern void tsi108_init_f(void);
int display_mem_map(void);
void after_reloc(ulong dest_addr)
{
DECLARE_GLOBAL_DATA_PTR;
/*
* Jump to the main U-Boot board init code
*/
board_init_r((gd_t *) gd, dest_addr);
/* NOTREACHED */
}
/*
* Check Board Identity:
*
* report board type
*/
int checkboard(void)
{
int l_type = 0;
printf("BOARD: %s\n", CFG_BOARD_NAME);
return (l_type);
}
/*
* Read Processor ID:
*
* report calling processor number
*/
int read_pid(void)
{
return 0; /* we are on single CPU platform for a while */
}
long int dram_size(int board_type)
{
return 0x20000000; /* 256M bytes */
}
long int initdram(int board_type)
{
return dram_size(board_type);
}
/* DRAM check routines copied from gw8260 */
#if defined (CFG_DRAM_TEST)
/*********************************************************************/
/* NAME: move64() - moves a double word (64-bit) */
/* */
/* DESCRIPTION: */
/* this function performs a double word move from the data at */
/* the source pointer to the location at the destination pointer. */
/* */
/* INPUTS: */
/* unsigned long long *src - pointer to data to move */
/* */
/* OUTPUTS: */
/* unsigned long long *dest - pointer to locate to move data */
/* */
/* RETURNS: */
/* None */
/* */
/* RESTRICTIONS/LIMITATIONS: */
/* May cloober fr0. */
/* */
/*********************************************************************/
static void move64(unsigned long long *src, unsigned long long *dest)
{
asm("lfd 0, 0(3)\n\t" /* fpr0 = *scr */
"stfd 0, 0(4)" /* *dest = fpr0 */
: : :"fr0"); /* Clobbers fr0 */
return;
}
#if defined (CFG_DRAM_TEST_DATA)
unsigned long long pattern[] = {
0xaaaaaaaaaaaaaaaaULL,
0xccccccccccccccccULL,
0xf0f0f0f0f0f0f0f0ULL,
0xff00ff00ff00ff00ULL,
0xffff0000ffff0000ULL,
0xffffffff00000000ULL,
0x00000000ffffffffULL,
0x0000ffff0000ffffULL,
0x00ff00ff00ff00ffULL,
0x0f0f0f0f0f0f0f0fULL,
0x3333333333333333ULL,
0x5555555555555555ULL
};
/*********************************************************************/
/* NAME: mem_test_data() - test data lines for shorts and opens */
/* */
/* DESCRIPTION: */
/* Tests data lines for shorts and opens by forcing adjacent data */
/* to opposite states. Because the data lines could be routed in */
/* an arbitrary manner the must ensure test patterns ensure that */
/* every case is tested. By using the following series of binary */
/* patterns every combination of adjacent bits is test regardless */
/* of routing. */
/* */
/* ...101010101010101010101010 */
/* ...110011001100110011001100 */
/* ...111100001111000011110000 */
/* ...111111110000000011111111 */
/* */
/* Carrying this out, gives us six hex patterns as follows: */
/* */
/* 0xaaaaaaaaaaaaaaaa */
/* 0xcccccccccccccccc */
/* 0xf0f0f0f0f0f0f0f0 */
/* 0xff00ff00ff00ff00 */
/* 0xffff0000ffff0000 */
/* 0xffffffff00000000 */
/* */
/* The number test patterns will always be given by: */
/* */
/* log(base 2)(number data bits) = log2 (64) = 6 */
/* */
/* To test for short and opens to other signals on our boards. we */
/* simply */
/* test with the 1's complemnt of the paterns as well. */
/* */
/* OUTPUTS: */
/* Displays failing test pattern */
/* */
/* RETURNS: */
/* 0 - Passed test */
/* 1 - Failed test */
/* */
/* RESTRICTIONS/LIMITATIONS: */
/* Assumes only one one SDRAM bank */
/* */
/*********************************************************************/
int mem_test_data(void)
{
unsigned long long *pmem = (unsigned long long *)CFG_MEMTEST_START;
unsigned long long temp64;
int num_patterns = sizeof(pattern) / sizeof(pattern[0]);
int i;
unsigned int hi, lo;
for (i = 0; i < num_patterns; i++) {
move64(&(pattern[i]), pmem);
move64(pmem, &temp64);
/* hi = (temp64>>32) & 0xffffffff; */
/* lo = temp64 & 0xffffffff; */
/* printf("\ntemp64 = 0x%08x%08x", hi, lo); */
hi = (pattern[i] >> 32) & 0xffffffff;
lo = pattern[i] & 0xffffffff;
/* printf("\npattern[%d] = 0x%08x%08x", i, hi, lo); */
if (temp64 != pattern[i]) {
printf("\n Data Test Failed, pattern 0x%08x%08x",
hi, lo);
return 1;
}
}
return 0;
}
#endif /* CFG_DRAM_TEST_DATA */
#if defined (CFG_DRAM_TEST_ADDRESS)
/*********************************************************************/
/* NAME: mem_test_address() - test address lines */
/* */
/* DESCRIPTION: */
/* This function performs a test to verify that each word im */
/* memory is uniquly addressable. The test sequence is as follows: */
/* */
/* 1) write the address of each word to each word. */
/* 2) verify that each location equals its address */
/* */
/* OUTPUTS: */
/* Displays failing test pattern and address */
/* */
/* RETURNS: */
/* 0 - Passed test */
/* 1 - Failed test */
/* */
/* RESTRICTIONS/LIMITATIONS: */
/* */
/* */
/*********************************************************************/
int mem_test_address(void)
{
volatile unsigned int *pmem =
(volatile unsigned int *)CFG_MEMTEST_START;
const unsigned int size = (CFG_MEMTEST_END - CFG_MEMTEST_START) / 4;
unsigned int i;
/* write address to each location */
for (i = 0; i < size; i++) {
pmem[i] = i;
}
/* verify each loaction */
for (i = 0; i < size; i++) {
if (pmem[i] != i) {
printf("\n Address Test Failed at 0x%x", i);
return 1;
}
}
return 0;
}
#endif /* CFG_DRAM_TEST_ADDRESS */
#if defined (CFG_DRAM_TEST_WALK)
/*********************************************************************/
/* NAME: mem_march() - memory march */
/* */
/* DESCRIPTION: */
/* Marches up through memory. At each location verifies rmask if */
/* read = 1. At each location write wmask if write = 1. Displays */
/* failing address and pattern. */
/* */
/* INPUTS: */
/* volatile unsigned long long * base - start address of test */
/* unsigned int size - number of dwords(64-bit) to test */
/* unsigned long long rmask - read verify mask */
/* unsigned long long wmask - wrtie verify mask */
/* short read - verifies rmask if read = 1 */
/* short write - writes wmask if write = 1 */
/* */
/* OUTPUTS: */
/* Displays failing test pattern and address */
/* */
/* RETURNS: */
/* 0 - Passed test */
/* 1 - Failed test */
/* */
/* RESTRICTIONS/LIMITATIONS: */
/* */
/* */
/*********************************************************************/
int mem_march(volatile unsigned long long *base,
unsigned int size,
unsigned long long rmask,
unsigned long long wmask, short read, short write)
{
unsigned int i;
unsigned long long temp;
unsigned int hitemp, lotemp, himask, lomask;
for (i = 0; i < size; i++) {
if (read != 0) {
/* temp = base[i]; */
move64((unsigned long long *)&(base[i]), &temp);
if (rmask != temp) {
hitemp = (temp >> 32) & 0xffffffff;
lotemp = temp & 0xffffffff;
himask = (rmask >> 32) & 0xffffffff;
lomask = rmask & 0xffffffff;
printf("\n Walking one's test failed: \
address = 0x%08x," "\n\texpected \
0x%08x%08x, found 0x%08x%08x", i << 3,\
himask, lomask, hitemp, lotemp);
return 1;
}
}
if (write != 0) {
/* base[i] = wmask; */
move64(&wmask, (unsigned long long *)&(base[i]));
}
}
return 0;
}
#endif /* CFG_DRAM_TEST_WALK */
/*********************************************************************/
/* NAME: mem_test_walk() - a simple walking ones test */
/* */
/* DESCRIPTION: */
/* Performs a walking ones through entire physical memory. The */
/* test uses as series of memory marches, mem_march(), to verify */
/* and write the test patterns to memory. The test sequence is as */
/* follows: */
/* 1) march writing 0000...0001 */
/* 2) march verifying 0000...0001 , writing 0000...0010 */
/* 3) repeat step 2 shifting masks left 1 bit each time unitl */
/* the write mask equals 1000...0000 */
/* 4) march verifying 1000...0000 */
/* The test fails if any of the memory marches return a failure. */
/* */
/* OUTPUTS: */
/* Displays which pass on the memory test is executing */
/* */
/* RETURNS: */
/* 0 - Passed test */
/* 1 - Failed test */
/* */
/* RESTRICTIONS/LIMITATIONS: */
/* */
/* */
/*********************************************************************/
int mem_test_walk(void)
{
unsigned long long mask;
volatile unsigned long long *pmem =
(volatile unsigned long long *)CFG_MEMTEST_START;
const unsigned long size = (CFG_MEMTEST_END - CFG_MEMTEST_START) / 8;
unsigned int i;
mask = 0x01;
printf("Initial Pass");
mem_march(pmem, size, 0x0, 0x1, 0, 1);
printf("\b\b\b\b\b\b\b\b\b\b\b\b");
printf(" ");
printf(" ");
printf("\b\b\b\b\b\b\b\b\b\b\b\b");
for (i = 0; i < 63; i++) {
printf("Pass %2d", i + 2);
if (mem_march(pmem, size, mask, mask << 1, 1, 1) != 0) {
/*printf("mask: 0x%x, pass: %d, ", mask, i); */
return 1;
}
mask = mask << 1;
printf("\b\b\b\b\b\b\b");
}
printf("Last Pass");
if (mem_march(pmem, size, 0, mask, 0, 1) != 0) {
/* printf("mask: 0x%x", mask); */
return 1;
}
printf("\b\b\b\b\b\b\b\b\b");
printf(" ");
printf("\b\b\b\b\b\b\b\b\b");
return 0;
}
/*********************************************************************/
/* NAME: testdram() - calls any enabled memory tests */
/* */
/* DESCRIPTION: */
/* Runs memory tests if the environment test variables are set to */
/* 'y'. */
/* */
/* INPUTS: */
/* testdramdata - If set to 'y', data test is run. */
/* testdramaddress - If set to 'y', address test is run. */
/* testdramwalk - If set to 'y', walking ones test is run */
/* */
/* OUTPUTS: */
/* None */
/* */
/* RETURNS: */
/* 0 - Passed test */
/* 1 - Failed test */
/* */
/* RESTRICTIONS/LIMITATIONS: */
/* */
/* */
/*********************************************************************/
int testdram(void)
{
char *s;
int rundata, runaddress, runwalk;
s = getenv("testdramdata");
rundata = (s && (*s == 'y')) ? 1 : 0;
s = getenv("testdramaddress");
runaddress = (s && (*s == 'y')) ? 1 : 0;
s = getenv("testdramwalk");
runwalk = (s && (*s == 'y')) ? 1 : 0;
/* rundata = 1; */
/* runaddress = 0; */
/* runwalk = 0; */
if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) {
printf("Testing RAM from 0x%08x to 0x%08x ... \
(don't panic... that will take a moment !!!!)\n", \
CFG_MEMTEST_START, CFG_MEMTEST_END);
}
#ifdef CFG_DRAM_TEST_DATA
if (rundata == 1) {
printf("Test DATA ... ");
if (mem_test_data () == 1) {
printf("failed \n");
return 1;
} else
printf("ok \n");
}
#endif
#ifdef CFG_DRAM_TEST_ADDRESS
if (runaddress == 1) {
printf("Test ADDRESS ... ");
if (mem_test_address () == 1) {
printf("failed \n");
return 1;
} else
printf("ok \n");
}
#endif
#ifdef CFG_DRAM_TEST_WALK
if (runwalk == 1) {
printf("Test WALKING ONEs ... ");
if (mem_test_walk() == 1) {
printf("failed \n");
return 1;
} else
printf("ok \n");
}
#endif
if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) {
printf("passed\n");
}
return 0;
}
#endif /* CFG_DRAM_TEST */
#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP)
void
ft_board_setup(void *blob, bd_t *bd)
{
u32 *p;
int len;
ft_cpu_setup(blob, bd);
p = ft_get_prop(blob, "/memory/reg", &len);
if (p != NULL) {
*p++ = cpu_to_be32(bd->bi_memstart);
*p = cpu_to_be32(bd->bi_memsize);
}
}
#endif

View File

@ -0,0 +1,662 @@
/*****************************************************************************
* (C) Copyright 2003; Tundra Semiconductor Corp.
*
* 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
*****************************************************************************/
/*----------------------------------------------------------------------------
* FILENAME: tsi108_init.c
*
* Originator: Alex Bounine
*
* DESCRIPTION:
* Initialization code for the Tundra Tsi108 bridge chip
*---------------------------------------------------------------------------*/
#include <common.h>
#include <74xx_7xx.h>
#include <config.h>
#include <version.h>
#include <asm/processor.h>
#include <tsi108.h>
extern void mpicInit(int verbose);
/*
* Configuration Options
*/
typedef struct {
ulong upper;
ulong lower;
} PB2OCN_LUT_ENTRY;
PB2OCN_LUT_ENTRY pb2ocn_lut1[32] = {
/* 0 - 7 */
{0x00000000, 0x00000201}, /* PBA=0xE000_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xE100_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xE200_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xE300_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xE400_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xE500_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xE600_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xE700_0000 -> PCI/X (Byte-Swap) */
/* 8 - 15 */
{0x00000000, 0x00000201}, /* PBA=0xE800_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xE900_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xEA00_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xEB00_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xEC00_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xED00_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xEE00_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xEF00_0000 -> PCI/X (Byte-Swap) */
/* 16 - 23 */
{0x00000000, 0x00000201}, /* PBA=0xF000_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xF100_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xF200_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xF300_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xF400_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xF500_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xF600_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xF700_0000 -> PCI/X (Byte-Swap) */
/* 24 - 31 */
{0x00000000, 0x00000201}, /* PBA=0xF800_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xF900_0000 -> PCI/X (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xFA00_0000 -> PCI/X PCI I/O (Byte-Swap) */
{0x00000000, 0x00000201}, /* PBA=0xFB00_0000 -> PCI/X PCI Config (Byte-Swap) */
{0x00000000, 0x02000240}, /* PBA=0xFC00_0000 -> HLP */
{0x00000000, 0x01000240}, /* PBA=0xFD00_0000 -> HLP */
{0x00000000, 0x03000240}, /* PBA=0xFE00_0000 -> HLP */
{0x00000000, 0x00000240} /* PBA=0xFF00_0000 -> HLP : (Translation Enabled + Byte-Swap)*/
};
#ifdef CFG_CLK_SPREAD
typedef struct {
ulong ctrl0;
ulong ctrl1;
} PLL_CTRL_SET;
/*
* Clock Generator SPLL0 initialization values
* PLL0 configuration table for various PB_CLKO freq.
* Uses pre-calculated values for Fs = 30 kHz, D = 0.5%
* Fout depends on required PB_CLKO. Based on Fref = 33 MHz
*/
static PLL_CTRL_SET pll0_config[8] = {
{0x00000000, 0x00000000}, /* 0: bypass */
{0x00000000, 0x00000000}, /* 1: reserved */
{0x00430044, 0x00000043}, /* 2: CG_PB_CLKO = 183 MHz */
{0x005c0044, 0x00000039}, /* 3: CG_PB_CLKO = 100 MHz */
{0x005c0044, 0x00000039}, /* 4: CG_PB_CLKO = 133 MHz */
{0x004a0044, 0x00000040}, /* 5: CG_PB_CLKO = 167 MHz */
{0x005c0044, 0x00000039}, /* 6: CG_PB_CLKO = 200 MHz */
{0x004f0044, 0x0000003e} /* 7: CG_PB_CLKO = 233 MHz */
};
#endif /* CFG_CLK_SPREAD */
/*
* Prosessor Bus Clock (in MHz) defined by CG_PB_SELECT
* (based on recommended Tsi108 reference clock 33MHz)
*/
static int pb_clk_sel[8] = { 0, 0, 183, 100, 133, 167, 200, 233 };
/*
* get_board_bus_clk()
*
* returns the bus clock in Hz.
*/
unsigned long get_board_bus_clk(void)
{
ulong i;
/* Detect PB clock freq. */
i = in32(CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PWRUP_STATUS);
i = (i >> 16) & 0x07; /* Get PB PLL multiplier */
return pb_clk_sel[i] * 1000000;
}
/*
* board_early_init_f()
*
* board-specific initialization executed from flash
*/
int board_early_init_f(void)
{
DECLARE_GLOBAL_DATA_PTR;
ulong i;
gd->mem_clk = 0;
i = in32(CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PWRUP_STATUS);
i = (i >> 20) & 0x07;
switch (i) {
case 0:
printf("Using external clock\n");
break;
case 1:
gd->mem_clk = gd->bus_clk;
break;
case 4:
case 5:
case 6:
gd->mem_clk = pb_clk_sel[i] * 1000000;
break;
default:
printf("Invalid DDR2 clock setting\n");
return -1;
}
printf("BUS! %d MHz\n", get_board_bus_clk() / 1000000);
printf("MEM! %d MHz\n", gd->mem_clk / 1000000);
return 0;
}
/*
* board_early_init_r() - Tsi108 initialization function executed right after
* relocation. Contains code that cannot be executed from flash.
*/
int board_early_init_r(void)
{
ulong temp, i;
ulong reg_val;
volatile ulong *reg_ptr;
reg_ptr =
(ulong *) (CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + 0x900);
for (i = 0; i < 32; i++) {
*reg_ptr++ = 0x00000201; /* SWAP ENABLED */
*reg_ptr++ = 0x00;
}
__asm__ __volatile__("eieio");
__asm__ __volatile__("sync");
/* Setup PB_OCN_BAR2: size 256B + ENable @ 0x0_80000000 */
out32(CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + PB_OCN_BAR2,
0x80000001);
__asm__ __volatile__("sync");
/* Make sure that OCN_BAR2 decoder is set (to allow following immediate
* read from SDRAM)
*/
temp = in32(CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + PB_OCN_BAR2);
__asm__ __volatile__("sync");
/*
* Remap PB_OCN_BAR1 to accomodate PCI-bus aperture and EPROM into the
* processor bus address space. Immediately after reset LUT and address
* translation are disabled for this BAR. Now we have to initialize LUT
* and switch from the BOOT mode to the normal operation mode.
*
* The aperture defined by PB_OCN_BAR1 startes at address 0xE0000000
* and covers 512MB of address space. To allow larger aperture we also
* have to relocate register window of Tsi108
*
* Initialize LUT (32-entries) prior switching PB_OCN_BAR1 from BOOT
* mode.
*
* initialize pointer to LUT associated with PB_OCN_BAR1
*/
reg_ptr =
(ulong *) (CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + 0x800);
for (i = 0; i < 32; i++) {
*reg_ptr++ = pb2ocn_lut1[i].lower;
*reg_ptr++ = pb2ocn_lut1[i].upper;
}
__asm__ __volatile__("sync");
/* Base addresses for Cs0, CS1, CS2, CS3 */
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B0_ADDR,
0x00000000);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B1_ADDR,
0x00100000);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B2_ADDR,
0x00200000);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B3_ADDR,
0x00300000);
__asm__ __volatile__("sync");
/* Masks for HLP banks */
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B0_MASK,
0xFFF00000);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B1_MASK,
0xFFF00000);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B2_MASK,
0xFFF00000);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B3_MASK,
0xFFF00000);
__asm__ __volatile__("sync");
/* Set CTRL0 values for banks */
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B0_CTRL0,
0x7FFC44C2);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B1_CTRL0,
0x7FFC44C0);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B2_CTRL0,
0x7FFC44C0);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B3_CTRL0,
0x7FFC44C2);
__asm__ __volatile__("sync");
/* Set banks to latched mode, enabled, and other default settings */
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B0_CTRL1,
0x7C0F2000);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B1_CTRL1,
0x7C0F2000);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B2_CTRL1,
0x7C0F2000);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B3_CTRL1,
0x7C0F2000);
__asm__ __volatile__("sync");
/*
* Set new value for PB_OCN_BAR1: switch from BOOT to LUT mode.
* value for PB_OCN_BAR1: (BA-0xE000_0000 + size 512MB + ENable)
*/
out32(CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + PB_OCN_BAR1,
0xE0000011);
__asm__ __volatile__("sync");
/* Make sure that OCN_BAR2 decoder is set (to allow following
* immediate read from SDRAM)
*/
temp = in32(CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + PB_OCN_BAR1);
__asm__ __volatile__("sync");
/*
* SRI: At this point we have enabled the HLP banks. That means we can
* now read from the NVRAM and initialize the environment variables.
* We will over-ride the env_init called in board_init_f
* This is really a work-around because, the HLP bank 1
* where NVRAM resides is not visible during board_init_f
* (lib_ppc/board.c)
* Alternatively, we could use the I2C EEPROM at start-up to configure
* and enable all HLP banks and not just HLP 0 as is being done for
* Taiga Rev. 2.
*/
env_init();
#ifndef DISABLE_PBM
/*
* For IBM processors we have to set Address-Only commands generated
* by PBM that are different from ones set after reset.
*/
temp = get_cpu_type();
if ((CPU_750FX == temp) || (CPU_750GX == temp)) {
out32(CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + PB_MCMD,
0x00009955);
}
#endif /* DISABLE_PBM */
#ifdef CONFIG_PCI
/*
* Initialize PCI/X block
*/
/* Map PCI/X Configuration Space (16MB @ 0x0_FE000000) */
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_PFAB_BAR0_UPPER,
0);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_PFAB_BAR0,
0xFB000001);
__asm__ __volatile__("sync");
/* Set Bus Number for the attached PCI/X bus (we will use 0 for NB) */
temp =
in32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_PCIX_STAT);
temp &= ~0xFF00; /* Clear the BUS_NUM field */
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_PCIX_STAT,
temp);
/* Map PCI/X IO Space (64KB @ 0x0_FD000000) takes one 16MB LUT entry */
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_PFAB_IO_UPPER,
0);
__asm__ __volatile__("sync");
/* This register is on the PCI side to interpret the address it receives
* and maps it as a IO address.
*/
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_PFAB_IO,
0xFA000001);
__asm__ __volatile__("sync");
/*
* Map PCI/X Memory Space
*
* Transactions directed from OCM to PCI Memory Space are directed
* from PB to PCI
* unchanged (as defined by PB_OCN_BAR1,2 and LUT settings).
* If address remapping is required the corresponding PCI_PFAB_MEM32
* and PCI_PFAB_PFMx register groups have to be configured.
*
* Map the path from the PCI/X bus into the system memory
*
* The memory mapped window assotiated with PCI P2O_BAR2 provides
* access to the system memory without address remapping.
* All system memory is opened for accesses initiated by PCI/X bus
* masters.
*
* Initialize LUT associated with PCI P2O_BAR2
*
* set pointer to LUT associated with PCI P2O_BAR2
*/
reg_ptr =
(ulong *) (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + 0x500);
#ifdef DISABLE_PBM
/* In case when PBM is disabled (no HW supported cache snoopng on PB)
* P2O_BAR2 is directly mapped into the system memory without address
* translation.
*/
reg_val = 0x00000004; /* SDRAM port + NO Addr_Translation */
for (i = 0; i < 32; i++) {
*reg_ptr++ = reg_val; /* P2O_BAR2_LUTx */
*reg_ptr++ = 0; /* P2O_BAR2_LUT_UPPERx */
}
/* value for PCI BAR2 (size = 512MB, Enabled, No Addr. Translation) */
reg_val = 0x00007500;
#else
reg_val = 0x00000002; /* Destination port = PBM */
for (i = 0; i < 32; i++) {
*reg_ptr++ = reg_val; /* P2O_BAR2_LUTx */
/* P2O_BAR2_LUT_UPPERx : Set data swapping mode for PBM (byte swapping) */
*reg_ptr++ = 0x40000000;
/* offset = 16MB, address translation is enabled to allow byte swapping */
reg_val += 0x01000000;
}
/* value for PCI BAR2 (size = 512MB, Enabled, Address Translation Enabled) */
reg_val = 0x00007100;
#endif
__asm__ __volatile__("eieio");
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_PAGE_SIZES,
reg_val);
__asm__ __volatile__("sync");
/* Set 64-bit PCI bus address for system memory
* ( 0 is the best choice for easy mapping)
*/
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_BAR2,
0x00000000);
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_BAR2_UPPER,
0x00000000);
__asm__ __volatile__("sync");
#ifndef DISABLE_PBM
/*
* The memory mapped window assotiated with PCI P2O_BAR3 provides
* access to the system memory using SDRAM OCN port and address
* translation. This is alternative way to access SDRAM from PCI
* required for Tsi108 emulation testing.
* All system memory is opened for accesses initiated by
* PCI/X bus masters.
*
* Initialize LUT associated with PCI P2O_BAR3
*
* set pointer to LUT associated with PCI P2O_BAR3
*/
reg_ptr =
(ulong *) (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + 0x600);
reg_val = 0x00000004; /* Destination port = SDC */
for (i = 0; i < 32; i++) {
*reg_ptr++ = reg_val; /* P2O_BAR3_LUTx */
/* P2O_BAR3_LUT_UPPERx : Set data swapping mode for PBM (byte swapping) */
*reg_ptr++ = 0;
/* offset = 16MB, address translation is enabled to allow byte swapping */
reg_val += 0x01000000;
}
__asm__ __volatile__("eieio");
__asm__ __volatile__("sync");
/* Configure PCI P2O_BAR3 (size = 512MB, Enabled) */
reg_val =
in32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET +
PCI_P2O_PAGE_SIZES);
reg_val &= ~0x00FF;
reg_val |= 0x0071;
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_PAGE_SIZES,
reg_val);
__asm__ __volatile__("sync");
/* Set 64-bit base PCI bus address for window (0x20000000) */
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_BAR3_UPPER,
0x00000000);
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_BAR3,
0x20000000);
__asm__ __volatile__("sync");
#endif /* !DISABLE_PBM */
#ifdef ENABLE_PCI_CSR_BAR
/* open if required access to Tsi108 CSRs from the PCI/X bus */
/* enable BAR0 on the PCI/X bus */
reg_val =
in32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_MISC_CSR);
reg_val |= 0x02;
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_MISC_CSR,
reg_val);
__asm__ __volatile__("sync");
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_BAR0_UPPER,
0x00000000);
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_BAR0,
CFG_TSI108_CSR_BASE);
__asm__ __volatile__("sync");
#endif
/*
* Finally enable PCI/X Bus Master and Memory Space access
*/
reg_val = in32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_CSR);
reg_val |= 0x06;
out32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_CSR, reg_val);
__asm__ __volatile__("sync");
#endif /* CONFIG_PCI */
/*
* Initialize MPIC outputs (interrupt pins):
* Interrupt routing on the Grendel Emul. Board:
* PB_INT[0] -> INT (CPU0)
* PB_INT[1] -> INT (CPU1)
* PB_INT[2] -> MCP (CPU0)
* PB_INT[3] -> MCP (CPU1)
* Set interrupt controller outputs as Level_Sensitive/Active_Low
*/
out32(CFG_TSI108_CSR_BASE + TSI108_MPIC_REG_OFFSET + MPIC_CSR(0), 0x02);
out32(CFG_TSI108_CSR_BASE + TSI108_MPIC_REG_OFFSET + MPIC_CSR(1), 0x02);
out32(CFG_TSI108_CSR_BASE + TSI108_MPIC_REG_OFFSET + MPIC_CSR(2), 0x02);
out32(CFG_TSI108_CSR_BASE + TSI108_MPIC_REG_OFFSET + MPIC_CSR(3), 0x02);
__asm__ __volatile__("sync");
/*
* Ensure that Machine Check exception is enabled
* We need it to support PCI Bus probing (configuration reads)
*/
reg_val = mfmsr();
mtmsr(reg_val | MSR_ME);
return 0;
}
/*
* Needed to print out L2 cache info
* used in the misc_init_r function
*/
unsigned long get_l2cr(void)
{
unsigned long l2controlreg;
asm volatile ("mfspr %0, 1017":"=r" (l2controlreg):);
return l2controlreg;
}
/*
* misc_init_r()
*
* various things to do after relocation
*
*/
int misc_init_r(void)
{
DECLARE_GLOBAL_DATA_PTR;
#ifdef CFG_CLK_SPREAD /* Initialize Spread-Spectrum Clock generation */
ulong i;
/* Ensure that Spread-Spectrum is disabled */
out32(CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PLL0_CTRL0, 0);
out32(CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PLL1_CTRL0, 0);
/* Initialize PLL1: CG_PCI_CLK , internal OCN_CLK
* Uses pre-calculated value for Fout = 800 MHz, Fs = 30 kHz, D = 0.5%
*/
out32(CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PLL1_CTRL0, 0x002e0044); /* D = 0.25% */
out32(CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PLL1_CTRL1, 0x00000039); /* BWADJ */
/* Initialize PLL0: CG_PB_CLKO */
/* Detect PB clock freq. */
i = in32(CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PWRUP_STATUS);
i = (i >> 16) & 0x07; /* Get PB PLL multiplier */
out32(CFG_TSI108_CSR_BASE +
TSI108_CLK_REG_OFFSET + CG_PLL0_CTRL0, pll0_config[i].ctrl0);
out32(CFG_TSI108_CSR_BASE +
TSI108_CLK_REG_OFFSET + CG_PLL0_CTRL1, pll0_config[i].ctrl1);
/* Wait and set SSEN for both PLL0 and 1 */
udelay(1000);
out32(CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PLL1_CTRL0, 0x802e0044); /* D=0.25% */
out32(CFG_TSI108_CSR_BASE +
TSI108_CLK_REG_OFFSET + CG_PLL0_CTRL0,
0x80000000 | pll0_config[i].ctrl0);
#endif /* CFG_CLK_SPREAD */
#ifdef CFG_L2
l2cache_enable();
#endif
printf("BUS: %d MHz\n", gd->bus_clk / 1000000);
printf("MEM: %d MHz\n", gd->mem_clk / 1000000);
/*
* All the information needed to print the cache details is avaiblable
* at this point i.e. above call to l2cache_enable is the very last
* thing done with regards to enabling diabling the cache.
* So this seems like a good place to print all this information
*/
printf("CACHE: ");
switch (get_cpu_type()) {
case CPU_7447A:
printf("L1 Instruction cache - 32KB 8-way");
(get_hid0() & (1 << 15)) ? printf(" ENABLED\n") :
printf(" DISABLED\n");
printf(" L1 Data cache - 32KB 8-way");
(get_hid0() & (1 << 14)) ? printf(" ENABLED\n") :
printf(" DISABLED\n");
printf(" Unified L2 cache - 512KB 8-way");
(get_l2cr() & (1 << 31)) ? printf(" ENABLED\n") :
printf(" DISABLED\n");
printf("\n");
break;
case CPU_7448:
printf("L1 Instruction cache - 32KB 8-way");
(get_hid0() & (1 << 15)) ? printf(" ENABLED\n") :
printf(" DISABLED\n");
printf(" L1 Data cache - 32KB 8-way");
(get_hid0() & (1 << 14)) ? printf(" ENABLED\n") :
printf(" DISABLED\n");
printf(" Unified L2 cache - 1MB 8-way");
(get_l2cr() & (1 << 31)) ? printf(" ENABLED\n") :
printf(" DISABLED\n");
break;
default:
break;
}
return 0;
}