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 (*check)(struct ics *ics, unsigned int hwirq);
  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        struct irq_chip *chip;
  97        char data[];
  98};
  99
 100/* Commons */
 101extern unsigned int xics_default_server;
 102extern unsigned int xics_default_distrib_server;
 103extern unsigned int xics_interrupt_server_size;
 104extern struct irq_domain *xics_host;
 105
 106struct xics_cppr {
 107        unsigned char stack[MAX_NUM_PRIORITIES];
 108        int index;
 109};
 110
 111DECLARE_PER_CPU(struct xics_cppr, xics_cppr);
 112
 113static inline void xics_push_cppr(unsigned int vec)
 114{
 115        struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
 116
 117        if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1))
 118                return;
 119
 120        if (vec == XICS_IPI)
 121                os_cppr->stack[++os_cppr->index] = IPI_PRIORITY;
 122        else
 123                os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY;
 124}
 125
 126static inline unsigned char xics_pop_cppr(void)
 127{
 128        struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
 129
 130        if (WARN_ON(os_cppr->index < 1))
 131                return LOWEST_PRIORITY;
 132
 133        return os_cppr->stack[--os_cppr->index];
 134}
 135
 136static inline void xics_set_base_cppr(unsigned char cppr)
 137{
 138        struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
 139
 140        /* we only really want to set the priority when there's
 141         * just one cppr value on the stack
 142         */
 143        WARN_ON(os_cppr->index != 0);
 144
 145        os_cppr->stack[0] = cppr;
 146}
 147
 148static inline unsigned char xics_cppr_top(void)
 149{
 150        struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
 151        
 152        return os_cppr->stack[os_cppr->index];
 153}
 154
 155DECLARE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message);
 156
 157extern void xics_init(void);
 158extern void xics_setup_cpu(void);
 159extern void xics_update_irq_servers(void);
 160extern void xics_set_cpu_giq(unsigned int gserver, unsigned int join);
 161extern void xics_mask_unknown_vec(unsigned int vec);
 162extern irqreturn_t xics_ipi_dispatch(int cpu);
 163extern void xics_smp_probe(void);
 164extern void xics_register_ics(struct ics *ics);
 165extern void xics_teardown_cpu(void);
 166extern void xics_kexec_teardown_cpu(int secondary);
 167extern void xics_migrate_irqs_away(void);
 168extern void icp_native_eoi(struct irq_data *d);
 169extern int xics_set_irq_type(struct irq_data *d, unsigned int flow_type);
 170extern int xics_retrigger(struct irq_data *data);
 171#ifdef CONFIG_SMP
 172extern int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,
 173                               unsigned int strict_check);
 174#else
 175#define xics_get_irq_server(virq, cpumask, strict_check) (xics_default_server)
 176#endif
 177
 178
 179#endif /* _XICS_H */
 180