summaryrefslogtreecommitdiffstats
path: root/pk/std/std_irq_config.h
blob: a3d9426eac93431caf1b9ad9d12b06f23d42cb81 (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
#ifndef __STD_IRQ_CONFIG_H__
#define __STD_IRQ_CONFIG_H__
//-----------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2015
// *! All Rights Reserved -- Property of IBM
// *! *** IBM Confidential ***
//-----------------------------------------------------------------------------

/// \file std_irq_config.h
/// \brief Contains data and macros pertaining to external interrupt
/// configuration for a standard PPE.
///

/// This constant is used to define the size of the table of interrupt handler
/// structures as well as a limit for error checking. 
#define EXTERNAL_IRQS 64

// Standard interrupt type values (level or edge)
#define STD_IRQ_TYPE_LEVEL            0
#define STD_IRQ_TYPE_EDGE             1

// Standard interrupt polarity values (high or low, rising falling)
#define STD_IRQ_POLARITY_LO           0
#define STD_IRQ_POLARITY_FALLING      0
#define STD_IRQ_POLARITY_HI           1
#define STD_IRQ_POLARITY_RISING       1

// Standard interrupt mask values (masked or enabled)
#define STD_IRQ_MASKED                0
#define STD_IRQ_ENABLED               1

// Fail to compile if the application does not define this
#ifndef APPCFG_EXT_IRQS_CONFIG
#error "APPCFG_EXT_IRQS_CONFIG must be defined in pk_app_cfg.h"
#endif

// Fail to compile if the application does not define this
#ifndef APPCFG_IRQ_INVALID_MASK
#error "APPCFG_IRQ_INVALID_MASK must be defined in pk_app_cfg.h"
#endif

#ifndef __ASSEMBLER__

/// This expression recognizes only those IRQ numbers that have named
/// (non-reserved) interrupts in the standard PPE interrupt controller.
#define STD_IRQ_VALID(irq) \
    ({unsigned __irq = (unsigned)(irq);         \
        ((__irq < EXTERNAL_IRQS) &&             \
         ((STD_IRQ_MASK64(__irq) &              \
            APPCFG_IRQ_INVALID_MASK) == 0));})

/// This is a 64-bit mask, with big-endian bit 'irq' set.
#define STD_IRQ_MASK64(irq) (0x8000000000000000ull >> (irq))

#else

//Untyped assembler version of STD_IRQ_MASK64
#define STD_IRQ_MASK64(irq) (0x8000000000000000 >> (irq))

#endif  /* __ASSEMBLER__ */

#ifndef __ASSEMBLER__
/// These globals are statically initialized elsewhere
extern uint64_t g_ext_irqs_type;
extern uint64_t g_ext_irqs_valid;
extern uint64_t g_ext_irqs_polarity;
extern uint64_t g_ext_irqs_enable;
#endif

#ifdef __ASSEMBLER__
/// 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 a standard PPE
    .macro .std_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_valid )
#.error "###### .std_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 > (EXTERNAL_IRQS - 1)))
                .error "###### .std_irq_config: invalid irq number \irq_num ######"
            .elseif ((.ext_irqs_valid & (1 << ( EXTERNAL_IRQS - 1 - \irq_num ))) == 0 )
                .error "###### .std_irq_config: Attempt to configure invalid irq number \irq_num ######" 
            .elseif (.ext_irqs_defd & (1 << ( EXTERNAL_IRQS - 1 - \irq_num )))
                .error "###### .std_irq_config: duplicate definition for irq \irq_num ######"
            .else
                .ext_irqs_defd = .ext_irqs_defd | (1 << ( EXTERNAL_IRQS - 1 - \irq_num ))
            .endif

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

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

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

            .std_irq_config \parms
        .endif
    .endm

    //Top level macro for generating interrupt configuration globals for a standard PPE
    .macro .std_irq_cfg_bitmaps
        .ext_irqs_valid = ~(APPCFG_IRQ_INVALID_MASK)
        .ext_irqs_type = 0
        .ext_irqs_polarity = 0
        .ext_irqs_enable = 0
        .irq_mask = 0
        .ext_irqs_defd = 0
        .std_irq_config APPCFG_EXT_IRQS_CONFIG
    .endm

#endif /*__ASSEMBLER__*/

#endif /*__STD_IRQ_CONFIG_H__*/ 
OpenPOWER on IntegriCloud