aboutsummaryrefslogtreecommitdiff
path: root/include/hw/ppc/openpic.h
blob: 9c6af8e2076ae3efbc7f91e2f1022676021e6de8 (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
#ifndef OPENPIC_H
#define OPENPIC_H

#include "hw/sysbus.h"
#include "hw/core/cpu.h"
#include "qom/object.h"

#define MAX_CPU     32
#define MAX_MSI     8
#define VID         0x03 /* MPIC version ID */

/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output */
enum {
    OPENPIC_OUTPUT_INT = 0, /* IRQ                       */
    OPENPIC_OUTPUT_CINT,    /* critical IRQ              */
    OPENPIC_OUTPUT_MCK,     /* Machine check event       */
    OPENPIC_OUTPUT_DEBUG,   /* Unconditional debug event */
    OPENPIC_OUTPUT_RESET,   /* Core reset event          */
    OPENPIC_OUTPUT_NB,
};

typedef struct IrqLines { qemu_irq irq[OPENPIC_OUTPUT_NB]; } IrqLines;

#define OPENPIC_MODEL_FSL_MPIC_20 1
#define OPENPIC_MODEL_FSL_MPIC_42 2
#define OPENPIC_MODEL_KEYLARGO    3

#define OPENPIC_MAX_SRC     256
#define OPENPIC_MAX_TMR     4
#define OPENPIC_MAX_IPI     4
#define OPENPIC_MAX_IRQ     (OPENPIC_MAX_SRC + OPENPIC_MAX_IPI + \
                             OPENPIC_MAX_TMR)

/* KeyLargo */
#define KEYLARGO_MAX_CPU  4
#define KEYLARGO_MAX_EXT  64
#define KEYLARGO_MAX_IPI  4
#define KEYLARGO_MAX_IRQ  (64 + KEYLARGO_MAX_IPI)
#define KEYLARGO_MAX_TMR  0
#define KEYLARGO_IPI_IRQ  (KEYLARGO_MAX_EXT) /* First IPI IRQ */
/* Timers don't exist but this makes the code happy... */
#define KEYLARGO_TMR_IRQ  (KEYLARGO_IPI_IRQ + KEYLARGO_MAX_IPI)

typedef struct FslMpicInfo {
    int max_ext;
} FslMpicInfo;

typedef enum IRQType {
    IRQ_TYPE_NORMAL = 0,
    IRQ_TYPE_FSLINT,        /* FSL internal interrupt -- level only */
    IRQ_TYPE_FSLSPECIAL,    /* FSL timer/IPI interrupt, edge, no polarity */
} IRQType;

/*
 * Round up to the nearest 64 IRQs so that the queue length
 * won't change when moving between 32 and 64 bit hosts.
 */
#define IRQQUEUE_SIZE_BITS ROUND_UP(OPENPIC_MAX_IRQ, 64)

typedef struct IRQQueue {
    unsigned long *queue;
    int32_t queue_size; /* Only used for VMSTATE_BITMAP */
    int next;
    int priority;
} IRQQueue;

typedef struct IRQSource {
    uint32_t ivpr;  /* IRQ vector/priority register */
    uint32_t idr;   /* IRQ destination register */
    uint32_t destmask; /* bitmap of CPU destinations */
    int last_cpu;
    int output;     /* IRQ level, e.g. OPENPIC_OUTPUT_INT */
    int pending;    /* TRUE if IRQ is pending */
    IRQType type;
    bool level:1;   /* level-triggered */
    bool nomask:1;  /* critical interrupts ignore mask on some FSL MPICs */
} IRQSource;

#define IVPR_MASK_SHIFT       31
#define IVPR_MASK_MASK        (1U << IVPR_MASK_SHIFT)
#define IVPR_ACTIVITY_SHIFT   30
#define IVPR_ACTIVITY_MASK    (1U << IVPR_ACTIVITY_SHIFT)
#define IVPR_MODE_SHIFT       29
#define IVPR_MODE_MASK        (1U << IVPR_MODE_SHIFT)
#define IVPR_POLARITY_SHIFT   23
#define IVPR_POLARITY_MASK    (1U << IVPR_POLARITY_SHIFT)
#define IVPR_SENSE_SHIFT      22
#define IVPR_SENSE_MASK       (1U << IVPR_SENSE_SHIFT)

#define IVPR_PRIORITY_MASK     (0xFU << 16)
#define IVPR_PRIORITY(_ivprr_) ((int)(((_ivprr_) & IVPR_PRIORITY_MASK) >> 16))
#define IVPR_VECTOR(opp, _ivprr_) ((_ivprr_) & (opp)->vector_mask)

/* IDR[EP/CI] are only for FSL MPIC prior to v4.0 */
#define IDR_EP      0x80000000  /* external pin */
#define IDR_CI      0x40000000  /* critical interrupt */

typedef struct OpenPICTimer {
    uint32_t tccr;  /* Global timer current count register */
    uint32_t tbcr;  /* Global timer base count register */
    int                   n_IRQ;
    bool                  qemu_timer_active; /* Is the qemu_timer is running? */
    struct QEMUTimer     *qemu_timer;
    struct OpenPICState  *opp;          /* Device timer is part of. */
    /*
     * The QEMU_CLOCK_VIRTUAL time (in ns) corresponding to the last
     * current_count written or read, only defined if qemu_timer_active.
     */
    uint64_t              origin_time;
} OpenPICTimer;

typedef struct OpenPICMSI {
    uint32_t msir;   /* Shared Message Signaled Interrupt Register */
} OpenPICMSI;

typedef struct IRQDest {
    int32_t ctpr; /* CPU current task priority */
    IRQQueue raised;
    IRQQueue servicing;
    qemu_irq *irqs;

    /* Count of IRQ sources asserting on non-INT outputs */
    uint32_t outputs_active[OPENPIC_OUTPUT_NB];
} IRQDest;

#define TYPE_OPENPIC "openpic"
OBJECT_DECLARE_SIMPLE_TYPE(OpenPICState, OPENPIC)

struct OpenPICState {
    /*< private >*/
    SysBusDevice parent_obj;
    /*< public >*/

    MemoryRegion mem;

    /* Behavior control */
    FslMpicInfo *fsl;
    uint32_t model;
    uint32_t flags;
    uint32_t nb_irqs;
    uint32_t vid;
    uint32_t vir; /* Vendor identification register */
    uint32_t vector_mask;
    uint32_t tfrr_reset;
    uint32_t ivpr_reset;
    uint32_t idr_reset;
    uint32_t brr1;
    uint32_t mpic_mode_mask;

    /* Sub-regions */
    MemoryRegion sub_io_mem[6];

    /* Global registers */
    uint32_t frr; /* Feature reporting register */
    uint32_t gcr; /* Global configuration register  */
    uint32_t pir; /* Processor initialization register */
    uint32_t spve; /* Spurious vector register */
    uint32_t tfrr; /* Timer frequency reporting register */
    /* Source registers */
    IRQSource src[OPENPIC_MAX_IRQ];
    /* Local registers per output pin */
    IRQDest dst[MAX_CPU];
    uint32_t nb_cpus;
    /* Timer registers */
    OpenPICTimer timers[OPENPIC_MAX_TMR];
    uint32_t max_tmr;

    /* Shared MSI registers */
    OpenPICMSI msi[MAX_MSI];
    uint32_t max_irq;
    uint32_t irq_ipi0;
    uint32_t irq_tim0;
    uint32_t irq_msi;
};

#endif /* OPENPIC_H */