summaryrefslogtreecommitdiffstats
path: root/src/ssx/pgp/pgp_init.c
blob: 4e2801427b2f618afddab9b4cd1127f8bda64bd1 (plain)
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
// $Id: pgp_init.c,v 1.2 2014/03/14 16:34:34 bcbrock Exp $
// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_init.c,v $
//-----------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2013
// *! All Rights Reserved -- Property of IBM
// *! *** IBM Confidential ***
//-----------------------------------------------------------------------------

/// \file pgp_init.c
/// \brief SSX initialization for PgP
///
/// The entry points in this routine are used during initialization.  This
/// code space can be deallocated and reassigned after application
/// initialization if required.

#include "ssx.h"
#include "pgp_vrm.h"
#include "simics_stdio.h"
#include "string_stream.h"

#if USE_RTX_IO
// This file is not avilable to OCC FW builds
#include "rtx_stdio.h"
#endif

// We need to make sure that the PLB arbiter is set up correctly to obtain
// highest performance in the PgP environment, and that PLB error reporting is
// appropriate.

// The PLB arbiter is configured to support fair arbitration of equal-priority
// requests, however we don't set priorities here. The default settings have
// been found to be acceptible so far. We do enable arbiter pipelining however.

// We do set the "plbarb_lockerr" bit so that the PLB arbiter will trap and
// hold the first PLB timeout address.

static void
plb_arbiter_setup()
{
    plb_pacr_t pacr;
    ocb_ocichsw_t oo;

    pacr.value = 0;
    pacr.fields.ppm = 1;        /* Fair arbitration */
    pacr.fields.hbu = 1;        /* High bus utilization */
    pacr.fields.rdp = 1;        /* 2-deep read pipelining */
    pacr.fields.wrp = 1;        /* 2-deep write pipelining */
    mtdcr(PLB_PACR, pacr.value);

    oo.value = in32(OCB_OCICHSW);
    oo.fields.plbarb_lockerr = 1;
    out32(OCB_OCICHSW, oo.value);
}


#if PPC405_MMU_SUPPORT

#include "ppc405_mmu.h"

// MMU regions
//
// The linker script provides a standard set of symbols that define the base
// address and size of each expected section. Any section with a non-0 size
// will be mapped in the MMU using protection attributes appropriate for the
// section.  All sections requiring different MMU attributes must be
// 1KB-aligned.  The OCI control register space is fixed and also mapped by
// the same mechanism.
//
// By default, caching is enabled for all sections other than the sections
// explicitly cache-inhibited.  Configuration options are provided to disable
// caching of text, data and both.  Note that sections that (may) contain code
// and data will be marked cache-inhibited if either text or data is globally
// configured as cache-inhibited.  Also note that "writethrough" can only be
// defined on cacheable data sections.

#ifdef CACHE_INHIBIT_ALL
#define CACHE_INHIBIT_TEXT 1
#define CACHE_INHIBIT_DATA 1
#endif

#if CACHE_INHIBIT_TEXT
#define TEXT_CACHEABILITY_FLAG TLBLO_I
#else
#define TEXT_CACHEABILITY_FLAG 0
#endif

#if CACHE_INHIBIT_DATA
#define DATA_CACHEABILITY_FLAG TLBLO_I
#define WRITETHROUGH_FLAG 0
#else
#define DATA_CACHEABILITY_FLAG 0
#define WRITETHROUGH_FLAG TLBLO_W
#endif


// This structure contains all of the fields necessary to create a MMU
// mapping.

typedef struct {
    SsxAddress base;
    size_t size;
    uint32_t tlbhi_flags;
    uint32_t tlblo_flags;
    Ppc405MmuMap* map;
} MmuRegion;

// The section table along with (default) MMU characteristics.  Global
// Ppc405MmuMap variables are defined for certain sections so that those
// mappings may be later modified.

Ppc405MmuMap G_ex_free_mmu_map;
Ppc405MmuMap G_applet0_mmu_map;
Ppc405MmuMap G_applet1_mmu_map;

