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