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