summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/mvme5500/start/bspstart.c
blob: fc7057613aa70e5dd7a5c99d41278291e619f9d6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
/*
 *  This routine does the bulk of the system initialization.
 */

/*
 *  COPYRIGHT (c) 1989-2007.
 *  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. valette@crf.canon.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 board.
 *  Also, the settings of L1, L2, and L3 caches is not necessary here.
 *  (C) by Brookhaven National Lab., S. Kate Feng <feng1@bnl.gov>, 2003-2009
 */

#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#include <rtems/sysinit.h>
#include <rtems/system.h>
#include <rtems/powerpc/powerpc.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 <libcpu/bat.h>
#include <libcpu/pte121.h>
#include <libcpu/cpuIdent.h>
#include <bsp/vectors.h>
#include <bsp/VME.h>
#include <bsp/bspException.h>

#include <rtems/bspIo.h>
#include <rtems/counter.h>

/*
#define SHOW_MORE_INIT_SETTINGS
#define SHOW_LCR1_REGISTER
#define SHOW_LCR2_REGISTER
#define SHOW_LCR3_REGISTER
#define CONF_VPD
*/

extern uint32_t probeMemoryEnd(void); /* from shared/startup/probeMemoryEnd.c */

BSP_output_char_function_type     BSP_output_char = BSP_output_char_via_serial;
BSP_polling_getchar_function_type BSP_poll_char = NULL;

extern void _return_to_ppcbug(void);
extern unsigned long __rtems_end[];
extern unsigned get_L1CR(void), get_L2CR(void), get_L3CR(void);
extern Triv121PgTbl BSP_pgtbl_setup(unsigned int *);
extern void BSP_pgtbl_activate(Triv121PgTbl);
extern int I2Cread_eeprom(unsigned char I2cBusAddr, uint32_t devA2A1A0, uint32_t AddrBytes, unsigned char *pBuff, uint32_t numBytes);
extern void BSP_vme_config(void);

extern unsigned char ReadConfVPD_buff(int offset);

uint32_t bsp_clicks_per_usec;

typedef struct CmdLineRec_ {
    unsigned long  size;
    char           buf[0];
} CmdLineRec, *CmdLine;


#define mtspr(reg, val)  \
  __asm __volatile("mtspr %0,%1" : : "K"(reg), "r"(val))


#define mfspr(reg) \
  ( { unsigned val; \
    __asm __volatile("mfspr %0,%1" : "=r"(val) : "K"(reg)); \
    val; } )

/*
 * Copy Additional boot param passed by boot loader
 */
#define MAX_LOADER_ADD_PARM 80
char loaderParam[MAX_LOADER_ADD_PARM];

/*
 * Total memory using RESIDUAL DATA
 */
unsigned int BSP_mem_size;
/*
 * PCI Bus Frequency
 */
unsigned int BSP_bus_frequency;
/*
 * processor clock frequency
 */
unsigned int BSP_processor_frequency;
/*
 * Time base divisior (how many tick for 1 second).
 */
unsigned int BSP_time_base_divisor;
static unsigned char ConfVPD_buff[200];

#define CMDLINE_BUF_SIZE  2048

static char cmdline_buf[CMDLINE_BUF_SIZE];
char *BSP_commandline_string = cmdline_buf;

/* NOTE: we cannot simply malloc the commandline string;
 * save_boot_params() is called during a very early stage when
 * libc/malloc etc. are not yet initialized!
 *
 * Here's what we do:
 *
 * initial layout setup by the loader (preload.S):
 *
 * 0..RTEMS...__rtems_end | cmdline ....... TOP
 *
 * After the save_boot_params() routine returns, the stack area will be
 * set up (start.S):
 *
 * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | ..... TOP
 *
 * initialize_executive_early() [called from boot_card()]
 * will initialize the workspace:
 *
 * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | ...... | workspace | TOP
 *
 * and later calls our bsp_predriver_hook() which ends up initializing
 * libc which in turn initializes the heap
 *
 * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | heap | workspace | TOP
 *
 * The idea here is to first move the commandline to the future 'heap' area
 * from where it will be picked up by our bsp_predriver_hook().
 * bsp_predriver_hook() then moves it either to INIT_STACK or the workspace
 * area using proper allocation, initializes libc and finally moves
 * the data to the environment / malloced areas...
 */

