| /***************************************************************************** |
| * (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; /* value of SW4[4:7] */ |
| switch (i) { |
| case 0: /* external clock */ |
| printf ("Using external clock\n"); |
| break; |
| case 1: /* system clock */ |
| gd->mem_clk = gd->bus_clk; |
| break; |
| case 4: /* 133 MHz */ |
| case 5: /* 166 MHz */ |
| case 6: /* 200 MHz */ |
| 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; |
| } |