summaryrefslogtreecommitdiffstats
path: root/src/include/occhw_irq_config.h
blob: 44e99dcfa29cdb103d401c502e3dc27c24eb778b (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
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/include/occhw_irq_config.h $                              */
/*                                                                        */
/* OpenPOWER OnChipController Project                                     */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2016                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef __OCCHW_IRQ_CONFIG_H__
#define __OCCHW_IRQ_CONFIG_H__

/// \file occhw_irq_config.h
/// \brief Contains data and macros pertaining to external interrupt routing
///        and configuration for processors running in the OCC complex.
///

/// Designate an instance (GPE 0-3 or 405) to own the routing registers
/// 0-3 -> GPE, 4 -> 405
#ifndef OCCHW_IRQ_ROUTE_OWNER
    #define OCCHW_IRQ_ROUTE_OWNER 4
#endif

/// This macro should be defined in the pk_app_cfg.h file for external interrupts
/// that are to be used by the OCC instance.  If not defined elsewhere then
/// interrupts owned by this instance will have the default configuration and be
/// masked.
#ifndef OCCHW_EXT_IRQS_CONFIG
    #define OCCHW_EXT_IRQS_CONFIG
#endif

#ifndef __ASSEMBLER__
    /// These globals are statically initialized elsewhere
    extern uint64_t g_ext_irqs_routeA;
    extern uint64_t g_ext_irqs_routeB;
    extern uint64_t g_ext_irqs_routeC;
    extern uint64_t g_ext_irqs_type;
    extern uint64_t g_ext_irqs_owned;
    extern uint64_t g_ext_irqs_polarity;
    extern uint64_t g_ext_irqs_enable;

    #define OCCHW_IRQ_OWNED(irq) ((OCCHW_IRQ_MASK64(irq) & g_ext_irqs_owned) != 0)

#endif

/// Convert a GPE instance ID to an IRQ target ID
#define OCCHW_GPEID_2_IRQTARGET(gpe_id) (gpe_id + OCCHW_IRQ_TARGET_ID_GPE0)

/// Add a pseudo target to indicate that an interrupt is not owned by anyone
#define OCCHW_IRQ_TARGET_ID_NONE    8

/// Default interrupt routing table
#ifndef OCCHW_IRQ_ROUTES
#define OCCHW_IRQ_ROUTES \
    OCCHW_IRQ_DEBUGGER                      OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_TRACE_TRIGGER                 OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_OCC_ERROR                     OCCHW_IRQ_TARGET_ID_GPE2\
    OCCHW_IRQ_PBA_ERROR                     OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_SRT_ERROR                     OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_GPE0_HALT                     OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_GPE1_HALT                     OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_GPE2_HALT                     OCCHW_IRQ_TARGET_ID_GPE3 \
    OCCHW_IRQ_GPE3_HALT                     OCCHW_IRQ_TARGET_ID_GPE2 \
    OCCHW_IRQ_PPC405_HALT                   OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_OCB_ERROR                     OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_SPIPSS_ERROR                  OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_CHECK_STOP_PPC405             OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_CHECK_STOP_GPE0               OCCHW_IRQ_TARGET_ID_GPE0 \
    OCCHW_IRQ_CHECK_STOP_GPE1               OCCHW_IRQ_TARGET_ID_GPE1 \
    OCCHW_IRQ_CHECK_STOP_GPE2               OCCHW_IRQ_TARGET_ID_GPE2 \
    OCCHW_IRQ_CHECK_STOP_GPE3               OCCHW_IRQ_TARGET_ID_GPE3 \
    OCCHW_IRQ_OCC_MALF_ALERT                OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_ADU_MALF_ALERT                OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_EXTERNAL_TRAP                 OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_IVRM_PVREF_ERROR              OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_OCC_TIMER0                    OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_OCC_TIMER1                    OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_HALT_PSTATES                  OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_IPI_SCOM                      OCCHW_IRQ_TARGET_ID_GPE1 \
    OCCHW_IRQ_IPI0_HI_PRIORITY              OCCHW_IRQ_TARGET_ID_GPE0 \
    OCCHW_IRQ_IPI1_HI_PRIORITY              OCCHW_IRQ_TARGET_ID_GPE1 \
    OCCHW_IRQ_IPI2_HI_PRIORITY              OCCHW_IRQ_TARGET_ID_GPE2 \
    OCCHW_IRQ_IPI3_HI_PRIORITY              OCCHW_IRQ_TARGET_ID_GPE3 \
    OCCHW_IRQ_IPI4_HI_PRIORITY              OCCHW_IRQ_TARGET_ID_405_CRIT \
    OCCHW_IRQ_ADCFSM_ONGOING                OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_RESERVED_31                   OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_PBAX_OCC_SEND                 OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_PBAX_OCC_PUSH0                OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_PBAX_OCC_PUSH1                OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_PBA_BCDE_ATTN                 OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_PBA_BCUE_ATTN                 OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_STRM0_PULL                    OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_STRM0_PUSH                    OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_STRM1_PULL                    OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_STRM1_PUSH                    OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_STRM2_PULL                    OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_STRM2_PUSH                    OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_STRM3_PULL                    OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_STRM3_PUSH                    OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_PMC_PCB_INTR_TYPE0_PENDING    OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_PMC_PCB_INTR_TYPE1_PENDING    OCCHW_IRQ_TARGET_ID_GPE2 \
    OCCHW_IRQ_PMC_PCB_INTR_TYPE2_PENDING    OCCHW_IRQ_TARGET_ID_GPE3 \
    OCCHW_IRQ_PMC_PCB_INTR_TYPE3_PENDING    OCCHW_IRQ_TARGET_ID_GPE3 \
    OCCHW_IRQ_PMC_PCB_INTR_TYPE4_PENDING    OCCHW_IRQ_TARGET_ID_GPE2 \
    OCCHW_IRQ_PMC_PCB_INTR_TYPE5_PENDING    OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_PMC_PCB_INTR_TYPE6_PENDING    OCCHW_IRQ_TARGET_ID_GPE3 \
    OCCHW_IRQ_PMC_PCB_INTR_TYPE7_PENDING    OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_PMC_O2S_0A_ONGOING            OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_PMC_O2S_0B_ONGOING            OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_PMC_O2S_1A_ONGOING            OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_PMC_O2S_1B_ONGOING            OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_PSSBRIDGE_ONGOING             OCCHW_IRQ_TARGET_ID_NONE \
    OCCHW_IRQ_IPI0_LO_PRIORITY              OCCHW_IRQ_TARGET_ID_GPE0 \
    OCCHW_IRQ_IPI1_LO_PRIORITY              OCCHW_IRQ_TARGET_ID_GPE1 \
    OCCHW_IRQ_IPI2_LO_PRIORITY              OCCHW_IRQ_TARGET_ID_GPE2 \
    OCCHW_IRQ_IPI3_LO_PRIORITY              OCCHW_IRQ_TARGET_ID_GPE3 \
    OCCHW_IRQ_IPI4_LO_PRIORITY              OCCHW_IRQ_TARGET_ID_405_NONCRIT \
    OCCHW_IRQ_RESERVED_63                   OCCHW_IRQ_TARGET_ID_NONE
#endif

// convenience macros for retrieving the IPI IRQ numbers for an OCC instance
// NOTE: this assumes the IPI IRQs are routed as shown above
#define OCCHW_IPI_LO_IRQ(instance_id) (OCCHW_IRQ_IPI0_LO_PRIORITY + instance_id)
#define OCCHW_IPI_HI_IRQ(instance_id) (OCCHW_IRQ_IPI0_HI_PRIORITY + instance_id)

#ifdef __ASSEMBLER__
// *INDENT-OFF*
/// These macros aid in the initialization of the external interrupt globals.  I would
/// prefer to use CPP macros, but they don't support recursive macros which I use to
/// convert the variable number of interrupts that a processor can control into static
/// bitmaps used by __hwmacro_setup() at runtime.


    //helper macro for setting up the irq configuration bitmaps for all entities in the occ complex
    .macro .occhw_irq_config irq_num=-1 irq_type=-1 irq_polarity=-1 irq_mask=-1 parms:vararg
        .if (( \irq_num == -1 ) && ( \irq_type == -1 ) && ( \irq_polarity == -1 ) && ( \irq_mask == -1 ))
            .if ( .ext_irqs_defd != .ext_irqs_owned )
                .error "###### .occhw_irq_config: Missing configuration for one or more interrupts ######"
            .endif

            .section .sdata
            .align 3
            .global g_ext_irqs_type
            .global g_ext_irqs_polarity
            .global g_ext_irqs_enable
            g_ext_irqs_polarity:
            .quad .ext_irqs_polarity
            g_ext_irqs_type:
            .quad .ext_irqs_type
            g_ext_irqs_enable:
            .quad .ext_irqs_enable
        .else
            .if (( \irq_num < 0 ) || ( \irq_num > (OCCHW_IRQS - 1)))
                .error "###### .occhw_irq_config: invalid irq number \irq_num ######"
            .elseif ((.ext_irqs_owned & (1 << ( OCCHW_IRQS - 1 - \irq_num ))) == 0 )
                .error "###### .occhw_irq_config: Attempt to configure unowned irq number \irq_num ######"
            .elseif (.ext_irqs_defd & (1 << ( OCCHW_IRQS - 1 - \irq_num )))
                .error "###### .occhw_irq_config: duplicate definition for irq \irq_num ######"
            .else
                .ext_irqs_defd = .ext_irqs_defd | (1 << ( OCCHW_IRQS - 1 - \irq_num ))
            .endif

            .if (( \irq_type < 0 ) || ( \irq_type > 1 ))
                .error "###### .occhw_irq_config: invalid/unspecified irq type \irq_type for irq \irq_num ######"
            .else
                .ext_irqs_type = .ext_irqs_type | ( \irq_type << ( OCCHW_IRQS - 1 - \irq_num ))
            .endif

            .if (( \irq_polarity < 0 ) || ( \irq_polarity > 1 ))
                .error "###### .occhw_irq_config: invalid/unspecified irq polarity ( \irq_polarity ) for irq \irq_num ######"
            .else
                .ext_irqs_polarity = .ext_irqs_polarity | ( \irq_polarity << ( OCCHW_IRQS - 1 - \irq_num ))
            .endif

            .if (( \irq_mask < 0 ) || ( \irq_mask > 1 ))
                .error "###### .occhw_irq_config: invalid/unspecified irq mask ( \irq_mask ) for irq \irq_num ######"
            .else
                .ext_irqs_enable = .ext_irqs_enable | ( \irq_mask << ( OCCHW_IRQS - 1 - \irq_num ))
            .endif

            .occhw_irq_config \parms
        .endif
    .endm

    //recursive helper macro for setting up the irq route bitmaps for all entities in the occ complex
    //
    //Once completed, g_ext_irqs_route(A,B,C) will hold the correct initialization values and
    //g_ext_irqs_owned will hold a bitmap of interrupts owned by this OCC instance
    .macro .occhw_irq_route irq_num=-1 irq_route=-1 parms:vararg
        .if (( \irq_num == -1 ) && ( \irq_route == -1 ))
            .section .sdata
            .align 3
            .global g_ext_irqs_routeA
            .global g_ext_irqs_routeB
            .global g_ext_irqs_routeC
            .global g_ext_irqs_owned
            g_ext_irqs_routeA:
            .quad .ext_irqs_routeA
            g_ext_irqs_routeB:
            .quad .ext_irqs_routeB
            g_ext_irqs_routeC:
            .quad .ext_irqs_routeC
            g_ext_irqs_owned:
            .quad .ext_irqs_owned
        .else
            .if (( \irq_num < 0) || ( \irq_num > (OCCHW_IRQS - 1)))
                   .error "###### .occhw_irq_route: invalid irq number \irq_num ######"
            .elseif .ext_irqs_defd & (1 << ( OCCHW_IRQS - 1 - \irq_num ))
                .error "###### .occhw_irq_route: Route for irq \irq_num is already defined ######"
            .else
                .ext_irqs_defd = .ext_irqs_defd | (1 << ( OCCHW_IRQS - 1 - \irq_num ))
            .endif

            .if (( \irq_route < 0) || ( \irq_route > 8 ))
                .error "###### .occhw_irq_route: route # \irq_route is invalid for irq # \irq_num ######"
            .endif

            .irq_mask = 1 << ( OCCHW_IRQS - 1 - \irq_num)
            .if \irq_route & 4
                .ext_irqs_routeA = .ext_irqs_routeA | .irq_mask
            .endif

            .if \irq_route & 2
                .ext_irqs_routeB = .ext_irqs_routeB | .irq_mask
            .endif

            .if \irq_route & 1
                .ext_irqs_routeC = .ext_irqs_routeC | .irq_mask
            .endif

            .if ( \irq_route == 8 )
                //do nothing, this irq is not owned by any OCC processor
            .elseif (( \irq_route < 4 ) && ( APPCFG_OCC_INSTANCE_ID == 4 ))
                .ext_irqs_owned = .ext_irqs_owned | .irq_mask
            .elseif ( \irq_route == (OCCHW_IRQ_TARGET_ID_GPE0 + APPCFG_OCC_INSTANCE_ID))
                .ext_irqs_owned = .ext_irqs_owned | .irq_mask
            .endif

            .occhw_irq_route \parms
        .endif
    .endm

    //Top level macro for generating interrupt routing/configuration globals for all entities in the occ complex
    .macro .occhw_irq_cfg_bitmaps
        .ext_irqs_routeA = 0
        .ext_irqs_routeB = 0
        .ext_irqs_routeC = 0
        .ext_irqs_owned = 0
        .ext_irqs_type = 0
        .ext_irqs_polarity = 0
        .ext_irqs_enable = 0
        .ext_irqs_defd = 0
        .irq_mask = 0
        .occhw_irq_route OCCHW_IRQ_ROUTES
        .ext_irqs_defd = 0
        .occhw_irq_config APPCFG_EXT_IRQS_CONFIG
    .endm

// *INDENT-ON*
#endif /*__ASSEMBLER__*/

#endif /*__OCCHW_IRQ_CONFIG_H__*/
OpenPOWER on IntegriCloud