1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Common definitions across all variants of ICP and ICS interrupt
4*4882a593Smuzhiyun * controllers.
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #ifndef _XICS_H
8*4882a593Smuzhiyun #define _XICS_H
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/interrupt.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #define XICS_IPI 2
13*4882a593Smuzhiyun #define XICS_IRQ_SPURIOUS 0
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun /* Want a priority other than 0. Various HW issues require this. */
16*4882a593Smuzhiyun #define DEFAULT_PRIORITY 5
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun /*
19*4882a593Smuzhiyun * Mark IPIs as higher priority so we can take them inside interrupts
20*4882a593Smuzhiyun * FIXME: still true now?
21*4882a593Smuzhiyun */
22*4882a593Smuzhiyun #define IPI_PRIORITY 4
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun /* The least favored priority */
25*4882a593Smuzhiyun #define LOWEST_PRIORITY 0xFF
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun /* The number of priorities defined above */
28*4882a593Smuzhiyun #define MAX_NUM_PRIORITIES 3
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun /* Native ICP */
31*4882a593Smuzhiyun #ifdef CONFIG_PPC_ICP_NATIVE
32*4882a593Smuzhiyun extern int icp_native_init(void);
33*4882a593Smuzhiyun extern void icp_native_flush_interrupt(void);
34*4882a593Smuzhiyun extern void icp_native_cause_ipi_rm(int cpu);
35*4882a593Smuzhiyun #else
icp_native_init(void)36*4882a593Smuzhiyun static inline int icp_native_init(void) { return -ENODEV; }
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /* PAPR ICP */
40*4882a593Smuzhiyun #ifdef CONFIG_PPC_ICP_HV
41*4882a593Smuzhiyun extern int icp_hv_init(void);
42*4882a593Smuzhiyun #else
icp_hv_init(void)43*4882a593Smuzhiyun static inline int icp_hv_init(void) { return -ENODEV; }
44*4882a593Smuzhiyun #endif
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #ifdef CONFIG_PPC_POWERNV
47*4882a593Smuzhiyun extern int icp_opal_init(void);
48*4882a593Smuzhiyun extern void icp_opal_flush_interrupt(void);
49*4882a593Smuzhiyun #else
icp_opal_init(void)50*4882a593Smuzhiyun static inline int icp_opal_init(void) { return -ENODEV; }
51*4882a593Smuzhiyun #endif
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun /* ICP ops */
54*4882a593Smuzhiyun struct icp_ops {
55*4882a593Smuzhiyun unsigned int (*get_irq)(void);
56*4882a593Smuzhiyun void (*eoi)(struct irq_data *d);
57*4882a593Smuzhiyun void (*set_priority)(unsigned char prio);
58*4882a593Smuzhiyun void (*teardown_cpu)(void);
59*4882a593Smuzhiyun void (*flush_ipi)(void);
60*4882a593Smuzhiyun #ifdef CONFIG_SMP
61*4882a593Smuzhiyun void (*cause_ipi)(int cpu);
62*4882a593Smuzhiyun irq_handler_t ipi_action;
63*4882a593Smuzhiyun #endif
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun extern const struct icp_ops *icp_ops;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /* Native ICS */
69*4882a593Smuzhiyun extern int ics_native_init(void);
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun /* RTAS ICS */
72*4882a593Smuzhiyun #ifdef CONFIG_PPC_ICS_RTAS
73*4882a593Smuzhiyun extern int ics_rtas_init(void);
74*4882a593Smuzhiyun #else
ics_rtas_init(void)75*4882a593Smuzhiyun static inline int ics_rtas_init(void) { return -ENODEV; }
76*4882a593Smuzhiyun #endif
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /* HAL ICS */
79*4882a593Smuzhiyun #ifdef CONFIG_PPC_POWERNV
80*4882a593Smuzhiyun extern int ics_opal_init(void);
81*4882a593Smuzhiyun #else
ics_opal_init(void)82*4882a593Smuzhiyun static inline int ics_opal_init(void) { return -ENODEV; }
83*4882a593Smuzhiyun #endif
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /* ICS instance, hooked up to chip_data of an irq */
86*4882a593Smuzhiyun struct ics {
87*4882a593Smuzhiyun struct list_head link;
88*4882a593Smuzhiyun int (*map)(struct ics *ics, unsigned int virq);
89*4882a593Smuzhiyun void (*mask_unknown)(struct ics *ics, unsigned long vec);
90*4882a593Smuzhiyun long (*get_server)(struct ics *ics, unsigned long vec);
91*4882a593Smuzhiyun int (*host_match)(struct ics *ics, struct device_node *node);
92*4882a593Smuzhiyun char data[];
93*4882a593Smuzhiyun };
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /* Commons */
96*4882a593Smuzhiyun extern unsigned int xics_default_server;
97*4882a593Smuzhiyun extern unsigned int xics_default_distrib_server;
98*4882a593Smuzhiyun extern unsigned int xics_interrupt_server_size;
99*4882a593Smuzhiyun extern struct irq_domain *xics_host;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun struct xics_cppr {
102*4882a593Smuzhiyun unsigned char stack[MAX_NUM_PRIORITIES];
103*4882a593Smuzhiyun int index;
104*4882a593Smuzhiyun };
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun DECLARE_PER_CPU(struct xics_cppr, xics_cppr);
107*4882a593Smuzhiyun
xics_push_cppr(unsigned int vec)108*4882a593Smuzhiyun static inline void xics_push_cppr(unsigned int vec)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1))
113*4882a593Smuzhiyun return;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun if (vec == XICS_IPI)
116*4882a593Smuzhiyun os_cppr->stack[++os_cppr->index] = IPI_PRIORITY;
117*4882a593Smuzhiyun else
118*4882a593Smuzhiyun os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
xics_pop_cppr(void)121*4882a593Smuzhiyun static inline unsigned char xics_pop_cppr(void)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun if (WARN_ON(os_cppr->index < 1))
126*4882a593Smuzhiyun return LOWEST_PRIORITY;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun return os_cppr->stack[--os_cppr->index];
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
xics_set_base_cppr(unsigned char cppr)131*4882a593Smuzhiyun static inline void xics_set_base_cppr(unsigned char cppr)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun /* we only really want to set the priority when there's
136*4882a593Smuzhiyun * just one cppr value on the stack
137*4882a593Smuzhiyun */
138*4882a593Smuzhiyun WARN_ON(os_cppr->index != 0);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun os_cppr->stack[0] = cppr;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
xics_cppr_top(void)143*4882a593Smuzhiyun static inline unsigned char xics_cppr_top(void)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun return os_cppr->stack[os_cppr->index];
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun DECLARE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun extern void xics_init(void);
153*4882a593Smuzhiyun extern void xics_setup_cpu(void);
154*4882a593Smuzhiyun extern void xics_update_irq_servers(void);
155*4882a593Smuzhiyun extern void xics_set_cpu_giq(unsigned int gserver, unsigned int join);
156*4882a593Smuzhiyun extern void xics_mask_unknown_vec(unsigned int vec);
157*4882a593Smuzhiyun extern irqreturn_t xics_ipi_dispatch(int cpu);
158*4882a593Smuzhiyun extern void xics_smp_probe(void);
159*4882a593Smuzhiyun extern void xics_register_ics(struct ics *ics);
160*4882a593Smuzhiyun extern void xics_teardown_cpu(void);
161*4882a593Smuzhiyun extern void xics_kexec_teardown_cpu(int secondary);
162*4882a593Smuzhiyun extern void xics_migrate_irqs_away(void);
163*4882a593Smuzhiyun extern void icp_native_eoi(struct irq_data *d);
164*4882a593Smuzhiyun extern int xics_set_irq_type(struct irq_data *d, unsigned int flow_type);
165*4882a593Smuzhiyun extern int xics_retrigger(struct irq_data *data);
166*4882a593Smuzhiyun #ifdef CONFIG_SMP
167*4882a593Smuzhiyun extern int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,
168*4882a593Smuzhiyun unsigned int strict_check);
169*4882a593Smuzhiyun #else
170*4882a593Smuzhiyun #define xics_get_irq_server(virq, cpumask, strict_check) (xics_default_server)
171*4882a593Smuzhiyun #endif
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun #endif /* _XICS_H */
175