summaryrefslogtreecommitdiffstats
path: root/pk/ppe42/ppe42_irq.h
blob: 89948d6025f7b8d0eede172ffdf73b28636f43cf (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
#ifndef __PPE42_IRQ_H__
#define __PPE42_IRQ_H__
//-----------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2014
// *! All Rights Reserved -- Property of IBM
// *! *** IBM Confidential ***
//-----------------------------------------------------------------------------

/// \file ppe42_irq.h
/// \brief PPE42 interrupt handling for PK
///
/// Interrupt handling protocols and interrupt controller programming are
/// inherently non-portable, however PK defines APIs that may be useful among
/// different machines.
///


// Define pseudo-IRQ numbers for PPE42 built-in interrupts.  These numbers
// will appear in bits 16:23 of SPRG0 (__PkKernelContext) when the handlers
// are active

#define PPE42_EXC_MACHINE_CHECK         0x50
#define PPE42_EXC_DATA_STORAGE          0x53
#define PPE42_EXC_INSTRUCTION_STORAGE   0x54
#define PPE42_EXC_ALIGNMENT             0x56
#define PPE42_EXC_PROGRAM               0x57
#define PPE42_IRQ_DEC                   0x58
#define PPE42_IRQ_FIT                   0x59
#define PPE42_IRQ_WATCHDOG              0x5A


//  Unhandled exceptions default to a kernel panic, but the application can
//  override these definition.  Note that the exception area only allocates 32
//  bytes (8 instructions) to an unhandled exception, so any redefinition
//  would most likely be a branch to an application-defined handler.

#ifndef PPE42_MACHINE_CHECK_HANDLER
#define PPE42_MACHINE_CHECK_HANDLER        PK_PANIC(0x0200)
#endif

#ifndef PPE42_DATA_STORAGE_HANDLER
#define PPE42_DATA_STORAGE_HANDLER         PK_PANIC(0x0300)
#endif

#ifndef PPE42_INSTRUCTION_STORAGE_HANDLER
#define PPE42_INSTRUCTION_STORAGE_HANDLER  PK_PANIC(0x0400)
#endif

#ifndef PPE42_ALIGNMENT_HANDLER
#define PPE42_ALIGNMENT_HANDLER            PK_PANIC(0x0600)
#endif


////////////////////////////////////////////////////////////////////////////
//  PK API
////////////////////////////////////////////////////////////////////////////

#ifndef __ASSEMBLER__

/// An IRQ handler takes 2 arguments:
/// \arg \c arg - Private handler data installed by \c ssx_irq_setup() or
///                   \c ssx_irq_handler_set().
/// \arg \c irq     - The IRQ id; to enable a generic handler to manipulate
///                   its own interrupt status .

typedef void (*PkIrqHandler)(void* arg, PkIrqId irq);

/// Declare a subroutine as an IRQ handler

#define PK_IRQ_HANDLER(f) void f(void* arg, PkIrqId irq)

int pk_irq_setup(PkIrqId irq,
                  int      polarity,
                  int      trigger);

int pk_irq_handler_set(PkIrqId      irq,
                        PkIrqHandler handler,
                        void*         arg);

void pk_irq_enable(PkIrqId irq);
void pk_irq_disable(PkIrqId irq);
void pk_irq_statusclear(PkIrqId irq);

PK_IRQ_HANDLER(__ppe42_default_irq_handler);
PK_IRQ_HANDLER(__ppe42_phantom_irq_handler);


int
ppe42_fit_setup(int tcr_fp, PkIrqHandler handler, void* arg);


///  The address of the optional FIT interrupt handler

UNLESS__PPE42_IRQ_CORE_C__(extern)
volatile
PkIrqHandler __ppe42_fit_routine;


/// The private data of the optional FIT interrupt handler

UNLESS__PPE42_IRQ_CORE_C__(extern)
volatile
void* __ppe42_fit_arg;


int
ppe42_watchdog_setup(int tcr_wp, int tcr_wrc, 
                      PkIrqHandler handler, void* arg);


///  The address of the optional Watchdog interrupt handler

UNLESS__PPE42_IRQ_CORE_C__(extern)
volatile
PkIrqHandler __ppe42_watchdog_routine;


/// The private data of the optional Watchdog interrupt handler

UNLESS__PPE42_IRQ_CORE_C__(extern)
volatile
void* __ppe42_watchdog_arg;


int
ppe42_debug_setup(PkIrqHandler handler, void* arg);


///  The address of the optional Debug interrupt handler

UNLESS__PPE42_IRQ_CORE_C__(extern)
volatile
PkIrqHandler __ppe42_debug_routine;


/// The private data of the optional Watchdog interrupt handler

UNLESS__PPE42_IRQ_CORE_C__(extern)
volatile
void* __ppe42_debug_arg;

#endif  /* __ASSEMBLER__ */

//  It's hard to be portable and get all of the definitions and headers in the
//  correct order.  We need to bring in the system IRQ header here.

#ifdef HWMACRO_GPE
#include "gpe_irq.h"
#else
#ifdef HWMACRO_STD
#include "std_irq.h"
#endif
#endif

/// \page ppe42_irq_macros_page PPE42 PK IRQ Assembler Macros
///
///
        
#ifndef __ASSEMBLER__


///  This structure holds the interrupt handler routine addresses and private
///  data.  Assembler code assumes the given structure layout, so any changes
///  to this structure will need to be reflected down into the interrupt
///  dispatch assembler code.

typedef struct {
    PkIrqHandler handler;
    void         *arg;
} Ppe42IrqHandler;


#ifdef STATIC_IRQ_TABLE

#define IRQ_HANDLER(func, arg) \
    {func, arg},

#define IRQ_HANDLER_DEFAULT \
    {__ppe42_default_irq_handler, 0},

#define EXTERNAL_IRQ_TABLE_END \
    {__ppe42_phantom_irq_handler, 0}\
};

#define EXTERNAL_IRQ_TABLE_START \
    Ppe42IrqHandler __ppe42_irq_handlers[EXTERNAL_IRQS + 1] = \
{

#else

#define EXTERNAL_IRQ_TABLE_START

#define IRQ_HANDLER(func, arg)

#define IRQ_HANDLER_DEFAULT

#define EXTERNAL_IRQ_TABLE_END

#endif /*STATIC_IRQ_TABLE*/

/// Interrupt handlers for real (implemented interrupts) plus one for the phantom interrupt handler
extern Ppe42IrqHandler __ppe42_irq_handlers[EXTERNAL_IRQS + 1];


/// The 'phantom interrupt' handler
///
/// A 'phantom' interrupt occurs when the interrupt handling code in the
/// kernel is entered, but no interrupt is found pending in the controller.
/// This is considered a serious bug, as it indictates a short window
/// condition where a level-sensitive interrupt has been asserted and then
/// quickly deasserted before it can be handled.

UNLESS__PPE42_IRQ_CORE_C__(extern)
Ppe42IrqHandler __ppe42_phantom_irq;
    
#endif  /* __ASSEMBLER__ */

#endif  /* __PPE42_IRQ_H__ */
OpenPOWER on IntegriCloud