xref: /openbmc/linux/arch/powerpc/include/asm/xics.h (revision a3a9f3b47d12b5f6dfc9c7ed9d7b193d77812195)
10b05ac6eSBenjamin Herrenschmidt /*
20b05ac6eSBenjamin Herrenschmidt  * Common definitions accross 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 /*
18*a3a9f3b4SYong Zhang  * Mark IPIs as higher priority so we can take them inside interrupts
19*a3a9f3b4SYong 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);
325c7c1e94SBenjamin Herrenschmidt #else
335c7c1e94SBenjamin Herrenschmidt static inline int icp_native_init(void) { return -ENODEV; }
345c7c1e94SBenjamin Herrenschmidt #endif
350b05ac6eSBenjamin Herrenschmidt 
360b05ac6eSBenjamin Herrenschmidt /* PAPR ICP */
375c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_ICP_HV
380b05ac6eSBenjamin Herrenschmidt extern int icp_hv_init(void);
395c7c1e94SBenjamin Herrenschmidt #else
405c7c1e94SBenjamin Herrenschmidt static inline int icp_hv_init(void) { return -ENODEV; }
415c7c1e94SBenjamin Herrenschmidt #endif
420b05ac6eSBenjamin Herrenschmidt 
430b05ac6eSBenjamin Herrenschmidt /* ICP ops */
440b05ac6eSBenjamin Herrenschmidt struct icp_ops {
450b05ac6eSBenjamin Herrenschmidt 	unsigned int (*get_irq)(void);
460b05ac6eSBenjamin Herrenschmidt 	void (*eoi)(struct irq_data *d);
470b05ac6eSBenjamin Herrenschmidt 	void (*set_priority)(unsigned char prio);
480b05ac6eSBenjamin Herrenschmidt 	void (*teardown_cpu)(void);
490b05ac6eSBenjamin Herrenschmidt 	void (*flush_ipi)(void);
500b05ac6eSBenjamin Herrenschmidt #ifdef CONFIG_SMP
5123d72bfdSMilton Miller 	void (*cause_ipi)(int cpu, unsigned long data);
520b05ac6eSBenjamin Herrenschmidt 	irq_handler_t ipi_action;
530b05ac6eSBenjamin Herrenschmidt #endif
540b05ac6eSBenjamin Herrenschmidt };
550b05ac6eSBenjamin Herrenschmidt 
560b05ac6eSBenjamin Herrenschmidt extern const struct icp_ops *icp_ops;
570b05ac6eSBenjamin Herrenschmidt 
580b05ac6eSBenjamin Herrenschmidt /* Native ICS */
590b05ac6eSBenjamin Herrenschmidt extern int ics_native_init(void);
600b05ac6eSBenjamin Herrenschmidt 
610b05ac6eSBenjamin Herrenschmidt /* RTAS ICS */
625c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_ICS_RTAS
630b05ac6eSBenjamin Herrenschmidt extern int ics_rtas_init(void);
645c7c1e94SBenjamin Herrenschmidt #else
655c7c1e94SBenjamin Herrenschmidt static inline int ics_rtas_init(void) { return -ENODEV; }
665c7c1e94SBenjamin Herrenschmidt #endif
675c7c1e94SBenjamin Herrenschmidt 
685c7c1e94SBenjamin Herrenschmidt /* HAL ICS */
695c7c1e94SBenjamin Herrenschmidt #ifdef CONFIG_PPC_POWERNV
705c7c1e94SBenjamin Herrenschmidt extern int ics_opal_init(void);
715c7c1e94SBenjamin Herrenschmidt #else
725c7c1e94SBenjamin Herrenschmidt static inline int ics_opal_init(void) { return -ENODEV; }
735c7c1e94SBenjamin Herrenschmidt #endif
740b05ac6eSBenjamin Herrenschmidt 
750b05ac6eSBenjamin Herrenschmidt /* ICS instance, hooked up to chip_data of an irq */
760b05ac6eSBenjamin Herrenschmidt struct ics {
770b05ac6eSBenjamin Herrenschmidt 	struct list_head link;
780b05ac6eSBenjamin Herrenschmidt 	int (*map)(struct ics *ics, unsigned int virq);
790b05ac6eSBenjamin Herrenschmidt 	void (*mask_unknown)(struct ics *ics, unsigned long vec);
800b05ac6eSBenjamin Herrenschmidt 	long (*get_server)(struct ics *ics, unsigned long vec);
815ca12376SMichael Ellerman 	int (*host_match)(struct ics *ics, struct device_node *node);
820b05ac6eSBenjamin Herrenschmidt 	char data[];
830b05ac6eSBenjamin Herrenschmidt };
840b05ac6eSBenjamin Herrenschmidt 
850b05ac6eSBenjamin Herrenschmidt /* Commons */
860b05ac6eSBenjamin Herrenschmidt extern unsigned int xics_default_server;
870b05ac6eSBenjamin Herrenschmidt extern unsigned int xics_default_distrib_server;
880b05ac6eSBenjamin Herrenschmidt extern unsigned int xics_interrupt_server_size;
890b05ac6eSBenjamin Herrenschmidt extern struct irq_host *xics_host;
900b05ac6eSBenjamin Herrenschmidt 
910b05ac6eSBenjamin Herrenschmidt struct xics_cppr {
920b05ac6eSBenjamin Herrenschmidt 	unsigned char stack[MAX_NUM_PRIORITIES];
930b05ac6eSBenjamin Herrenschmidt 	int index;
940b05ac6eSBenjamin Herrenschmidt };
950b05ac6eSBenjamin Herrenschmidt 
960b05ac6eSBenjamin Herrenschmidt DECLARE_PER_CPU(struct xics_cppr, xics_cppr);
970b05ac6eSBenjamin Herrenschmidt 
980b05ac6eSBenjamin Herrenschmidt static inline void xics_push_cppr(unsigned int vec)
990b05ac6eSBenjamin Herrenschmidt {
1000b05ac6eSBenjamin Herrenschmidt 	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
1010b05ac6eSBenjamin Herrenschmidt 
1020b05ac6eSBenjamin Herrenschmidt 	if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1))
1030b05ac6eSBenjamin Herrenschmidt 		return;
1040b05ac6eSBenjamin Herrenschmidt 
1050b05ac6eSBenjamin Herrenschmidt 	if (vec == XICS_IPI)
1060b05ac6eSBenjamin Herrenschmidt 		os_cppr->stack[++os_cppr->index] = IPI_PRIORITY;
1070b05ac6eSBenjamin Herrenschmidt 	else
1080b05ac6eSBenjamin Herrenschmidt 		os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY;
1090b05ac6eSBenjamin Herrenschmidt }
1100b05ac6eSBenjamin Herrenschmidt 
1110b05ac6eSBenjamin Herrenschmidt static inline unsigned char xics_pop_cppr(void)
1120b05ac6eSBenjamin Herrenschmidt {
1130b05ac6eSBenjamin Herrenschmidt 	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
1140b05ac6eSBenjamin Herrenschmidt 
1150b05ac6eSBenjamin Herrenschmidt 	if (WARN_ON(os_cppr->index < 1))
1160b05ac6eSBenjamin Herrenschmidt 		return LOWEST_PRIORITY;
1170b05ac6eSBenjamin Herrenschmidt 
1180b05ac6eSBenjamin Herrenschmidt 	return os_cppr->stack[--os_cppr->index];
1190b05ac6eSBenjamin Herrenschmidt }
1200b05ac6eSBenjamin Herrenschmidt 
1210b05ac6eSBenjamin Herrenschmidt static inline void xics_set_base_cppr(unsigned char cppr)
1220b05ac6eSBenjamin Herrenschmidt {
1230b05ac6eSBenjamin Herrenschmidt 	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
1240b05ac6eSBenjamin Herrenschmidt 
1250b05ac6eSBenjamin Herrenschmidt 	/* we only really want to set the priority when there's
1260b05ac6eSBenjamin Herrenschmidt 	 * just one cppr value on the stack
1270b05ac6eSBenjamin Herrenschmidt 	 */
1280b05ac6eSBenjamin Herrenschmidt 	WARN_ON(os_cppr->index != 0);
1290b05ac6eSBenjamin Herrenschmidt 
1300b05ac6eSBenjamin Herrenschmidt 	os_cppr->stack[0] = cppr;
1310b05ac6eSBenjamin Herrenschmidt }
1320b05ac6eSBenjamin Herrenschmidt 
1330b05ac6eSBenjamin Herrenschmidt static inline unsigned char xics_cppr_top(void)
1340b05ac6eSBenjamin Herrenschmidt {
1350b05ac6eSBenjamin Herrenschmidt 	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
1360b05ac6eSBenjamin Herrenschmidt 
1370b05ac6eSBenjamin Herrenschmidt 	return os_cppr->stack[os_cppr->index];
1380b05ac6eSBenjamin Herrenschmidt }
1390b05ac6eSBenjamin Herrenschmidt 
1400b05ac6eSBenjamin Herrenschmidt DECLARE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message);
1410b05ac6eSBenjamin Herrenschmidt 
1420b05ac6eSBenjamin Herrenschmidt extern void xics_init(void);
1430b05ac6eSBenjamin Herrenschmidt extern void xics_setup_cpu(void);
1440b05ac6eSBenjamin Herrenschmidt extern void xics_update_irq_servers(void);
1450b05ac6eSBenjamin Herrenschmidt extern void xics_set_cpu_giq(unsigned int gserver, unsigned int join);
1460b05ac6eSBenjamin Herrenschmidt extern void xics_mask_unknown_vec(unsigned int vec);
1470b05ac6eSBenjamin Herrenschmidt extern irqreturn_t xics_ipi_dispatch(int cpu);
1480b05ac6eSBenjamin Herrenschmidt extern int xics_smp_probe(void);
1490b05ac6eSBenjamin Herrenschmidt extern void xics_register_ics(struct ics *ics);
1500b05ac6eSBenjamin Herrenschmidt extern void xics_teardown_cpu(void);
1510b05ac6eSBenjamin Herrenschmidt extern void xics_kexec_teardown_cpu(int secondary);
1520b05ac6eSBenjamin Herrenschmidt extern void xics_migrate_irqs_away(void);
1530b05ac6eSBenjamin Herrenschmidt #ifdef CONFIG_SMP
1540b05ac6eSBenjamin Herrenschmidt extern int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,
1550b05ac6eSBenjamin Herrenschmidt 			       unsigned int strict_check);
1560b05ac6eSBenjamin Herrenschmidt #else
1570b05ac6eSBenjamin Herrenschmidt #define xics_get_irq_server(virq, cpumask, strict_check) (xics_default_server)
1580b05ac6eSBenjamin Herrenschmidt #endif
1590b05ac6eSBenjamin Herrenschmidt 
1600b05ac6eSBenjamin Herrenschmidt 
1610b05ac6eSBenjamin Herrenschmidt #endif /* _XICS_H */
162