static const MmuRegion mmu_regions[] = {

    {(SsxAddress)&_TEXT0_SECTION_BASE,
     (size_t)&_TEXT0_SECTION_SIZE,
     0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0} ,

    {(SsxAddress)&_TEXT1_SECTION_BASE,
     (size_t)&_TEXT1_SECTION_SIZE,
     0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0} ,

    {(SsxAddress)&_RODATA_SECTION_BASE,
     (size_t)&_RODATA_SECTION_SIZE,
     0, DATA_CACHEABILITY_FLAG, 0} ,

    {(SsxAddress)&_NONCACHEABLE_RO_SECTION_BASE,
     (size_t)&_NONCACHEABLE_RO_SECTION_SIZE,
     0, TLBLO_I, 0} ,

    {(SsxAddress)&_NONCACHEABLE_SECTION_BASE,
     (size_t)&_NONCACHEABLE_SECTION_SIZE,
     0, TLBLO_I | TLBLO_WR, 0} ,

    {(SsxAddress)&_WRITETHROUGH_SECTION_BASE,
     (size_t)&_WRITETHROUGH_SECTION_SIZE,
     0, DATA_CACHEABILITY_FLAG | WRITETHROUGH_FLAG | TLBLO_WR, 0} ,

    {(SsxAddress)&_DATA_SECTION_BASE,
     (size_t)&_DATA_SECTION_SIZE,
     0, DATA_CACHEABILITY_FLAG | TLBLO_WR, 0} ,

    {(SsxAddress)&_EX_FREE_SECTION_BASE,
     (size_t)&_EX_FREE_SECTION_SIZE,
     0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_EX | TLBLO_WR,
     &G_ex_free_mmu_map},

    {(SsxAddress)&_APPLET0_SECTION_BASE,
     (size_t)&_APPLET0_SECTION_SIZE,
     0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_WR | TLBLO_EX,
     &G_applet0_mmu_map},

    {(SsxAddress)&_APPLET1_SECTION_BASE,
     (size_t)&_APPLET1_SECTION_SIZE,
     0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_WR | TLBLO_EX,
     &G_applet1_mmu_map},

    {(SsxAddress)OCI_REGISTER_SPACE_BASE,
     (size_t)OCI_REGISTER_SPACE_SIZE,
     0, TLBLO_WR | TLBLO_I | TLBLO_G, 0} ,
};

/// PgP MMU setup
///
/// Run down the mmu_regions[] array and map all regions with non-0 sizes.
/// These are direct maps, setting the effective address to the physical
/// address.  Once the MMU is set up MMU protection is enabled.
///
/// Any OCC mappings of PBA space will have to be done elsewhere, as these
/// memory areas are controlled by pHyp, and the product firmware has no plans
/// to access main memory from the OCC.

static void
pgp_mmu_setup()
{
    int i, regions;

    ppc405_mmu_reset();

    regions = sizeof(mmu_regions) / sizeof(MmuRegion);
    for (i = 0; i < regions; i++) {
        if (mmu_regions[i].size != 0) {
            ppc405_mmu_map(mmu_regions[i].base,
                           mmu_regions[i].base,
                           mmu_regions[i].size,
                           mmu_regions[i].tlbhi_flags,
                           mmu_regions[i].tlblo_flags,
                           mmu_regions[i].map);
        }
    }

    ppc405_mmu_start();
}

#endif  /* PPC405_MMU_SUPPORT */


// I/O Initialization
//
// Initialize the SSX/Simics/Verification Serial I/O channels.  This is done
// early in the initialization to allow initialization code to use printk().
// If the application does not select one of the I/O methods then 'ssxout'
// defaults to the NULL stream and 'stdin', 'stdout' and 'stderr' are
// undefined.

#if USE_TRACE_IO || USE_EPM_IO

WrappingStream G_ssxout
SECTION_ATTRIBUTE(".noncacheable") = {{0}};

uint8_t G_ssxout_buffer[SSXOUT_TRACE_BUFFER_SIZE]
SECTION_ATTRIBUTE(".noncacheable") = {0};

#endif  // USE_TRACE_IO || USE_EPM_IO

