forked from Imagelibrary/rtems
378 lines
10 KiB
C
378 lines
10 KiB
C
/*
|
|
* This routine does the bulk of the system initialization.
|
|
*/
|
|
|
|
/*
|
|
* COPYRIGHT (c) 1989-1998.
|
|
* On-Line Applications Research Corporation (OAR).
|
|
*
|
|
* The license and distribution terms for this file may be
|
|
* found in the file LICENSE in this distribution or at
|
|
* http://www.rtems.org/license/LICENSE.
|
|
*
|
|
* Modified to support the MCP750.
|
|
* Modifications Copyright (C) 1999 Eric Valette. eric.valette@free.fr
|
|
*
|
|
* Modified to support the Synergy VGM & Motorola PowerPC boards.
|
|
* (C) by Till Straumann, <strauman@slac.stanford.edu>, 2002, 2004, 2005
|
|
*
|
|
* Modified to support the mvme5500 BSP
|
|
* (C) by Kate Feng <feng1@bnl.gov>, 2003, 2004
|
|
* under the contract DE-AC02-98CH10886 with the Deaprtment of Energy
|
|
*
|
|
* T. Straumann: 2005-2007; stolen again for 'beatnik'...
|
|
*/
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
|
|
#include <rtems/libio.h>
|
|
#include <rtems/libcsupport.h>
|
|
#include <rtems/bspIo.h>
|
|
#include <rtems/counter.h>
|
|
#include <rtems/powerpc/powerpc.h>
|
|
#include <rtems/sysinit.h>
|
|
/*#include <bsp/consoleIo.h>*/
|
|
#include <libcpu/spr.h> /* registers.h is included here */
|
|
#include <bsp.h>
|
|
#include <bsp/bootcard.h>
|
|
#include <bsp/uart.h>
|
|
#include <bsp/pci.h>
|
|
#include <bsp/gtreg.h>
|
|
#include <bsp/gt_timer.h>
|
|
#include <libcpu/bat.h>
|
|
#include <libcpu/pte121.h>
|
|
#include <libcpu/cpuIdent.h>
|
|
#include <bsp/vectors.h>
|
|
#include <bsp/VME.h>
|
|
#include <bsp/vpd.h>
|
|
|
|
#define SHOW_MORE_INIT_SETTINGS
|
|
|
|
BSP_output_char_function_type BSP_output_char = BSP_output_char_via_serial;
|
|
BSP_polling_getchar_function_type BSP_poll_char = NULL;
|
|
|
|
extern Triv121PgTbl BSP_pgtbl_setup(unsigned int *);
|
|
extern void BSP_pgtbl_activate(Triv121PgTbl);
|
|
extern void BSP_motload_pci_fixup(void);
|
|
|
|
extern unsigned long __rtems_end[];
|
|
|
|
/* We really shouldn't use these since MMUoff also sets IP;
|
|
* nevertheless, during early init I don't care for now
|
|
*/
|
|
extern void MMUoff(void);
|
|
extern void MMUon(void);
|
|
|
|
extern uint32_t probeMemoryEnd(void);
|
|
|
|
SPR_RW(SPRG0)
|
|
SPR_RW(SPRG1)
|
|
SPR_RO(HID1)
|
|
|
|
/* Table of PLL multipliers for 7455/7457:
|
|
01000 2 00010 7.5 00000 11.5 00001 17
|
|
10000 3 11000 8 10111 12 00101 18
|
|
10100 4 01100 8.5 11111 12.5 00111 20
|
|
10110 5 01111 9 01011 13 01001 21
|
|
10010 5.5 01110 9.5 11100 13.5 01101 24
|
|
11010 6 10101 10 11001 14 11101 28
|
|
01010 6.5 10001 10.5 00011 15 00110 bypass
|
|
00100 7 10011 11 11011 16 11110 off
|
|
*/
|
|
|
|
/* Sorted according to CFG bits and multiplied by 2 it looks
|
|
* like this (note that this is in sequential order, not
|
|
* tabulated as above)
|
|
*/
|
|
signed char mpc7450PllMultByTwo[32] = {
|
|
23, 34, 15, 30,
|
|
14, 36, 2/*bypass*/, 40,
|
|
4, 42, 13, 26,
|
|
17, 48, 19, 18,
|
|
6, 21, 11, 22,
|
|
8, 20, 10, 24,
|
|
16, 28, 12, 32,
|
|
27, 56, 0/*off*/, 25,
|
|
};
|
|
|
|
uint32_t bsp_clicks_per_usec = 0;
|
|
|
|
/*
|
|
* Total memory using probing.
|
|
*/
|
|
unsigned int BSP_mem_size;
|
|
|
|
/*
|
|
* PCI Bus Frequency
|
|
*/
|
|
unsigned int BSP_bus_frequency = 0xdeadbeef;
|
|
/*
|
|
* processor clock frequency
|
|
*/
|
|
unsigned int BSP_processor_frequency = 0xdeadbeef;
|
|
|
|
/*
|
|
* Time base divisior (bus freq / TB clock)
|
|
*/
|
|
unsigned int BSP_time_base_divisor = 4000; /* most 604+ CPUs seem to use this */
|
|
|
|
/* Board identification string */
|
|
char BSP_productIdent[20] = {0};
|
|
char BSP_serialNumber[20] = {0};
|
|
|
|
/* VPD appends an extra char -- what for ? */
|
|
char BSP_enetAddr0[7] = {0};
|
|
char BSP_enetAddr1[7] = {0};
|
|
|
|
char *rtems_progname;
|
|
|
|
#define CMDLINE_BUF_SIZE 2048
|
|
|
|
static char cmdline_buf[CMDLINE_BUF_SIZE];
|
|
char *BSP_commandline_string = cmdline_buf;
|
|
|
|
/* this routine is called early and must be safe with a not properly
|
|
* aligned stack
|
|
*/
|
|
char *save_boot_params(
|
|
void *r3,
|
|
void *r4,
|
|
void *r5,
|
|
char *cmdline_start,
|
|
char *cmdline_end
|
|
)
|
|
{
|
|
int i=cmdline_end-cmdline_start;
|
|
if ( i >= CMDLINE_BUF_SIZE )
|
|
i = CMDLINE_BUF_SIZE-1;
|
|
else if ( i < 0 )
|
|
i = 0;
|
|
memmove(cmdline_buf, cmdline_start, i);
|
|
cmdline_buf[i]=0;
|
|
return cmdline_buf;
|
|
}
|
|
|
|
static BSP_BoardType board_type = Unknown;
|
|
|
|
BSP_BoardType
|
|
BSP_getBoardType( void )
|
|
{
|
|
return board_type;
|
|
}
|
|
|
|
uint32_t _CPU_Counter_frequency(void)
|
|
{
|
|
return BSP_bus_frequency / (BSP_time_base_divisor / 1000);
|
|
}
|
|
|
|
static void bsp_early( void )
|
|
{
|
|
unsigned char *stack;
|
|
char *chpt;
|
|
|
|
Triv121PgTbl pt=0;
|
|
|
|
VpdBufRec vpdData [] = {
|
|
{ key: ProductIdent, instance: 0, buf: BSP_productIdent, buflen: sizeof(BSP_productIdent) - 1 },
|
|
{ key: SerialNumber, instance: 0, buf: BSP_serialNumber, buflen: sizeof(BSP_serialNumber) - 1 },
|
|
{ key: CpuClockHz, instance: 0, buf: &BSP_processor_frequency, buflen: sizeof(BSP_processor_frequency) },
|
|
{ key: BusClockHz, instance: 0, buf: &BSP_bus_frequency, buflen: sizeof(BSP_bus_frequency) },
|
|
{ key: EthernetAddr, instance: 0, buf: BSP_enetAddr0, buflen: sizeof(BSP_enetAddr0) },
|
|
{ key: EthernetAddr, instance: 1, buf: BSP_enetAddr1, buflen: sizeof(BSP_enetAddr1) },
|
|
VPD_END
|
|
};
|
|
|
|
/* T. Straumann: 4/2005
|
|
*
|
|
* Need to map the system registers early, so we can printk...
|
|
* (otherwise we silently die)
|
|
*/
|
|
/* map the PCI 0, 1 Domain I/O space, GT64260B registers
|
|
* and the reserved area so that the size is the power of 2.
|
|
*/
|
|
setdbat(7, BSP_DEV_AND_PCI_IO_BASE, BSP_DEV_AND_PCI_IO_BASE, BSP_DEV_AND_PCI_IO_SIZE, IO_PAGE);
|
|
|
|
/* Intersperse messages with actions to help locate problems */
|
|
printk("-----------------------------------------\n");
|
|
|
|
/*
|
|
* Get CPU identification dynamically. Note that the get_ppc_cpu_type() & friends functions
|
|
* store the result in global variables so that it can be used latter...
|
|
* This also verifies that we run on a known CPU.
|
|
*/
|
|
get_ppc_cpu_type();
|
|
get_ppc_cpu_revision();
|
|
|
|
/* Make sure we detect a known host bridge */
|
|
BSP_getDiscoveryVersion(/* assert detection */ 1);
|
|
|
|
printk("Welcome to RTEMS %s\n", rtems_get_version_string() );
|
|
|
|
/* Leave all caches as MotLoad left them. Seems to be fine */
|
|
|
|
/*
|
|
* the initial stack has aready been set to this value in start.S
|
|
* so there is no need to set it in r1 again... It is just for info
|
|
* so that it can be printed without accessing R1.
|
|
*/
|
|
__asm__ volatile("mr %0, 1":"=r"(stack));
|
|
|
|
/* tag the bottom (T. Straumann 6/36/2001 <strauman@slac.stanford.edu>) */
|
|
|
|
*((uint32_t *)stack) = 0;
|
|
|
|
ppc_exc_initialize();
|
|
|
|
printk("CPU: %s\n", get_ppc_cpu_type_name(current_ppc_cpu));
|
|
|
|
/*
|
|
* Initialize RTEMS IRQ system
|
|
*/
|
|
BSP_rtems_irq_mng_init(0);
|
|
|
|
BSP_vpdRetrieveFields(vpdData);
|
|
|
|
if ( !strncmp(BSP_productIdent,"MVME5500",8) )
|
|
board_type = MVME5500;
|
|
else if ( !strncmp(BSP_productIdent,"MVME6100",8) )
|
|
board_type = MVME6100;
|
|
|
|
printk("Board Type: %s (S/N %s)\n",
|
|
BSP_productIdent[0] ? BSP_productIdent : "n/a",
|
|
BSP_serialNumber[0] ? BSP_serialNumber : "n/a");
|
|
|
|
if ( 0xdeadbeef == BSP_bus_frequency ) {
|
|
BSP_bus_frequency = 133333333;
|
|
printk("Bus Clock Freq NOT FOUND in VPD; using %10u Hz\n",
|
|
BSP_bus_frequency);
|
|
} else {
|
|
printk("Bus Clock Freq: %10u Hz\n",
|
|
BSP_bus_frequency);
|
|
}
|
|
|
|
if ( 0xdeadbeef == BSP_processor_frequency ) {
|
|
BSP_processor_frequency = BSP_bus_frequency/2;
|
|
BSP_processor_frequency *= mpc7450PllMultByTwo[ (_read_HID1() >> (31-19)) & 31 ];
|
|
}
|
|
printk("CPU Clock Freq: %10u Hz\n", BSP_processor_frequency);
|
|
|
|
/* probe real memory size; if it's more than 256M we can't currently access it
|
|
* since at this point only BAT-0 maps 0..256M
|
|
*/
|
|
BSP_mem_size = probeMemoryEnd();
|
|
|
|
if ( (chpt = strstr(BSP_commandline_string,"MEMSZ=")) ) {
|
|
char *endp;
|
|
uint32_t sz;
|
|
chpt+=6 /* strlen("MEMSZ=") */;
|
|
sz = strtoul(chpt, &endp, 0);
|
|
if ( endp != chpt )
|
|
BSP_mem_size = sz;
|
|
}
|
|
|
|
printk("Memory: %10u bytes\n", BSP_mem_size);
|
|
|
|
if ( BSP_mem_size > 0x10000000 ) {
|
|
uint32_t s;
|
|
if ( BSP_mem_size > 0x80000000 ) {
|
|
BSP_mem_size = 0x80000000;
|
|
printk("Memory clipped to 0x%08x for now, sorry\n", BSP_mem_size);
|
|
}
|
|
for ( s = 0x20000000; s < BSP_mem_size ; s<<=1)
|
|
;
|
|
MMUoff();
|
|
/* since it's currently in use we must first surrender it */
|
|
setdbat(0, 0, 0, 0, 0);
|
|
setdbat(0, 0, 0, s, _PAGE_RW);
|
|
MMUon();
|
|
}
|
|
|
|
printk("-----------------------------------------\n");
|
|
|
|
/* Maybe not setup yet because of the warning message */
|
|
|
|
/* Allocate and set up the page table mappings
|
|
* This is only available on >604 CPUs.
|
|
*
|
|
* NOTE: This setup routine may modify the available memory
|
|
* size. It is essential to call it before
|
|
* calculating the workspace etc.
|
|
*/
|
|
pt = BSP_pgtbl_setup(&BSP_mem_size);
|
|
if (!pt)
|
|
printk("WARNING: unable to setup page tables.\n");
|
|
|
|
#ifdef SHOW_MORE_INIT_SETTINGS
|
|
printk("Now BSP_mem_size = 0x%x\n",BSP_mem_size);
|
|
#endif
|
|
|
|
/*
|
|
* Set up our hooks
|
|
*/
|
|
|
|
bsp_clicks_per_usec = BSP_bus_frequency/(BSP_time_base_divisor * 1000);
|
|
|
|
#ifdef SHOW_MORE_INIT_SETTINGS
|
|
printk(
|
|
"Configuration.work_space_size = %x\n",
|
|
rtems_configuration_get_work_space_size()
|
|
);
|
|
#endif
|
|
|
|
/* Activate the page table mappings only after
|
|
* initializing interrupts because the irq_mng_init()
|
|
* routine needs to modify the text
|
|
*/
|
|
if ( pt ) {
|
|
#ifdef SHOW_MORE_INIT_SETTINGS
|
|
printk("Page table setup finished; will activate it NOW...\n");
|
|
#endif
|
|
BSP_pgtbl_activate(pt);
|
|
}
|
|
|
|
#ifdef SHOW_MORE_INIT_SETTINGS
|
|
printk("Going to start PCI buses scanning and initialization\n");
|
|
#endif
|
|
BSP_pci_initialize();
|
|
|
|
/* need to tweak the motload setup */
|
|
BSP_motload_pci_fixup();
|
|
|
|
/* map 512M, 256 for PCI 256 for VME */
|
|
setdbat(5,BSP_PCI_HOSE0_MEM_BASE, BSP_PCI_HOSE0_MEM_BASE, BSP_PCI_HOSE0_MEM_SIZE, IO_PAGE);
|
|
setdbat(6,BSP_PCI_HOSE1_MEM_BASE, BSP_PCI_HOSE1_MEM_BASE, 0x10000000, IO_PAGE);
|
|
|
|
#ifdef SHOW_MORE_INIT_SETTINGS
|
|
printk("Number of PCI buses found is : %d\n", pci_bus_count());
|
|
#endif
|
|
|
|
/*
|
|
* Initialize hardware timer facility (not used by BSP itself)
|
|
* Needs PCI to identify discovery version...
|
|
*/
|
|
BSP_timers_initialize();
|
|
|
|
#ifdef SHOW_MORE_INIT_SETTINGS
|
|
printk("MSR 0x%lx \n", _read_MSR());
|
|
printk("Exit from bspstart\n");
|
|
#endif
|
|
}
|
|
|
|
RTEMS_SYSINIT_ITEM(
|
|
bsp_early,
|
|
RTEMS_SYSINIT_BSP_EARLY,
|
|
RTEMS_SYSINIT_ORDER_MIDDLE
|
|
);
|
|
|
|
void bsp_start( void )
|
|
{
|
|
/* Initialization was done by bsp_early() */
|
|
}
|
|
|
|
RTEMS_SYSINIT_ITEM(
|
|
BSP_vme_config,
|
|
RTEMS_SYSINIT_BSP_PRE_DRIVERS,
|
|
RTEMS_SYSINIT_ORDER_MIDDLE
|
|
);
|