xref: /openbmc/linux/arch/powerpc/include/asm/xics.h (revision d74361881f0dfe5f9dcac37d1b753a15a2345d8c)
10b05ac6eSBenjamin Herrenschmidt /*
2446957baSAdam Buchbinder  * Common definitions across all variants of ICP and ICS interrupt
30b05ac6eSBenjamin Herrenschmidt  * controllers.
40b05ac6eSBenjamin Herrenschmidt  */
50b05ac6eSBenjamin Herrenschmidt 
60b05ac6eSBenjamin Herrenschmidt #ifndef _XICS_H
70b05ac6eSBenjamin Herrenschmidt #define _XICS_H
80b05ac6eSBenjamin Herrenschmidt 
9cd852579SMichael Ellerman #include <linux/interrupt.h>
10cd852579SMichael Ellerman 
110b05ac6eSBenjamin Herrenschmidt #define XICS_IPI		2
120b05ac6eSBenjamin Herrenschmidt #define XICS_IRQ_SPURIOUS	0
130b05ac6eSBenjamin Herrenschmidt 
140b05ac6eSBenjamin Herrenschmidt /* Want a priority other than 0.  Various HW issues require this. */
150b05ac6eSBenjamin Herrenschmidt #define	DEFAULT_PRIORITY	5
160b05ac6eSBenjamin Herrenschmidt 
170b05ac6eSBenjamin Herrenschmidt /*
18a3a9f3b4SYong Zhang  * Mark IPIs as higher priority so we can take them inside interrupts
19a3a9f3b4SYong Zhang  * FIXME: still true now?
200b05ac6eSBenjamin Herrenschmidt  */
210b05ac6eSBenjamin Herrenschmidt #define IPI_PRIORITY		4
220b05ac6eSBenjamin Herrenschmidt 
230b05ac6eSBenjamin Herrenschmidt /* The least favored priority */
240b05ac6eSBenjamin Herrenschmidt #define LOWEST_PRIORITY		0xFF
250b05ac6eSBenjamin Herrenschmidt 
260b05ac6eSBenjamin Herrenschmidt /* The number of priorities defined above */
270b05ac6eSBenjamin Herrenschmidt #define MAX_NUM_PRIORITIES	3
280b05ac6eSBenjamin Herrenschmidt 
290b05ac6eSBenjamin Herrenschmidt /* Native ICP */
305c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_ICP_NATIVE
310b05ac6eSBenjamin Herrenschmidt extern int icp_native_init(void);
32d6a4f709SPaul Mackerras extern void icp_native_flush_interrupt(void);
33ec13e9b6SSuresh Warrier extern void icp_native_cause_ipi_rm(int cpu);
345c7c1e94SBenjamin Herrenschmidt #else
355c7c1e94SBenjamin Herrenschmidt static inline int icp_native_init(void) { return -ENODEV; }
365c7c1e94SBenjamin Herrenschmidt #endif
370b05ac6eSBenjamin Herrenschmidt 
380b05ac6eSBenjamin Herrenschmidt /* PAPR ICP */
395c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_ICP_HV
400b05ac6eSBenjamin Herrenschmidt extern int icp_hv_init(void);
415c7c1e94SBenjamin Herrenschmidt #else
425c7c1e94SBenjamin Herrenschmidt static inline int icp_hv_init(void) { return -ENODEV; }
435c7c1e94SBenjamin Herrenschmidt #endif
440b05ac6eSBenjamin Herrenschmidt 
45*d7436188SBenjamin Herrenschmidt #ifdef CONFIG_PPC_POWERNV
46*d7436188SBenjamin Herrenschmidt extern int icp_opal_init(void);
47*d7436188SBenjamin Herrenschmidt #else
48*d7436188SBenjamin Herrenschmidt static inline int icp_opal_init(void) { return -ENODEV; }
49*d7436188SBenjamin Herrenschmidt #endif
50*d7436188SBenjamin Herrenschmidt 
510b05ac6eSBenjamin Herrenschmidt /* ICP ops */
520b05ac6eSBenjamin Herrenschmidt struct icp_ops {
530b05ac6eSBenjamin Herrenschmidt 	unsigned int (*get_irq)(void);
540b05ac6eSBenjamin Herrenschmidt 	void (*eoi)(struct irq_data *d);
550b05ac6eSBenjamin Herrenschmidt 	void (*set_priority)(unsigned char prio);
560b05ac6eSBenjamin Herrenschmidt 	void (*teardown_cpu)(void);
570b05ac6eSBenjamin Herrenschmidt 	void (*flush_ipi)(void);
580b05ac6eSBenjamin Herrenschmidt #ifdef CONFIG_SMP
5923d72bfdSMilton Miller 	void (*cause_ipi)(int cpu, unsigned long data);
600b05ac6eSBenjamin Herrenschmidt 	irq_handler_t ipi_action;
610b05ac6eSBenjamin Herrenschmidt #endif
620b05ac6eSBenjamin Herrenschmidt };
630b05ac6eSBenjamin Herrenschmidt 
640b05ac6eSBenjamin Herrenschmidt extern const struct icp_ops *icp_ops;
650b05ac6eSBenjamin Herrenschmidt 
660b05ac6eSBenjamin Herrenschmidt /* Native ICS */
670b05ac6eSBenjamin Herrenschmidt extern int ics_native_init(void);
680b05ac6eSBenjamin Herrenschmidt 
690b05ac6eSBenjamin Herrenschmidt /* RTAS ICS */
705c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_ICS_RTAS
710b05ac6eSBenjamin Herrenschmidt extern int ics_rtas_init(void);
725c7c1e94SBenjamin Herrenschmidt #else
735c7c1e94SBenjamin Herrenschmidt static inline int ics_rtas_init(void) { return -ENODEV; }
745c7c1e94SBenjamin Herrenschmidt #endif
755c7c1e94SBenjamin Herrenschmidt 
765c7c1e94SBenjamin Herrenschmidt /* HAL ICS */
775c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_POWERNV
785c7c1e94SBenjamin Herrenschmidt extern int ics_opal_init(void);
795c7c1e94SBenjamin Herrenschmidt #else
805c7c1e94SBenjamin Herrenschmidt static inline int ics_opal_init(void) { return -ENODEV; }
815c7c1e94SBenjamin Herrenschmidt #endif
820b05ac6eSBenjamin Herrenschmidt 
830b05ac6eSBenjamin Herrenschmidt /* ICS instance, hooked up to chip_data of an irq */
840b05ac6eSBenjamin Herrenschmidt struct ics {
850b05ac6eSBenjamin Herrenschmidt 	struct list_head link;
860b05ac6eSBenjamin Herrenschmidt 	int (*map)(struct ics *ics, unsigned int virq);
870b05ac6eSBenjamin Herrenschmidt 	void (*mask_unknown)(struct ics *ics, unsigned long vec);
880b05ac6eSBenjamin Herrenschmidt 	long (*get_server)(struct ics *ics, unsigned long vec);
895ca12376SMichael Ellerman 	int (*host_match)(struct ics *ics, struct device_node *node);
900b05ac6eSBenjamin Herrenschmidt 	char data[];
910b05ac6eSBenjamin Herrenschmidt };
920b05ac6eSBenjamin Herrenschmidt 
930b05ac6eSBenjamin Herrenschmidt /* Commons */
940b05ac6eSBenjamin Herrenschmidt extern unsigned int xics_default_server;
950b05ac6eSBenjamin Herrenschmidt extern unsigned int xics_default_distrib_server;
960b05ac6eSBenjamin Herrenschmidt extern unsigned int xics_interrupt_server_size;
97bae1d8f1SGrant Likely extern struct irq_domain *xics_host;
980b05ac6eSBenjamin Herrenschmidt 
990b05ac6eSBenjamin Herrenschmidt struct xics_cppr {
1000b05ac6eSBenjamin Herrenschmidt 	unsigned char stack[MAX_NUM_PRIORITIES];
1010b05ac6eSBenjamin Herrenschmidt 	int index;
1020b05ac6eSBenjamin Herrenschmidt };
1030b05ac6eSBenjamin Herrenschmidt 
1040b05ac6eSBenjamin Herrenschmidt DECLARE_PER_CPU(struct xics_cppr, xics_cppr);
1050b05ac6eSBenjamin Herrenschmidt 
1060b05ac6eSBenjamin Herrenschmidt static inline void xics_push_cppr(unsigned int vec)
1070b05ac6eSBenjamin Herrenschmidt {
10869111bacSChristoph Lameter 	struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
1090b05ac6eSBenjamin Herrenschmidt 
1100b05ac6eSBenjamin Herrenschmidt 	if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1))
1110b05ac6eSBenjamin Herrenschmidt 		return;
1120b05ac6eSBenjamin Herrenschmidt 
1130b05ac6eSBenjamin Herrenschmidt 	if (vec == XICS_IPI)
1140b05ac6eSBenjamin Herrenschmidt 		os_cppr->stack[++os_cppr->index] = IPI_PRIORITY;
1150b05ac6eSBenjamin Herrenschmidt 	else
1160b05ac6eSBenjamin Herrenschmidt 		os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY;
1170b05ac6eSBenjamin Herrenschmidt }
1180b05ac6eSBenjamin Herrenschmidt 
1190b05ac6eSBenjamin Herrenschmidt static inline unsigned char xics_pop_cppr(void)
1200b05ac6eSBenjamin Herrenschmidt {
12169111bacSChristoph Lameter 	struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
1220b05ac6eSBenjamin Herrenschmidt 
1230b05ac6eSBenjamin Herrenschmidt 	if (WARN_ON(os_cppr->index < 1))
1240b05ac6eSBenjamin Herrenschmidt 		return LOWEST_PRIORITY;
1250b05ac6eSBenjamin Herrenschmidt 
1260b05ac6eSBenjamin Herrenschmidt 	return os_cppr->stack[--os_cppr->index];
1270b05ac6eSBenjamin Herrenschmidt }
1280b05ac6eSBenjamin Herrenschmidt 
1290b05ac6eSBenjamin Herrenschmidt static inline void xics_set_base_cppr(unsigned char cppr)
1300b05ac6eSBenjamin Herrenschmidt {
13169111bacSChristoph Lameter 	struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
1320b05ac6eSBenjamin Herrenschmidt 
1330b05ac6eSBenjamin Herrenschmidt 	/* we only really want to set the priority when there's
1340b05ac6eSBenjamin Herrenschmidt 	 * just one cppr value on the stack
1350b05ac6eSBenjamin Herrenschmidt 	 */
1360b05ac6eSBenjamin Herrenschmidt 	WARN_ON(os_cppr->index != 0);
1370b05ac6eSBenjamin Herrenschmidt 
1380b05ac6eSBenjamin Herrenschmidt 	os_cppr->stack[0] = cppr;
1390b05ac6eSBenjamin Herrenschmidt }
1400b05ac6eSBenjamin Herrenschmidt 
1410b05ac6eSBenjamin Herrenschmidt static inline unsigned char xics_cppr_top(void)
1420b05ac6eSBenjamin Herrenschmidt {
14369111bacSChristoph Lameter 	struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
1440b05ac6eSBenjamin Herrenschmidt 
1450b05ac6eSBenjamin Herrenschmidt 	return os_cppr->stack[os_cppr->index];
1460b05ac6eSBenjamin Herrenschmidt }
1470b05ac6eSBenjamin Herrenschmidt 
1480b05ac6eSBenjamin Herrenschmidt DECLARE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message);
1490b05ac6eSBenjamin Herrenschmidt 
1500b05ac6eSBenjamin Herrenschmidt extern void xics_init(void);
1510b05ac6eSBenjamin Herrenschmidt extern void xics_setup_cpu(void);
1520b05ac6eSBenjamin Herrenschmidt extern void xics_update_irq_servers(void);
1530b05ac6eSBenjamin Herrenschmidt extern void xics_set_cpu_giq(unsigned int gserver, unsigned int join);
1540b05ac6eSBenjamin Herrenschmidt extern void xics_mask_unknown_vec(unsigned int vec);
1550b05ac6eSBenjamin Herrenschmidt extern irqreturn_t xics_ipi_dispatch(int cpu);
156a7f4ee1fSMichael Ellerman extern void xics_smp_probe(void);
1570b05ac6eSBenjamin Herrenschmidt extern void xics_register_ics(struct ics *ics);
1580b05ac6eSBenjamin Herrenschmidt extern void xics_teardown_cpu(void);
1590b05ac6eSBenjamin Herrenschmidt extern void xics_kexec_teardown_cpu(int secondary);
1600b05ac6eSBenjamin Herrenschmidt extern void xics_migrate_irqs_away(void);
161137436c9SGavin Shan extern void icp_native_eoi(struct irq_data *d);
1620b05ac6eSBenjamin Herrenschmidt #ifdef CONFIG_SMP
1630b05ac6eSBenjamin Herrenschmidt extern int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,
1640b05ac6eSBenjamin Herrenschmidt 			       unsigned int strict_check);
1650b05ac6eSBenjamin Herrenschmidt #else
1660b05ac6eSBenjamin Herrenschmidt #define xics_get_irq_server(virq, cpumask, strict_check) (xics_default_server)
1670b05ac6eSBenjamin Herrenschmidt #endif
1680b05ac6eSBenjamin Herrenschmidt 
1690b05ac6eSBenjamin Herrenschmidt 
1700b05ac6eSBenjamin Herrenschmidt #endif /* _XICS_H */
171