diff options
Diffstat (limited to 'arch/powerpc/include/asm/xics.h')
-rw-r--r-- | arch/powerpc/include/asm/xics.h | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/xics.h b/arch/powerpc/include/asm/xics.h new file mode 100644 index 000000000000..b183a4062011 --- /dev/null +++ b/arch/powerpc/include/asm/xics.h | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * Common definitions accross all variants of ICP and ICS interrupt | ||
3 | * controllers. | ||
4 | */ | ||
5 | |||
6 | #ifndef _XICS_H | ||
7 | #define _XICS_H | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | |||
11 | #define XICS_IPI 2 | ||
12 | #define XICS_IRQ_SPURIOUS 0 | ||
13 | |||
14 | /* Want a priority other than 0. Various HW issues require this. */ | ||
15 | #define DEFAULT_PRIORITY 5 | ||
16 | |||
17 | /* | ||
18 | * Mark IPIs as higher priority so we can take them inside interrupts that | ||
19 | * arent marked IRQF_DISABLED | ||
20 | */ | ||
21 | #define IPI_PRIORITY 4 | ||
22 | |||
23 | /* The least favored priority */ | ||
24 | #define LOWEST_PRIORITY 0xFF | ||
25 | |||
26 | /* The number of priorities defined above */ | ||
27 | #define MAX_NUM_PRIORITIES 3 | ||
28 | |||
29 | /* Native ICP */ | ||
30 | extern int icp_native_init(void); | ||
31 | |||
32 | /* PAPR ICP */ | ||
33 | extern int icp_hv_init(void); | ||
34 | |||
35 | /* ICP ops */ | ||
36 | struct icp_ops { | ||
37 | unsigned int (*get_irq)(void); | ||
38 | void (*eoi)(struct irq_data *d); | ||
39 | void (*set_priority)(unsigned char prio); | ||
40 | void (*teardown_cpu)(void); | ||
41 | void (*flush_ipi)(void); | ||
42 | #ifdef CONFIG_SMP | ||
43 | void (*cause_ipi)(int cpu, unsigned long data); | ||
44 | irq_handler_t ipi_action; | ||
45 | #endif | ||
46 | }; | ||
47 | |||
48 | extern const struct icp_ops *icp_ops; | ||
49 | |||
50 | /* Native ICS */ | ||
51 | extern int ics_native_init(void); | ||
52 | |||
53 | /* RTAS ICS */ | ||
54 | extern int ics_rtas_init(void); | ||
55 | |||
56 | /* ICS instance, hooked up to chip_data of an irq */ | ||
57 | struct ics { | ||
58 | struct list_head link; | ||
59 | int (*map)(struct ics *ics, unsigned int virq); | ||
60 | void (*mask_unknown)(struct ics *ics, unsigned long vec); | ||
61 | long (*get_server)(struct ics *ics, unsigned long vec); | ||
62 | int (*host_match)(struct ics *ics, struct device_node *node); | ||
63 | char data[]; | ||
64 | }; | ||
65 | |||
66 | /* Commons */ | ||
67 | extern unsigned int xics_default_server; | ||
68 | extern unsigned int xics_default_distrib_server; | ||
69 | extern unsigned int xics_interrupt_server_size; | ||
70 | extern struct irq_host *xics_host; | ||
71 | |||
72 | struct xics_cppr { | ||
73 | unsigned char stack[MAX_NUM_PRIORITIES]; | ||
74 | int index; | ||
75 | }; | ||
76 | |||
77 | DECLARE_PER_CPU(struct xics_cppr, xics_cppr); | ||
78 | |||
79 | static inline void xics_push_cppr(unsigned int vec) | ||
80 | { | ||
81 | struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | ||
82 | |||
83 | if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1)) | ||
84 | return; | ||
85 | |||
86 | if (vec == XICS_IPI) | ||
87 | os_cppr->stack[++os_cppr->index] = IPI_PRIORITY; | ||
88 | else | ||
89 | os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY; | ||
90 | } | ||
91 | |||
92 | static inline unsigned char xics_pop_cppr(void) | ||
93 | { | ||
94 | struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | ||
95 | |||
96 | if (WARN_ON(os_cppr->index < 1)) | ||
97 | return LOWEST_PRIORITY; | ||
98 | |||
99 | return os_cppr->stack[--os_cppr->index]; | ||
100 | } | ||
101 | |||
102 | static inline void xics_set_base_cppr(unsigned char cppr) | ||
103 | { | ||
104 | struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | ||
105 | |||
106 | /* we only really want to set the priority when there's | ||
107 | * just one cppr value on the stack | ||
108 | */ | ||
109 | WARN_ON(os_cppr->index != 0); | ||
110 | |||
111 | os_cppr->stack[0] = cppr; | ||
112 | } | ||
113 | |||
114 | static inline unsigned char xics_cppr_top(void) | ||
115 | { | ||
116 | struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | ||
117 | |||
118 | return os_cppr->stack[os_cppr->index]; | ||
119 | } | ||
120 | |||
121 | DECLARE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message); | ||
122 | |||
123 | extern void xics_init(void); | ||
124 | extern void xics_setup_cpu(void); | ||
125 | extern void xics_update_irq_servers(void); | ||
126 | extern void xics_set_cpu_giq(unsigned int gserver, unsigned int join); | ||
127 | extern void xics_mask_unknown_vec(unsigned int vec); | ||
128 | extern irqreturn_t xics_ipi_dispatch(int cpu); | ||
129 | extern int xics_smp_probe(void); | ||
130 | extern void xics_register_ics(struct ics *ics); | ||
131 | extern void xics_teardown_cpu(void); | ||
132 | extern void xics_kexec_teardown_cpu(int secondary); | ||
133 | extern void xics_migrate_irqs_away(void); | ||
134 | #ifdef CONFIG_SMP | ||
135 | extern int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask, | ||
136 | unsigned int strict_check); | ||
137 | #else | ||
138 | #define xics_get_irq_server(virq, cpumask, strict_check) (xics_default_server) | ||
139 | #endif | ||
140 | |||
141 | |||
142 | #endif /* _XICS_H */ | ||