| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 1 | /* | 
 | 2 |  * Common definitions accross all variants of ICP and ICS interrupt | 
 | 3 |  * controllers. | 
 | 4 |  */ | 
 | 5 |  | 
 | 6 | #ifndef _XICS_H | 
 | 7 | #define _XICS_H | 
 | 8 |  | 
| Michael Ellerman | cd85257 | 2011-04-14 22:31:58 +0000 | [diff] [blame] | 9 | #include <linux/interrupt.h> | 
 | 10 |  | 
| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 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 | /* | 
| Yong Zhang | a3a9f3b | 2011-10-21 23:56:27 +0000 | [diff] [blame] | 18 |  * Mark IPIs as higher priority so we can take them inside interrupts | 
 | 19 |  * FIXME: still true now? | 
| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 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 */ | 
| Benjamin Herrenschmidt | 5c7c1e9 | 2011-09-19 17:45:02 +0000 | [diff] [blame] | 30 | #ifdef CONFIG_PPC_ICP_NATIVE | 
| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 31 | extern int icp_native_init(void); | 
| Benjamin Herrenschmidt | 5c7c1e9 | 2011-09-19 17:45:02 +0000 | [diff] [blame] | 32 | #else | 
 | 33 | static inline int icp_native_init(void) { return -ENODEV; } | 
 | 34 | #endif | 
| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 35 |  | 
 | 36 | /* PAPR ICP */ | 
| Benjamin Herrenschmidt | 5c7c1e9 | 2011-09-19 17:45:02 +0000 | [diff] [blame] | 37 | #ifdef CONFIG_PPC_ICP_HV | 
| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 38 | extern int icp_hv_init(void); | 
| Benjamin Herrenschmidt | 5c7c1e9 | 2011-09-19 17:45:02 +0000 | [diff] [blame] | 39 | #else | 
 | 40 | static inline int icp_hv_init(void) { return -ENODEV; } | 
 | 41 | #endif | 
| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 42 |  | 
 | 43 | /* ICP ops */ | 
 | 44 | struct icp_ops { | 
 | 45 | 	unsigned int (*get_irq)(void); | 
 | 46 | 	void (*eoi)(struct irq_data *d); | 
 | 47 | 	void (*set_priority)(unsigned char prio); | 
 | 48 | 	void (*teardown_cpu)(void); | 
 | 49 | 	void (*flush_ipi)(void); | 
 | 50 | #ifdef CONFIG_SMP | 
| Milton Miller | 23d72bf | 2011-05-10 19:29:39 +0000 | [diff] [blame] | 51 | 	void (*cause_ipi)(int cpu, unsigned long data); | 
| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 52 | 	irq_handler_t ipi_action; | 
 | 53 | #endif | 
 | 54 | }; | 
 | 55 |  | 
 | 56 | extern const struct icp_ops *icp_ops; | 
 | 57 |  | 
 | 58 | /* Native ICS */ | 
 | 59 | extern int ics_native_init(void); | 
 | 60 |  | 
 | 61 | /* RTAS ICS */ | 
| Benjamin Herrenschmidt | 5c7c1e9 | 2011-09-19 17:45:02 +0000 | [diff] [blame] | 62 | #ifdef CONFIG_PPC_ICS_RTAS | 
| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 63 | extern int ics_rtas_init(void); | 
| Benjamin Herrenschmidt | 5c7c1e9 | 2011-09-19 17:45:02 +0000 | [diff] [blame] | 64 | #else | 
 | 65 | static inline int ics_rtas_init(void) { return -ENODEV; } | 
 | 66 | #endif | 
 | 67 |  | 
 | 68 | /* HAL ICS */ | 
 | 69 | #ifdef CONFIG_PPC_POWERNV | 
 | 70 | extern int ics_opal_init(void); | 
 | 71 | #else | 
 | 72 | static inline int ics_opal_init(void) { return -ENODEV; } | 
 | 73 | #endif | 
| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 74 |  | 
 | 75 | /* ICS instance, hooked up to chip_data of an irq */ | 
 | 76 | struct ics { | 
 | 77 | 	struct list_head link; | 
 | 78 | 	int (*map)(struct ics *ics, unsigned int virq); | 
 | 79 | 	void (*mask_unknown)(struct ics *ics, unsigned long vec); | 
 | 80 | 	long (*get_server)(struct ics *ics, unsigned long vec); | 
| Michael Ellerman | 5ca1237 | 2011-04-14 22:31:59 +0000 | [diff] [blame] | 81 | 	int (*host_match)(struct ics *ics, struct device_node *node); | 
| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 82 | 	char data[]; | 
 | 83 | }; | 
 | 84 |  | 
 | 85 | /* Commons */ | 
 | 86 | extern unsigned int xics_default_server; | 
 | 87 | extern unsigned int xics_default_distrib_server; | 
 | 88 | extern unsigned int xics_interrupt_server_size; | 
| Grant Likely | bae1d8f | 2012-02-14 14:06:50 -0700 | [diff] [blame] | 89 | extern struct irq_domain *xics_host; | 
| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 90 |  | 
 | 91 | struct xics_cppr { | 
 | 92 | 	unsigned char stack[MAX_NUM_PRIORITIES]; | 
 | 93 | 	int index; | 
 | 94 | }; | 
 | 95 |  | 
 | 96 | DECLARE_PER_CPU(struct xics_cppr, xics_cppr); | 
 | 97 |  | 
 | 98 | static inline void xics_push_cppr(unsigned int vec) | 
 | 99 | { | 
 | 100 | 	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | 
 | 101 |  | 
 | 102 | 	if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1)) | 
 | 103 | 		return; | 
 | 104 |  | 
 | 105 | 	if (vec == XICS_IPI) | 
 | 106 | 		os_cppr->stack[++os_cppr->index] = IPI_PRIORITY; | 
 | 107 | 	else | 
 | 108 | 		os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY; | 
 | 109 | } | 
 | 110 |  | 
 | 111 | static inline unsigned char xics_pop_cppr(void) | 
 | 112 | { | 
 | 113 | 	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | 
 | 114 |  | 
 | 115 | 	if (WARN_ON(os_cppr->index < 1)) | 
 | 116 | 		return LOWEST_PRIORITY; | 
 | 117 |  | 
 | 118 | 	return os_cppr->stack[--os_cppr->index]; | 
 | 119 | } | 
 | 120 |  | 
 | 121 | static inline void xics_set_base_cppr(unsigned char cppr) | 
 | 122 | { | 
 | 123 | 	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | 
 | 124 |  | 
 | 125 | 	/* we only really want to set the priority when there's | 
 | 126 | 	 * just one cppr value on the stack | 
 | 127 | 	 */ | 
 | 128 | 	WARN_ON(os_cppr->index != 0); | 
 | 129 |  | 
 | 130 | 	os_cppr->stack[0] = cppr; | 
 | 131 | } | 
 | 132 |  | 
 | 133 | static inline unsigned char xics_cppr_top(void) | 
 | 134 | { | 
 | 135 | 	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | 
 | 136 | 	 | 
 | 137 | 	return os_cppr->stack[os_cppr->index]; | 
 | 138 | } | 
 | 139 |  | 
 | 140 | DECLARE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message); | 
 | 141 |  | 
 | 142 | extern void xics_init(void); | 
 | 143 | extern void xics_setup_cpu(void); | 
 | 144 | extern void xics_update_irq_servers(void); | 
 | 145 | extern void xics_set_cpu_giq(unsigned int gserver, unsigned int join); | 
 | 146 | extern void xics_mask_unknown_vec(unsigned int vec); | 
 | 147 | extern irqreturn_t xics_ipi_dispatch(int cpu); | 
 | 148 | extern int xics_smp_probe(void); | 
 | 149 | extern void xics_register_ics(struct ics *ics); | 
 | 150 | extern void xics_teardown_cpu(void); | 
 | 151 | extern void xics_kexec_teardown_cpu(int secondary); | 
 | 152 | extern void xics_migrate_irqs_away(void); | 
| Gavin Shan | 137436c | 2013-04-25 19:20:59 +0000 | [diff] [blame] | 153 | extern void icp_native_eoi(struct irq_data *d); | 
| Benjamin Herrenschmidt | 0b05ac6 | 2011-04-04 13:46:58 +1000 | [diff] [blame] | 154 | #ifdef CONFIG_SMP | 
 | 155 | extern int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask, | 
 | 156 | 			       unsigned int strict_check); | 
 | 157 | #else | 
 | 158 | #define xics_get_irq_server(virq, cpumask, strict_check) (xics_default_server) | 
 | 159 | #endif | 
 | 160 |  | 
 | 161 |  | 
 | 162 | #endif /* _XICS_H */ |