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 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 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 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 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 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 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 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 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 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 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); 1620b05ac6eSBenjamin Herrenschmidt extern irqreturn_t xics_ipi_dispatch(int cpu); 163a7f4ee1fSMichael Ellerman extern void xics_smp_probe(void); 1640b05ac6eSBenjamin Herrenschmidt extern void xics_register_ics(struct ics *ics); 1650b05ac6eSBenjamin Herrenschmidt extern void xics_teardown_cpu(void); 1660b05ac6eSBenjamin Herrenschmidt extern void xics_kexec_teardown_cpu(int secondary); 1670b05ac6eSBenjamin Herrenschmidt extern void xics_migrate_irqs_away(void); 168137436c9SGavin Shan extern void icp_native_eoi(struct irq_data *d); 169880a3d6aSBenjamin Herrenschmidt extern int xics_set_irq_type(struct irq_data *d, unsigned int flow_type); 170880a3d6aSBenjamin Herrenschmidt extern int xics_retrigger(struct irq_data *data); 1710b05ac6eSBenjamin Herrenschmidt #ifdef CONFIG_SMP 1720b05ac6eSBenjamin Herrenschmidt extern int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask, 1730b05ac6eSBenjamin Herrenschmidt unsigned int strict_check); 1740b05ac6eSBenjamin Herrenschmidt #else 1750b05ac6eSBenjamin Herrenschmidt #define xics_get_irq_server(virq, cpumask, strict_check) (xics_default_server) 1760b05ac6eSBenjamin Herrenschmidt #endif 1770b05ac6eSBenjamin Herrenschmidt 1780b05ac6eSBenjamin Herrenschmidt 1790b05ac6eSBenjamin Herrenschmidt #endif /* _XICS_H */ 180