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/* Native ICS */
  69extern int ics_native_init(void);
  70
  71/* RTAS ICS */
  72#ifdef CONFIG_PPC_ICS_RTAS
  73extern int ics_rtas_init(void);
  74#else
  75static inline int ics_rtas_init(void) { return -ENODEV; }
  76#endif
  77
  78/* HAL ICS */
  79#ifdef CONFIG_PPC_POWERNV
  80extern int ics_opal_init(void);
  81#else
  82static inline int ics_opal_init(void) { return -ENODEV; }
  83#endif
  84
  85/* ICS instance, hooked up to chip_data of an irq */
  86struct ics {
  87        struct list_head link;
  88        int (*map)(struct ics *ics, unsigned int virq);
  89        void (*mask_unknown)(struct ics *ics, unsigned long vec);
  90        long (*get_server)(struct ics *ics, unsigned long vec);
  91        int (*host_match)(struct ics *ics, struct device_node *node);
  92        char data[];
  93};
  94
  95/* Commons */
  96extern unsigned int xics_default_server;
  97extern unsigned int xics_default_distrib_server;
  98extern unsigned int xics_interrupt_server_size;
  99extern struct irq_domain *xics_host;
 100
 101struct xics_cppr {
 102        unsigned char stack[MAX_NUM_PRIORITIES];
 103        int index;
 104};
 105
 106DECLARE_PER_CPU(struct xics_cppr, xics_cppr);
 107
 108static inline void xics_push_cppr(unsigned int vec)
 109{
 110        struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
 111
 112        if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1))
 113                return;
 114
 115        if (vec == XICS_IPI)
 116                os_cppr->stack[++os_cppr->index] = IPI_PRIORITY;
 117        else
 118                os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY;
 119}
 120
 121static inline unsigned char xics_pop_cppr(void)
 122{
 123        struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
 124
 125        if (WARN_ON(os_cppr->index < 1))
 126                return LOWEST_PRIORITY;
 127
 128        return os_cppr->stack[--os_cppr->index];
 129}
 130
 131static inline void xics_set_base_cppr(unsigned char cppr)
 132{
 133        struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
 134
 135        /* we only really want to set the priority when there's
 136         * just one cppr value on the stack
 137         */
 138        WARN_ON(os_cppr->index != 0);
 139
 140        os_cppr->stack[0] = cppr;
 141}
 142
 143static inline unsigned char xics_cppr_top(void)
 144{
 145        struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr);
 146        
 147        return os_cppr->stack[os_cppr->index];
 148}
 149
 150DECLARE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message);
 151
 152extern void xics_init(void);
 153extern void xics_setup_cpu(void);
 154extern void xics_update_irq_servers(void);
 155extern void xics_set_cpu_giq(unsigned int gserver, unsigned int join);
 156extern void xics_mask_unknown_vec(unsigned int vec);
 157extern irqreturn_t xics_ipi_dispatch(int cpu);
 158extern void xics_smp_probe(void);
 159extern void xics_register_ics(struct ics *ics);
 160extern void xics_teardown_cpu(void);
 161extern void xics_kexec_teardown_cpu(int secondary);
 162extern void xics_migrate_irqs_away(void);
 163extern void icp_native_eoi(struct irq_data *d);
 164extern int xics_set_irq_type(struct irq_data *d, unsigned int flow_type);
 165extern int xics_retrigger(struct irq_data *data);
 166#ifdef CONFIG_SMP
 167extern int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,
 168                               unsigned int strict_check);
 169#else
 170#define xics_get_irq_server(virq, cpumask, strict_check) (xics_default_server)
 171#endif
 172
 173
 174#endif /* _XICS_H */
 175