xref: /openbmc/linux/arch/powerpc/include/asm/xics.h (revision b24413180f5600bcb3bb70fbed5cf186b60864bd)
1*b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
20b05ac6eSBenjamin Herrenschmidt /*
3446957baSAdam Buchbinder  * Common definitions across all variants of ICP and ICS interrupt
40b05ac6eSBenjamin Herrenschmidt  * controllers.
50b05ac6eSBenjamin Herrenschmidt  */
60b05ac6eSBenjamin Herrenschmidt 
70b05ac6eSBenjamin Herrenschmidt #ifndef _XICS_H
80b05ac6eSBenjamin Herrenschmidt #define _XICS_H
90b05ac6eSBenjamin Herrenschmidt 
10cd852579SMichael Ellerman #include <linux/interrupt.h>
11cd852579SMichael Ellerman 
120b05ac6eSBenjamin Herrenschmidt #define XICS_IPI		2
130b05ac6eSBenjamin Herrenschmidt #define XICS_IRQ_SPURIOUS	0
140b05ac6eSBenjamin Herrenschmidt 
150b05ac6eSBenjamin Herrenschmidt /* Want a priority other than 0.  Various HW issues require this. */
160b05ac6eSBenjamin Herrenschmidt #define	DEFAULT_PRIORITY	5
170b05ac6eSBenjamin Herrenschmidt 
180b05ac6eSBenjamin Herrenschmidt /*
19a3a9f3b4SYong Zhang  * Mark IPIs as higher priority so we can take them inside interrupts
20a3a9f3b4SYong Zhang  * FIXME: still true now?
210b05ac6eSBenjamin Herrenschmidt  */
220b05ac6eSBenjamin Herrenschmidt #define IPI_PRIORITY		4
230b05ac6eSBenjamin Herrenschmidt 
240b05ac6eSBenjamin Herrenschmidt /* The least favored priority */
250b05ac6eSBenjamin Herrenschmidt #define LOWEST_PRIORITY		0xFF
260b05ac6eSBenjamin Herrenschmidt 
270b05ac6eSBenjamin Herrenschmidt /* The number of priorities defined above */
280b05ac6eSBenjamin Herrenschmidt #define MAX_NUM_PRIORITIES	3
290b05ac6eSBenjamin Herrenschmidt 
300b05ac6eSBenjamin Herrenschmidt /* Native ICP */
315c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_ICP_NATIVE
320b05ac6eSBenjamin Herrenschmidt extern int icp_native_init(void);
33d6a4f709SPaul Mackerras extern void icp_native_flush_interrupt(void);
34ec13e9b6SSuresh Warrier extern void icp_native_cause_ipi_rm(int cpu);
355c7c1e94SBenjamin Herrenschmidt #else
365c7c1e94SBenjamin Herrenschmidt static inline int icp_native_init(void) { return -ENODEV; }
375c7c1e94SBenjamin Herrenschmidt #endif
380b05ac6eSBenjamin Herrenschmidt 
390b05ac6eSBenjamin Herrenschmidt /* PAPR ICP */
405c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_ICP_HV
410b05ac6eSBenjamin Herrenschmidt extern int icp_hv_init(void);
425c7c1e94SBenjamin Herrenschmidt #else
435c7c1e94SBenjamin Herrenschmidt static inline int icp_hv_init(void) { return -ENODEV; }
445c7c1e94SBenjamin Herrenschmidt #endif
450b05ac6eSBenjamin Herrenschmidt 
46d7436188SBenjamin Herrenschmidt #ifdef CONFIG_PPC_POWERNV
47d7436188SBenjamin Herrenschmidt extern int icp_opal_init(void);
489b256714SBenjamin Herrenschmidt extern void icp_opal_flush_interrupt(void);
49d7436188SBenjamin Herrenschmidt #else
50d7436188SBenjamin Herrenschmidt static inline int icp_opal_init(void) { return -ENODEV; }
51d7436188SBenjamin Herrenschmidt #endif
52d7436188SBenjamin Herrenschmidt 
530b05ac6eSBenjamin Herrenschmidt /* ICP ops */
540b05ac6eSBenjamin Herrenschmidt struct icp_ops {
550b05ac6eSBenjamin Herrenschmidt 	unsigned int (*get_irq)(void);
560b05ac6eSBenjamin Herrenschmidt 	void (*eoi)(struct irq_data *d);
570b05ac6eSBenjamin Herrenschmidt 	void (*set_priority)(unsigned char prio);
580b05ac6eSBenjamin Herrenschmidt 	void (*teardown_cpu)(void);
590b05ac6eSBenjamin Herrenschmidt 	void (*flush_ipi)(void);
600b05ac6eSBenjamin Herrenschmidt #ifdef CONFIG_SMP
61b866cc21SNicholas Piggin 	void (*cause_ipi)(int cpu);
620b05ac6eSBenjamin Herrenschmidt 	irq_handler_t ipi_action;
630b05ac6eSBenjamin Herrenschmidt #endif
640b05ac6eSBenjamin Herrenschmidt };
650b05ac6eSBenjamin Herrenschmidt 
660b05ac6eSBenjamin Herrenschmidt extern const struct icp_ops *icp_ops;
670b05ac6eSBenjamin Herrenschmidt 
680b05ac6eSBenjamin Herrenschmidt /* Native ICS */
690b05ac6eSBenjamin Herrenschmidt extern int ics_native_init(void);
700b05ac6eSBenjamin Herrenschmidt 
710b05ac6eSBenjamin Herrenschmidt /* RTAS ICS */
725c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_ICS_RTAS
730b05ac6eSBenjamin Herrenschmidt extern int ics_rtas_init(void);
745c7c1e94SBenjamin Herrenschmidt #else
755c7c1e94SBenjamin Herrenschmidt static inline int ics_rtas_init(void) { return -ENODEV; }
765c7c1e94SBenjamin Herrenschmidt #endif
775c7c1e94SBenjamin Herrenschmidt 
785c7c1e94SBenjamin Herrenschmidt /* HAL ICS */
795c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_POWERNV
805c7c1e94SBenjamin Herrenschmidt extern int ics_opal_init(void);
815c7c1e94SBenjamin Herrenschmidt #else
825c7c1e94SBenjamin Herrenschmidt static inline int ics_opal_init(void) { return -ENODEV; }
835c7c1e94SBenjamin Herrenschmidt #endif
840b05ac6eSBenjamin Herrenschmidt 
850b05ac6eSBenjamin Herrenschmidt /* ICS instance, hooked up to chip_data of an irq */
860b05ac6eSBenjamin Herrenschmidt struct ics {
870b05ac6eSBenjamin Herrenschmidt 	struct list_head link;
880b05ac6eSBenjamin Herrenschmidt 	int (*map)(struct ics *ics, unsigned int virq);
890b05ac6eSBenjamin Herrenschmidt 	void (*mask_unknown)(struct ics *ics, unsigned long vec);
900b05ac6eSBenjamin Herrenschmidt 	long (*get_server)(struct ics *ics, unsigned long vec);
915ca12376SMichael Ellerman 	int (*host_match)(struct ics *ics, struct device_node *node);
920b05ac6eSBenjamin Herrenschmidt 	char data[];
930b05ac6eSBenjamin Herrenschmidt };
940b05ac6eSBenjamin Herrenschmidt 
950b05ac6eSBenjamin Herrenschmidt /* Commons */
960b05ac6eSBenjamin Herrenschmidt extern unsigned int xics_default_server;
970b05ac6eSBenjamin Herrenschmidt extern unsigned int xics_default_distrib_server;
980b05ac6eSBenjamin Herrenschmidt extern unsigned int xics_interrupt_server_size;
99bae1d8f1SGrant Likely extern struct irq_domain *xics_host;
1000b05ac6eSBenjamin Herrenschmidt 
1010b05ac6eSBenjamin Herrenschmidt struct xics_cppr {
1020b05ac6eSBenjamin Herrenschmidt 	unsigned char stack[MAX_NUM_PRIORITIES];
1030b05ac6eSBenjamin Herrenschmidt 	int index;
1040b05ac6eSBenjamin Herrenschmidt };
1050b05ac6eSBenjamin Herrenschmidt 
1060b05ac6eSBenjamin Herrenschmidt DECLARE_PER_CPU(struct xics_cppr, xics_cppr);
1070b05ac6eSBenjamin Herrenschmidt 
1080b05ac6eSBenjamin Herrenschmidt static inline void xics_push_cppr(unsigned int vec)
1090b05ac6eSBenjamin Herrenschmidt {
11069111bacSChristoph Lameter 	struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
1110b05ac6eSBenjamin Herrenschmidt 
1120b05ac6eSBenjamin Herrenschmidt 	if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1))
1130b05ac6eSBenjamin Herrenschmidt 		return;
1140b05ac6eSBenjamin Herrenschmidt 
1150b05ac6eSBenjamin Herrenschmidt 	if (vec == XICS_IPI)
1160b05ac6eSBenjamin Herrenschmidt 		os_cppr->stack[++os_cppr->index] = IPI_PRIORITY;
1170b05ac6eSBenjamin Herrenschmidt 	else
1180b05ac6eSBenjamin Herrenschmidt 		os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY;
1190b05ac6eSBenjamin Herrenschmidt }
1200b05ac6eSBenjamin Herrenschmidt 
1210b05ac6eSBenjamin Herrenschmidt static inline unsigned char xics_pop_cppr(void)
1220b05ac6eSBenjamin Herrenschmidt {
12369111bacSChristoph Lameter 	struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
1240b05ac6eSBenjamin Herrenschmidt 
1250b05ac6eSBenjamin Herrenschmidt 	if (WARN_ON(os_cppr->index < 1))
1260b05ac6eSBenjamin Herrenschmidt 		return LOWEST_PRIORITY;
1270b05ac6eSBenjamin Herrenschmidt 
1280b05ac6eSBenjamin Herrenschmidt 	return os_cppr->stack[--os_cppr->index];
1290b05ac6eSBenjamin Herrenschmidt }
1300b05ac6eSBenjamin Herrenschmidt 
1310b05ac6eSBenjamin Herrenschmidt static inline void xics_set_base_cppr(unsigned char cppr)
1320b05ac6eSBenjamin Herrenschmidt {
13369111bacSChristoph Lameter 	struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
1340b05ac6eSBenjamin Herrenschmidt 
1350b05ac6eSBenjamin Herrenschmidt 	/* we only really want to set the priority when there's
1360b05ac6eSBenjamin Herrenschmidt 	 * just one cppr value on the stack
1370b05ac6eSBenjamin Herrenschmidt 	 */
1380b05ac6eSBenjamin Herrenschmidt 	WARN_ON(os_cppr->index != 0);
1390b05ac6eSBenjamin Herrenschmidt 
1400b05ac6eSBenjamin Herrenschmidt 	os_cppr->stack[0] = cppr;
1410b05ac6eSBenjamin Herrenschmidt }
1420b05ac6eSBenjamin Herrenschmidt 
1430b05ac6eSBenjamin Herrenschmidt static inline unsigned char xics_cppr_top(void)
1440b05ac6eSBenjamin Herrenschmidt {
14569111bacSChristoph Lameter 	struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
1460b05ac6eSBenjamin Herrenschmidt 
1470b05ac6eSBenjamin Herrenschmidt 	return os_cppr->stack[os_cppr->index];
1480b05ac6eSBenjamin Herrenschmidt }
1490b05ac6eSBenjamin Herrenschmidt 
1500b05ac6eSBenjamin Herrenschmidt DECLARE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message);
1510b05ac6eSBenjamin Herrenschmidt 
1520b05ac6eSBenjamin Herrenschmidt extern void xics_init(void);
1530b05ac6eSBenjamin Herrenschmidt extern void xics_setup_cpu(void);
1540b05ac6eSBenjamin Herrenschmidt extern void xics_update_irq_servers(void);
1550b05ac6eSBenjamin Herrenschmidt extern void xics_set_cpu_giq(unsigned int gserver, unsigned int join);
1560b05ac6eSBenjamin Herrenschmidt extern void xics_mask_unknown_vec(unsigned int vec);
1570b05ac6eSBenjamin Herrenschmidt extern irqreturn_t xics_ipi_dispatch(int cpu);
158a7f4ee1fSMichael Ellerman extern void xics_smp_probe(void);
1590b05ac6eSBenjamin Herrenschmidt extern void xics_register_ics(struct ics *ics);
1600b05ac6eSBenjamin Herrenschmidt extern void xics_teardown_cpu(void);
1610b05ac6eSBenjamin Herrenschmidt extern void xics_kexec_teardown_cpu(int secondary);
1620b05ac6eSBenjamin Herrenschmidt extern void xics_migrate_irqs_away(void);
163137436c9SGavin Shan extern void icp_native_eoi(struct irq_data *d);
164880a3d6aSBenjamin Herrenschmidt extern int xics_set_irq_type(struct irq_data *d, unsigned int flow_type);
165880a3d6aSBenjamin Herrenschmidt extern int xics_retrigger(struct irq_data *data);
1660b05ac6eSBenjamin Herrenschmidt #ifdef CONFIG_SMP
1670b05ac6eSBenjamin Herrenschmidt extern int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,
1680b05ac6eSBenjamin Herrenschmidt 			       unsigned int strict_check);
1690b05ac6eSBenjamin Herrenschmidt #else
1700b05ac6eSBenjamin Herrenschmidt #define xics_get_irq_server(virq, cpumask, strict_check) (xics_default_server)
1710b05ac6eSBenjamin Herrenschmidt #endif
1720b05ac6eSBenjamin Herrenschmidt 
1730b05ac6eSBenjamin Herrenschmidt 
1740b05ac6eSBenjamin Herrenschmidt #endif /* _XICS_H */
175