xref: /openbmc/linux/arch/powerpc/include/asm/xics.h (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1b2441318SGreg 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
icp_native_init(void)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
41*6c552983SNick Child int __init icp_hv_init(void);
425c7c1e94SBenjamin Herrenschmidt #else
icp_hv_init(void)435c7c1e94SBenjamin Herrenschmidt static inline int icp_hv_init(void) { return -ENODEV; }
445c7c1e94SBenjamin Herrenschmidt #endif
450b05ac6eSBenjamin Herrenschmidt 
46d7436188SBenjamin Herrenschmidt #ifdef CONFIG_PPC_POWERNV
47*6c552983SNick Child int __init icp_opal_init(void);
489b256714SBenjamin Herrenschmidt extern void icp_opal_flush_interrupt(void);
49d7436188SBenjamin Herrenschmidt #else
icp_opal_init(void)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 
68aa9c5adfSBenjamin Herrenschmidt #ifdef CONFIG_PPC_ICS_NATIVE
690b05ac6eSBenjamin Herrenschmidt /* Native ICS */
700b05ac6eSBenjamin Herrenschmidt extern int ics_native_init(void);
71aa9c5adfSBenjamin Herrenschmidt #else
ics_native_init(void)72aa9c5adfSBenjamin Herrenschmidt static inline int ics_native_init(void) { return -ENODEV; }
73aa9c5adfSBenjamin Herrenschmidt #endif
740b05ac6eSBenjamin Herrenschmidt 
750b05ac6eSBenjamin Herrenschmidt /* RTAS ICS */
765c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_ICS_RTAS
770b05ac6eSBenjamin Herrenschmidt extern int ics_rtas_init(void);
785c7c1e94SBenjamin Herrenschmidt #else
ics_rtas_init(void)795c7c1e94SBenjamin Herrenschmidt static inline int ics_rtas_init(void) { return -ENODEV; }
805c7c1e94SBenjamin Herrenschmidt #endif
815c7c1e94SBenjamin Herrenschmidt 
825c7c1e94SBenjamin Herrenschmidt /* HAL ICS */
835c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_POWERNV
845c7c1e94SBenjamin Herrenschmidt extern int ics_opal_init(void);
855c7c1e94SBenjamin Herrenschmidt #else
ics_opal_init(void)865c7c1e94SBenjamin Herrenschmidt static inline int ics_opal_init(void) { return -ENODEV; }
875c7c1e94SBenjamin Herrenschmidt #endif
880b05ac6eSBenjamin Herrenschmidt 
890b05ac6eSBenjamin Herrenschmidt /* ICS instance, hooked up to chip_data of an irq */
900b05ac6eSBenjamin Herrenschmidt struct ics {
910b05ac6eSBenjamin Herrenschmidt 	struct list_head link;
92248af248SCédric Le Goater 	int (*check)(struct ics *ics, unsigned int hwirq);
930b05ac6eSBenjamin Herrenschmidt 	void (*mask_unknown)(struct ics *ics, unsigned long vec);
940b05ac6eSBenjamin Herrenschmidt 	long (*get_server)(struct ics *ics, unsigned long vec);
955ca12376SMichael Ellerman 	int (*host_match)(struct ics *ics, struct device_node *node);
96248af248SCédric Le Goater 	struct irq_chip *chip;
970b05ac6eSBenjamin Herrenschmidt 	char data[];
980b05ac6eSBenjamin Herrenschmidt };
990b05ac6eSBenjamin Herrenschmidt 
1000b05ac6eSBenjamin Herrenschmidt /* Commons */
1010b05ac6eSBenjamin Herrenschmidt extern unsigned int xics_default_server;
1020b05ac6eSBenjamin Herrenschmidt extern unsigned int xics_default_distrib_server;
1030b05ac6eSBenjamin Herrenschmidt extern unsigned int xics_interrupt_server_size;
104bae1d8f1SGrant Likely extern struct irq_domain *xics_host;
1050b05ac6eSBenjamin Herrenschmidt 
1060b05ac6eSBenjamin Herrenschmidt struct xics_cppr {
1070b05ac6eSBenjamin Herrenschmidt 	unsigned char stack[MAX_NUM_PRIORITIES];
1080b05ac6eSBenjamin Herrenschmidt 	int index;
1090b05ac6eSBenjamin Herrenschmidt };
1100b05ac6eSBenjamin Herrenschmidt 
1110b05ac6eSBenjamin Herrenschmidt DECLARE_PER_CPU(struct xics_cppr, xics_cppr);
1120b05ac6eSBenjamin Herrenschmidt 
xics_push_cppr(unsigned int vec)1130b05ac6eSBenjamin Herrenschmidt static inline void xics_push_cppr(unsigned int vec)
1140b05ac6eSBenjamin Herrenschmidt {
11569111bacSChristoph Lameter 	struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
1160b05ac6eSBenjamin Herrenschmidt 
1170b05ac6eSBenjamin Herrenschmidt 	if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1))
1180b05ac6eSBenjamin Herrenschmidt 		return;
1190b05ac6eSBenjamin Herrenschmidt 
1200b05ac6eSBenjamin Herrenschmidt 	if (vec == XICS_IPI)
1210b05ac6eSBenjamin Herrenschmidt 		os_cppr->stack[++os_cppr->index] = IPI_PRIORITY;
1220b05ac6eSBenjamin Herrenschmidt 	else
1230b05ac6eSBenjamin Herrenschmidt 		os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY;
1240b05ac6eSBenjamin Herrenschmidt }
1250b05ac6eSBenjamin Herrenschmidt 
xics_pop_cppr(void)1260b05ac6eSBenjamin Herrenschmidt static inline unsigned char xics_pop_cppr(void)
1270b05ac6eSBenjamin Herrenschmidt {
12869111bacSChristoph Lameter 	struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
1290b05ac6eSBenjamin Herrenschmidt 
1300b05ac6eSBenjamin Herrenschmidt 	if (WARN_ON(os_cppr->index < 1))
1310b05ac6eSBenjamin Herrenschmidt 		return LOWEST_PRIORITY;
1320b05ac6eSBenjamin Herrenschmidt 
1330b05ac6eSBenjamin Herrenschmidt 	return os_cppr->stack[--os_cppr->index];
1340b05ac6eSBenjamin Herrenschmidt }
1350b05ac6eSBenjamin Herrenschmidt 
xics_set_base_cppr(unsigned char cppr)1360b05ac6eSBenjamin Herrenschmidt static inline void xics_set_base_cppr(unsigned char cppr)
1370b05ac6eSBenjamin Herrenschmidt {
13869111bacSChristoph Lameter 	struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
1390b05ac6eSBenjamin Herrenschmidt 
1400b05ac6eSBenjamin Herrenschmidt 	/* we only really want to set the priority when there's
1410b05ac6eSBenjamin Herrenschmidt 	 * just one cppr value on the stack
1420b05ac6eSBenjamin Herrenschmidt 	 */
1430b05ac6eSBenjamin Herrenschmidt 	WARN_ON(os_cppr->index != 0);
1440b05ac6eSBenjamin Herrenschmidt 
1450b05ac6eSBenjamin Herrenschmidt 	os_cppr->stack[0] = cppr;
1460b05ac6eSBenjamin Herrenschmidt }
1470b05ac6eSBenjamin Herrenschmidt 
xics_cppr_top(void)1480b05ac6eSBenjamin Herrenschmidt static inline unsigned char xics_cppr_top(void)
1490b05ac6eSBenjamin Herrenschmidt {
15069111bacSChristoph Lameter 	struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
1510b05ac6eSBenjamin Herrenschmidt 
1520b05ac6eSBenjamin Herrenschmidt 	return os_cppr->stack[os_cppr->index];
1530b05ac6eSBenjamin Herrenschmidt }
1540b05ac6eSBenjamin Herrenschmidt 
1550b05ac6eSBenjamin Herrenschmidt DECLARE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message);
1560b05ac6eSBenjamin Herrenschmidt 
1570b05ac6eSBenjamin Herrenschmidt extern void xics_init(void);
1580b05ac6eSBenjamin Herrenschmidt extern void xics_setup_cpu(void);
1590b05ac6eSBenjamin Herrenschmidt extern void xics_update_irq_servers(void);
1600b05ac6eSBenjamin Herrenschmidt extern void xics_set_cpu_giq(unsigned int gserver, unsigned int join);
1610b05ac6eSBenjamin Herrenschmidt extern void xics_mask_unknown_vec(unsigned int vec);
162a7f4ee1fSMichael Ellerman extern void xics_smp_probe(void);
1630b05ac6eSBenjamin Herrenschmidt extern void xics_register_ics(struct ics *ics);
1640b05ac6eSBenjamin Herrenschmidt extern void xics_teardown_cpu(void);
1650b05ac6eSBenjamin Herrenschmidt extern void xics_kexec_teardown_cpu(int secondary);
1660b05ac6eSBenjamin Herrenschmidt extern void xics_migrate_irqs_away(void);
167137436c9SGavin Shan extern void icp_native_eoi(struct irq_data *d);
168880a3d6aSBenjamin Herrenschmidt extern int xics_set_irq_type(struct irq_data *d, unsigned int flow_type);
169880a3d6aSBenjamin Herrenschmidt extern int xics_retrigger(struct irq_data *data);
1700b05ac6eSBenjamin Herrenschmidt #ifdef CONFIG_SMP
1710b05ac6eSBenjamin Herrenschmidt extern int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,
1720b05ac6eSBenjamin Herrenschmidt 			       unsigned int strict_check);
1730b05ac6eSBenjamin Herrenschmidt #else
1740b05ac6eSBenjamin Herrenschmidt #define xics_get_irq_server(virq, cpumask, strict_check) (xics_default_server)
1750b05ac6eSBenjamin Herrenschmidt #endif
1760b05ac6eSBenjamin Herrenschmidt 
1770b05ac6eSBenjamin Herrenschmidt 
1780b05ac6eSBenjamin Herrenschmidt #endif /* _XICS_H */
179