diff options
author | roy zang <tie-fei.zang@freescale.com> | 2006-11-02 18:59:15 +0800 |
---|---|---|
committer | Zang Tiefei <roy@bus.ap.freescale.net> | 2006-11-02 18:59:15 +0800 |
commit | 87c4db09699c6b89176b31004afcb83eb1585d47 (patch) | |
tree | 761efc05e345c77e6981cbd03d34aec195ff2e17 /board | |
parent | 27801b8ab11c61b577e45742a515bb3b23b80241 (diff) | |
download | u-boot-imx-87c4db09699c6b89176b31004afcb83eb1585d47.zip u-boot-imx-87c4db09699c6b89176b31004afcb83eb1585d47.tar.gz u-boot-imx-87c4db09699c6b89176b31004afcb83eb1585d47.tar.bz2 |
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>
Diffstat (limited to 'board')
-rw-r--r-- | board/mpc7448hpc2/mpc7448hpc2.c | 489 | ||||
-rw-r--r-- | board/mpc7448hpc2/tsi108_init.c | 662 |
2 files changed, 1151 insertions, 0 deletions
diff --git a/board/mpc7448hpc2/mpc7448hpc2.c b/board/mpc7448hpc2/mpc7448hpc2.c new file mode 100644 index 0000000..f90a751 --- /dev/null +++ b/board/mpc7448hpc2/mpc7448hpc2.c @@ -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 diff --git a/board/mpc7448hpc2/tsi108_init.c b/board/mpc7448hpc2/tsi108_init.c new file mode 100644 index 0000000..6f517f5 --- /dev/null +++ b/board/mpc7448hpc2/tsi108_init.c @@ -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; +} |