static void
io_setup()
{
    //NB: These I/O options are listed in priority order - multiple options may
    //be selected.
#if USE_TRACE_IO

    // If the application chooses to use trace buffer output, the application
    // must define SSXOUT_TRACE_BUFFER_SIZE, and all output streams are merged
    // into a single trace buffer which locks low-level file operations in an
    // SSX_CRITICAL critical secton.

    /// \todo Split trace I/O mode into multiple streams

    wrapping_stream_create(&G_ssxout, &G_ssxout_buffer,
                           SSXOUT_TRACE_BUFFER_SIZE,
                           SSX_FILE_OP_LOCK_CRITICAL);

    stdout = (FILE *)(&G_ssxout);
    stderr = (FILE *)(&G_ssxout);
    ssxout = (FILE *)(&G_ssxout);

#elif USE_EPM_IO

    linear_stream_create(&G_ssxout, &G_ssxout_buffer,
                        SSXOUT_TRACE_BUFFER_SIZE,
                        SSX_FILE_OP_LOCK_CRITICAL);

    stdout = (FILE *)(&G_ssxout);
    stderr = (FILE *)(&G_ssxout);
    ssxout = (FILE *)(&G_ssxout);

#elif USE_RTX_IO

    rtx_stdin_create(&rtx_stdin);
    rtx_stdout_create(&rtx_stdout);
    rtx_stderr_create(&rtx_stderr);

    stdin = (FILE *)(&rtx_stdin);
    stdout = (FILE *)(&rtx_stdout);
    stderr = (FILE *)(&rtx_stderr);
    ssxout = (FILE *)(&rtx_stdout);

    printf("Initialize the RTX stdio.\n");
    printf("RTX stdin is not implemented.\n");

#elif USE_SIMICS_IO

    simics_stdin_create(&simics_stdin);
    simics_stdout_create(&simics_stdout);
    simics_stderr_create(&simics_stderr);

    stdin = (FILE *)(&simics_stdin);
    stdout = (FILE *)(&simics_stdout);
    stderr = (FILE *)(&simics_stderr);
    ssxout = (FILE *)(&simics_stdout);

#endif // I/O Configuration
}


/// PgP environment initial setup.
///
/// This is setup common to all PgP applications.  This setup takes place
/// during boot, before main() is called.

void
__pgp_setup()
{
    // All OCB interrupts are masked.  The SSX/PPC405 Boot code masks PPC405
    // PIT, FIT, and Watchdog interrupts.  All interrupts are also initially
    // set up as noncritical, non-debugged, edge-triggered, active-high, and
    // their status is cleared.  This clarifies IPL debugging as it eliminates
    // spurious "asserted" interrupts until the firmware comes in and actually
    // sets up the interrupt.

    out32(OCB_OIMR0, 0xffffffff);  /* Masked */
    out32(OCB_OIMR1, 0xffffffff);
    out32(OCB_OITR0, 0xffffffff);  /* Edge */
    out32(OCB_OITR1, 0xffffffff);
    out32(OCB_OIEPR0, 0xffffffff); /* Active High */
    out32(OCB_OIEPR1, 0xffffffff);
    out32(OCB_OCIR0, 0);           /* Noncritical */
    out32(OCB_OCIR1, 0);
    out32(OCB_OISR0_AND, 0);       /* Clear Status */
    out32(OCB_OISR1_AND, 0);
    out32(OCB_OUDER0, 0);          /* No Unconditional Debug Event */
    out32(OCB_OUDER1, 0);
    out32(OCB_ODHER0, 0);          /* No Debug Halt Event */
    out32(OCB_ODHER1, 0);

    // Setup requires SCOM, which requires a timeout. Therefore we need to set
    // up a default timebase frequency, which may be overridden during
    // ssx_initialize(). 

    __ssx_timebase_frequency_hz = 600000000;
    __ssx_timebase_frequency_khz = 600000;
    __ssx_timebase_frequency_mhz = 600;

    // Set up I/O.  This is done early in the initialization so that
    // initialization drivers can use printk().

    io_setup();

    // Cache the device identification and chip configuration
    _pgp_get_ids();
    _pgp_get_chip_configuration();

    // Set up the PLB arbiter

    plb_arbiter_setup();

    // If the MMU is enabled the base image MMU programming is set up, and the
    // MMU is activated.

#if PPC405_MMU_SUPPORT
    pgp_mmu_setup();
#endif

    // The PgP Async drivers are initialized.

    async_initialize();
}
OpenPOWER on IntegriCloud