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