/* this routine is called early at shared/start/start.S
 * 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;
}

uint32_t _CPU_Counter_frequency(void)
{
  return BSP_bus_frequency / (BSP_time_base_divisor / 1000);
}

void bsp_start( void )
{
#ifdef CONF_VPD
  int i;
#endif
#ifdef SHOW_LCR1_REGISTER
  unsigned l1cr;
#endif
#ifdef SHOW_LCR2_REGISTER
  unsigned l2cr;
#endif
#ifdef SHOW_LCR3_REGISTER
  unsigned l3cr;
#endif
  uintptr_t intrStackStart;
  uintptr_t intrStackSize;
  Triv121PgTbl  pt=0;

  /* Till Straumann: 4/2005
   * Need to map the system registers early, so we can printk...
   * (otherwise we silently die)
   */
  /*
   * Kate Feng : PCI 0 domain memory space, want to leave room for the VME window
   */
  setdbat(2, PCI0_MEM_BASE, PCI0_MEM_BASE, 0x10000000, IO_PAGE);

  /* Till Straumann: 2004
   * map the PCI 0, 1 Domain I/O space, GT64260B registers
   * and the reserved area so that the size is the power of 2.
   * 2009 : map the entire 256 M space
   *
   */
  setdbat(3,PCI0_IO_BASE, PCI0_IO_BASE, 0x10000000, IO_PAGE);


  /*
   * Get CPU identification dynamically. Note that the get_ppc_cpu_type()
   * function store the result in global variables so that it can be used later.
   */
  get_ppc_cpu_type();
  get_ppc_cpu_revision();

#ifdef SHOW_LCR1_REGISTER
  l1cr = get_L1CR();
  printk("Initial L1CR value = %x\n", l1cr);
#endif

  /*
   * Initialize the interrupt related settings.
   */
  intrStackStart = (uintptr_t) __rtems_end;
  intrStackSize = rtems_configuration_get_interrupt_stack_size();

  /*
   * Initialize default raw exception handlers.
   */
  ppc_exc_initialize(intrStackStart, intrStackSize);

  /*
   * Init MMU block address translation to enable hardware
   * access
   * More PCI1 memory mapping to be done after BSP_pgtbl_activate.
   */
  printk("-----------------------------------------\n");
  printk("Welcome to %s on MVME5500-0163\n", _RTEMS_version );
  printk("-----------------------------------------\n");

  BSP_mem_size         =  probeMemoryEnd();

  /* TODO: calculate the BSP_bus_frequency using the REF_CLK bit
   *       of System Status  register
   */
  /* rtems_bsp_delay_in_bus_cycles are defined in registers.h */
  BSP_bus_frequency      = 133333333;
  BSP_processor_frequency    = 1000000000;
  /* P94 : 7455 clocks the TB/DECR at 1/4 of the system bus clock frequency */
  BSP_time_base_divisor      = 4000;

  /* Maybe not setup yet becuase 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");

  printk("Now BSP_mem_size = 0x%x\n",BSP_mem_size);

  /* P94 : 7455 TB/DECR is clocked by the system bus clock frequency */

  bsp_clicks_per_usec    = BSP_bus_frequency/(BSP_time_base_divisor * 1000);

  /*
   * Initalize RTEMS IRQ system
   */
   BSP_rtems_irq_mng_init(0);

#ifdef SHOW_LCR2_REGISTER
  l2cr = get_L2CR();
  printk("Initial L2CR value = %x\n", l2cr);
#endif

#ifdef SHOW_LCR3_REGISTER
  /* L3CR needs DEC int. handler installed for bsp_delay()*/
  l3cr = get_L3CR();
  printk("Initial L3CR value = %x\n", l3cr);
#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);
  }
  /* Read Configuration Vital Product Data (VPD) */
  if ( I2Cread_eeprom(0xa8, 4,2, &ConfVPD_buff[0], 150))
     printk("I2Cread_eeprom() error \n");
  else {
#ifdef CONF_VPD
    printk("\n");
    for (i=0; i<150; i++) {
      printk("%2x ", ConfVPD_buff[i]);
      if ((i % 20)==0 ) printk("\n");
    }
    printk("\n");
#endif
  }

  /*
   * PCI 1 domain memory space
   */
  setdbat(1, PCI1_MEM_BASE, PCI1_MEM_BASE, 0x10000000, IO_PAGE);


#ifdef SHOW_MORE_INIT_SETTINGS
  printk("Going to start PCI buses scanning and initialization\n");
#endif
  pci_initialize();
#ifdef SHOW_MORE_INIT_SETTINGS
  printk("Number of PCI buses found is : %d\n", pci_bus_count());
#endif

  /* Install our own exception handler (needs PCI) */
  globalExceptHdl = BSP_exceptionHandler;

  /* clear hostbridge errors. MCP signal is not used on the MVME5500
   * PCI config space scanning code will trip otherwise :-(
   */
  _BSP_clear_hostbridge_errors(0, 1 /*quiet*/);

#ifdef SHOW_MORE_INIT_SETTINGS
  printk("MSR %x \n", _read_MSR());
  printk("Exit from bspstart\n");
#endif

}

unsigned char ReadConfVPD_buff(int offset)
{
  return(ConfVPD_buff[offset]);
}

RTEMS_SYSINIT_ITEM(
  BSP_vme_config,
  RTEMS_SYSINIT_BSP_PRE_DRIVERS,
  RTEMS_SYSINIT_ORDER_MIDDLE
);