| .. | .. |
|---|
| 7 | 7 | * Copyright (C) 1999 - 2001 Kanoj Sarcar |
|---|
| 8 | 8 | */ |
|---|
| 9 | 9 | |
|---|
| 10 | | -#undef DEBUG |
|---|
| 11 | | - |
|---|
| 12 | | -#include <linux/init.h> |
|---|
| 13 | | -#include <linux/irq.h> |
|---|
| 14 | | -#include <linux/errno.h> |
|---|
| 15 | | -#include <linux/signal.h> |
|---|
| 16 | | -#include <linux/sched.h> |
|---|
| 17 | | -#include <linux/types.h> |
|---|
| 18 | 10 | #include <linux/interrupt.h> |
|---|
| 11 | +#include <linux/irq.h> |
|---|
| 19 | 12 | #include <linux/ioport.h> |
|---|
| 20 | | -#include <linux/timex.h> |
|---|
| 21 | | -#include <linux/smp.h> |
|---|
| 22 | | -#include <linux/random.h> |
|---|
| 23 | 13 | #include <linux/kernel.h> |
|---|
| 24 | | -#include <linux/kernel_stat.h> |
|---|
| 25 | | -#include <linux/delay.h> |
|---|
| 26 | 14 | #include <linux/bitops.h> |
|---|
| 15 | +#include <linux/sched.h> |
|---|
| 27 | 16 | |
|---|
| 28 | | -#include <asm/bootinfo.h> |
|---|
| 29 | 17 | #include <asm/io.h> |
|---|
| 30 | | -#include <asm/mipsregs.h> |
|---|
| 31 | | - |
|---|
| 32 | | -#include <asm/processor.h> |
|---|
| 18 | +#include <asm/irq_cpu.h> |
|---|
| 33 | 19 | #include <asm/sn/addrs.h> |
|---|
| 34 | 20 | #include <asm/sn/agent.h> |
|---|
| 35 | 21 | #include <asm/sn/arch.h> |
|---|
| 36 | | -#include <asm/sn/hub.h> |
|---|
| 37 | 22 | #include <asm/sn/intr.h> |
|---|
| 23 | +#include <asm/sn/irq_alloc.h> |
|---|
| 38 | 24 | |
|---|
| 39 | | -/* |
|---|
| 40 | | - * Linux has a controller-independent x86 interrupt architecture. |
|---|
| 41 | | - * every controller has a 'controller-template', that is used |
|---|
| 42 | | - * by the main code to do the right thing. Each driver-visible |
|---|
| 43 | | - * interrupt source is transparently wired to the appropriate |
|---|
| 44 | | - * controller. Thus drivers need not be aware of the |
|---|
| 45 | | - * interrupt-controller. |
|---|
| 46 | | - * |
|---|
| 47 | | - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, |
|---|
| 48 | | - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. |
|---|
| 49 | | - * (IO-APICs assumed to be messaging to Pentium local-APICs) |
|---|
| 50 | | - * |
|---|
| 51 | | - * the code is designed to be easily extended with new/different |
|---|
| 52 | | - * interrupt controllers, without having to do assembly magic. |
|---|
| 53 | | - */ |
|---|
| 25 | +struct hub_irq_data { |
|---|
| 26 | + u64 *irq_mask[2]; |
|---|
| 27 | + cpuid_t cpu; |
|---|
| 28 | +}; |
|---|
| 54 | 29 | |
|---|
| 55 | | -extern asmlinkage void ip27_irq(void); |
|---|
| 30 | +static DECLARE_BITMAP(hub_irq_map, IP27_HUB_IRQ_COUNT); |
|---|
| 56 | 31 | |
|---|
| 57 | | -/* |
|---|
| 58 | | - * Find first bit set |
|---|
| 59 | | - */ |
|---|
| 60 | | -static int ms1bit(unsigned long x) |
|---|
| 32 | +static DEFINE_PER_CPU(unsigned long [2], irq_enable_mask); |
|---|
| 33 | + |
|---|
| 34 | +static inline int alloc_level(void) |
|---|
| 61 | 35 | { |
|---|
| 62 | | - int b = 0, s; |
|---|
| 36 | + int level; |
|---|
| 63 | 37 | |
|---|
| 64 | | - s = 16; if (x >> 16 == 0) s = 0; b += s; x >>= s; |
|---|
| 65 | | - s = 8; if (x >> 8 == 0) s = 0; b += s; x >>= s; |
|---|
| 66 | | - s = 4; if (x >> 4 == 0) s = 0; b += s; x >>= s; |
|---|
| 67 | | - s = 2; if (x >> 2 == 0) s = 0; b += s; x >>= s; |
|---|
| 68 | | - s = 1; if (x >> 1 == 0) s = 0; b += s; |
|---|
| 38 | +again: |
|---|
| 39 | + level = find_first_zero_bit(hub_irq_map, IP27_HUB_IRQ_COUNT); |
|---|
| 40 | + if (level >= IP27_HUB_IRQ_COUNT) |
|---|
| 41 | + return -ENOSPC; |
|---|
| 69 | 42 | |
|---|
| 70 | | - return b; |
|---|
| 43 | + if (test_and_set_bit(level, hub_irq_map)) |
|---|
| 44 | + goto again; |
|---|
| 45 | + |
|---|
| 46 | + return level; |
|---|
| 71 | 47 | } |
|---|
| 48 | + |
|---|
| 49 | +static void enable_hub_irq(struct irq_data *d) |
|---|
| 50 | +{ |
|---|
| 51 | + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); |
|---|
| 52 | + unsigned long *mask = per_cpu(irq_enable_mask, hd->cpu); |
|---|
| 53 | + |
|---|
| 54 | + set_bit(d->hwirq, mask); |
|---|
| 55 | + __raw_writeq(mask[0], hd->irq_mask[0]); |
|---|
| 56 | + __raw_writeq(mask[1], hd->irq_mask[1]); |
|---|
| 57 | +} |
|---|
| 58 | + |
|---|
| 59 | +static void disable_hub_irq(struct irq_data *d) |
|---|
| 60 | +{ |
|---|
| 61 | + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); |
|---|
| 62 | + unsigned long *mask = per_cpu(irq_enable_mask, hd->cpu); |
|---|
| 63 | + |
|---|
| 64 | + clear_bit(d->hwirq, mask); |
|---|
| 65 | + __raw_writeq(mask[0], hd->irq_mask[0]); |
|---|
| 66 | + __raw_writeq(mask[1], hd->irq_mask[1]); |
|---|
| 67 | +} |
|---|
| 68 | + |
|---|
| 69 | +static void setup_hub_mask(struct hub_irq_data *hd, const struct cpumask *mask) |
|---|
| 70 | +{ |
|---|
| 71 | + nasid_t nasid; |
|---|
| 72 | + int cpu; |
|---|
| 73 | + |
|---|
| 74 | + cpu = cpumask_first_and(mask, cpu_online_mask); |
|---|
| 75 | + if (cpu >= nr_cpu_ids) |
|---|
| 76 | + cpu = cpumask_any(cpu_online_mask); |
|---|
| 77 | + |
|---|
| 78 | + nasid = cpu_to_node(cpu); |
|---|
| 79 | + hd->cpu = cpu; |
|---|
| 80 | + if (!cputoslice(cpu)) { |
|---|
| 81 | + hd->irq_mask[0] = REMOTE_HUB_PTR(nasid, PI_INT_MASK0_A); |
|---|
| 82 | + hd->irq_mask[1] = REMOTE_HUB_PTR(nasid, PI_INT_MASK1_A); |
|---|
| 83 | + } else { |
|---|
| 84 | + hd->irq_mask[0] = REMOTE_HUB_PTR(nasid, PI_INT_MASK0_B); |
|---|
| 85 | + hd->irq_mask[1] = REMOTE_HUB_PTR(nasid, PI_INT_MASK1_B); |
|---|
| 86 | + } |
|---|
| 87 | +} |
|---|
| 88 | + |
|---|
| 89 | +static int set_affinity_hub_irq(struct irq_data *d, const struct cpumask *mask, |
|---|
| 90 | + bool force) |
|---|
| 91 | +{ |
|---|
| 92 | + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); |
|---|
| 93 | + |
|---|
| 94 | + if (!hd) |
|---|
| 95 | + return -EINVAL; |
|---|
| 96 | + |
|---|
| 97 | + if (irqd_is_started(d)) |
|---|
| 98 | + disable_hub_irq(d); |
|---|
| 99 | + |
|---|
| 100 | + setup_hub_mask(hd, mask); |
|---|
| 101 | + |
|---|
| 102 | + if (irqd_is_started(d)) |
|---|
| 103 | + enable_hub_irq(d); |
|---|
| 104 | + |
|---|
| 105 | + irq_data_update_effective_affinity(d, cpumask_of(hd->cpu)); |
|---|
| 106 | + |
|---|
| 107 | + return 0; |
|---|
| 108 | +} |
|---|
| 109 | + |
|---|
| 110 | +static struct irq_chip hub_irq_type = { |
|---|
| 111 | + .name = "HUB", |
|---|
| 112 | + .irq_mask = disable_hub_irq, |
|---|
| 113 | + .irq_unmask = enable_hub_irq, |
|---|
| 114 | + .irq_set_affinity = set_affinity_hub_irq, |
|---|
| 115 | +}; |
|---|
| 116 | + |
|---|
| 117 | +static int hub_domain_alloc(struct irq_domain *domain, unsigned int virq, |
|---|
| 118 | + unsigned int nr_irqs, void *arg) |
|---|
| 119 | +{ |
|---|
| 120 | + struct irq_alloc_info *info = arg; |
|---|
| 121 | + struct hub_irq_data *hd; |
|---|
| 122 | + struct hub_data *hub; |
|---|
| 123 | + struct irq_desc *desc; |
|---|
| 124 | + int swlevel; |
|---|
| 125 | + |
|---|
| 126 | + if (nr_irqs > 1 || !info) |
|---|
| 127 | + return -EINVAL; |
|---|
| 128 | + |
|---|
| 129 | + hd = kzalloc(sizeof(*hd), GFP_KERNEL); |
|---|
| 130 | + if (!hd) |
|---|
| 131 | + return -ENOMEM; |
|---|
| 132 | + |
|---|
| 133 | + swlevel = alloc_level(); |
|---|
| 134 | + if (unlikely(swlevel < 0)) { |
|---|
| 135 | + kfree(hd); |
|---|
| 136 | + return -EAGAIN; |
|---|
| 137 | + } |
|---|
| 138 | + irq_domain_set_info(domain, virq, swlevel, &hub_irq_type, hd, |
|---|
| 139 | + handle_level_irq, NULL, NULL); |
|---|
| 140 | + |
|---|
| 141 | + /* use CPU connected to nearest hub */ |
|---|
| 142 | + hub = hub_data(info->nasid); |
|---|
| 143 | + setup_hub_mask(hd, &hub->h_cpus); |
|---|
| 144 | + info->nasid = cpu_to_node(hd->cpu); |
|---|
| 145 | + |
|---|
| 146 | + /* Make sure it's not already pending when we connect it. */ |
|---|
| 147 | + REMOTE_HUB_CLR_INTR(info->nasid, swlevel); |
|---|
| 148 | + |
|---|
| 149 | + desc = irq_to_desc(virq); |
|---|
| 150 | + desc->irq_common_data.node = info->nasid; |
|---|
| 151 | + cpumask_copy(desc->irq_common_data.affinity, &hub->h_cpus); |
|---|
| 152 | + |
|---|
| 153 | + return 0; |
|---|
| 154 | +} |
|---|
| 155 | + |
|---|
| 156 | +static void hub_domain_free(struct irq_domain *domain, |
|---|
| 157 | + unsigned int virq, unsigned int nr_irqs) |
|---|
| 158 | +{ |
|---|
| 159 | + struct irq_data *irqd; |
|---|
| 160 | + |
|---|
| 161 | + if (nr_irqs > 1) |
|---|
| 162 | + return; |
|---|
| 163 | + |
|---|
| 164 | + irqd = irq_domain_get_irq_data(domain, virq); |
|---|
| 165 | + if (irqd && irqd->chip_data) |
|---|
| 166 | + kfree(irqd->chip_data); |
|---|
| 167 | +} |
|---|
| 168 | + |
|---|
| 169 | +static const struct irq_domain_ops hub_domain_ops = { |
|---|
| 170 | + .alloc = hub_domain_alloc, |
|---|
| 171 | + .free = hub_domain_free, |
|---|
| 172 | +}; |
|---|
| 72 | 173 | |
|---|
| 73 | 174 | /* |
|---|
| 74 | 175 | * This code is unnecessarily complex, because we do |
|---|
| .. | .. |
|---|
| 82 | 183 | * Kanoj 05.13.00 |
|---|
| 83 | 184 | */ |
|---|
| 84 | 185 | |
|---|
| 85 | | -static void ip27_do_irq_mask0(void) |
|---|
| 186 | +static void ip27_do_irq_mask0(struct irq_desc *desc) |
|---|
| 86 | 187 | { |
|---|
| 87 | | - int irq, swlevel; |
|---|
| 88 | | - hubreg_t pend0, mask0; |
|---|
| 89 | 188 | cpuid_t cpu = smp_processor_id(); |
|---|
| 90 | | - int pi_int_mask0 = |
|---|
| 91 | | - (cputoslice(cpu) == 0) ? PI_INT_MASK0_A : PI_INT_MASK0_B; |
|---|
| 189 | + unsigned long *mask = per_cpu(irq_enable_mask, cpu); |
|---|
| 190 | + struct irq_domain *domain; |
|---|
| 191 | + u64 pend0; |
|---|
| 192 | + int irq; |
|---|
| 92 | 193 | |
|---|
| 93 | 194 | /* copied from Irix intpend0() */ |
|---|
| 94 | 195 | pend0 = LOCAL_HUB_L(PI_INT_PEND0); |
|---|
| 95 | | - mask0 = LOCAL_HUB_L(pi_int_mask0); |
|---|
| 96 | 196 | |
|---|
| 97 | | - pend0 &= mask0; /* Pick intrs we should look at */ |
|---|
| 197 | + pend0 &= mask[0]; /* Pick intrs we should look at */ |
|---|
| 98 | 198 | if (!pend0) |
|---|
| 99 | 199 | return; |
|---|
| 100 | 200 | |
|---|
| 101 | | - swlevel = ms1bit(pend0); |
|---|
| 102 | 201 | #ifdef CONFIG_SMP |
|---|
| 103 | 202 | if (pend0 & (1UL << CPU_RESCHED_A_IRQ)) { |
|---|
| 104 | 203 | LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); |
|---|
| .. | .. |
|---|
| 108 | 207 | scheduler_ipi(); |
|---|
| 109 | 208 | } else if (pend0 & (1UL << CPU_CALL_A_IRQ)) { |
|---|
| 110 | 209 | LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ); |
|---|
| 111 | | - irq_enter(); |
|---|
| 112 | 210 | generic_smp_call_function_interrupt(); |
|---|
| 113 | | - irq_exit(); |
|---|
| 114 | 211 | } else if (pend0 & (1UL << CPU_CALL_B_IRQ)) { |
|---|
| 115 | 212 | LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ); |
|---|
| 116 | | - irq_enter(); |
|---|
| 117 | 213 | generic_smp_call_function_interrupt(); |
|---|
| 118 | | - irq_exit(); |
|---|
| 119 | 214 | } else |
|---|
| 120 | 215 | #endif |
|---|
| 121 | 216 | { |
|---|
| 122 | | - /* "map" swlevel to irq */ |
|---|
| 123 | | - struct slice_data *si = cpu_data[cpu].data; |
|---|
| 124 | | - |
|---|
| 125 | | - irq = si->level_to_irq[swlevel]; |
|---|
| 126 | | - do_IRQ(irq); |
|---|
| 217 | + domain = irq_desc_get_handler_data(desc); |
|---|
| 218 | + irq = irq_linear_revmap(domain, __ffs(pend0)); |
|---|
| 219 | + if (irq) |
|---|
| 220 | + generic_handle_irq(irq); |
|---|
| 221 | + else |
|---|
| 222 | + spurious_interrupt(); |
|---|
| 127 | 223 | } |
|---|
| 128 | 224 | |
|---|
| 129 | 225 | LOCAL_HUB_L(PI_INT_PEND0); |
|---|
| 130 | 226 | } |
|---|
| 131 | 227 | |
|---|
| 132 | | -static void ip27_do_irq_mask1(void) |
|---|
| 228 | +static void ip27_do_irq_mask1(struct irq_desc *desc) |
|---|
| 133 | 229 | { |
|---|
| 134 | | - int irq, swlevel; |
|---|
| 135 | | - hubreg_t pend1, mask1; |
|---|
| 136 | 230 | cpuid_t cpu = smp_processor_id(); |
|---|
| 137 | | - int pi_int_mask1 = (cputoslice(cpu) == 0) ? PI_INT_MASK1_A : PI_INT_MASK1_B; |
|---|
| 138 | | - struct slice_data *si = cpu_data[cpu].data; |
|---|
| 231 | + unsigned long *mask = per_cpu(irq_enable_mask, cpu); |
|---|
| 232 | + struct irq_domain *domain; |
|---|
| 233 | + u64 pend1; |
|---|
| 234 | + int irq; |
|---|
| 139 | 235 | |
|---|
| 140 | 236 | /* copied from Irix intpend0() */ |
|---|
| 141 | 237 | pend1 = LOCAL_HUB_L(PI_INT_PEND1); |
|---|
| 142 | | - mask1 = LOCAL_HUB_L(pi_int_mask1); |
|---|
| 143 | 238 | |
|---|
| 144 | | - pend1 &= mask1; /* Pick intrs we should look at */ |
|---|
| 239 | + pend1 &= mask[1]; /* Pick intrs we should look at */ |
|---|
| 145 | 240 | if (!pend1) |
|---|
| 146 | 241 | return; |
|---|
| 147 | 242 | |
|---|
| 148 | | - swlevel = ms1bit(pend1); |
|---|
| 149 | | - /* "map" swlevel to irq */ |
|---|
| 150 | | - irq = si->level_to_irq[swlevel]; |
|---|
| 151 | | - LOCAL_HUB_CLR_INTR(swlevel); |
|---|
| 152 | | - do_IRQ(irq); |
|---|
| 243 | + domain = irq_desc_get_handler_data(desc); |
|---|
| 244 | + irq = irq_linear_revmap(domain, __ffs(pend1) + 64); |
|---|
| 245 | + if (irq) |
|---|
| 246 | + generic_handle_irq(irq); |
|---|
| 247 | + else |
|---|
| 248 | + spurious_interrupt(); |
|---|
| 153 | 249 | |
|---|
| 154 | 250 | LOCAL_HUB_L(PI_INT_PEND1); |
|---|
| 155 | 251 | } |
|---|
| 156 | 252 | |
|---|
| 157 | | -static void ip27_prof_timer(void) |
|---|
| 253 | +void install_ipi(void) |
|---|
| 158 | 254 | { |
|---|
| 159 | | - panic("CPU %d got a profiling interrupt", smp_processor_id()); |
|---|
| 160 | | -} |
|---|
| 255 | + int cpu = smp_processor_id(); |
|---|
| 256 | + unsigned long *mask = per_cpu(irq_enable_mask, cpu); |
|---|
| 257 | + int slice = LOCAL_HUB_L(PI_CPU_NUM); |
|---|
| 258 | + int resched, call; |
|---|
| 161 | 259 | |
|---|
| 162 | | -static void ip27_hub_error(void) |
|---|
| 163 | | -{ |
|---|
| 164 | | - panic("CPU %d got a hub error interrupt", smp_processor_id()); |
|---|
| 165 | | -} |
|---|
| 260 | + resched = CPU_RESCHED_A_IRQ + slice; |
|---|
| 261 | + set_bit(resched, mask); |
|---|
| 262 | + LOCAL_HUB_CLR_INTR(resched); |
|---|
| 166 | 263 | |
|---|
| 167 | | -asmlinkage void plat_irq_dispatch(void) |
|---|
| 168 | | -{ |
|---|
| 169 | | - unsigned long pending = read_c0_cause() & read_c0_status(); |
|---|
| 170 | | - extern unsigned int rt_timer_irq; |
|---|
| 264 | + call = CPU_CALL_A_IRQ + slice; |
|---|
| 265 | + set_bit(call, mask); |
|---|
| 266 | + LOCAL_HUB_CLR_INTR(call); |
|---|
| 171 | 267 | |
|---|
| 172 | | - if (pending & CAUSEF_IP4) |
|---|
| 173 | | - do_IRQ(rt_timer_irq); |
|---|
| 174 | | - else if (pending & CAUSEF_IP2) /* PI_INT_PEND_0 or CC_PEND_{A|B} */ |
|---|
| 175 | | - ip27_do_irq_mask0(); |
|---|
| 176 | | - else if (pending & CAUSEF_IP3) /* PI_INT_PEND_1 */ |
|---|
| 177 | | - ip27_do_irq_mask1(); |
|---|
| 178 | | - else if (pending & CAUSEF_IP5) |
|---|
| 179 | | - ip27_prof_timer(); |
|---|
| 180 | | - else if (pending & CAUSEF_IP6) |
|---|
| 181 | | - ip27_hub_error(); |
|---|
| 268 | + if (slice == 0) { |
|---|
| 269 | + LOCAL_HUB_S(PI_INT_MASK0_A, mask[0]); |
|---|
| 270 | + LOCAL_HUB_S(PI_INT_MASK1_A, mask[1]); |
|---|
| 271 | + } else { |
|---|
| 272 | + LOCAL_HUB_S(PI_INT_MASK0_B, mask[0]); |
|---|
| 273 | + LOCAL_HUB_S(PI_INT_MASK1_B, mask[1]); |
|---|
| 274 | + } |
|---|
| 182 | 275 | } |
|---|
| 183 | 276 | |
|---|
| 184 | 277 | void __init arch_init_irq(void) |
|---|
| 185 | 278 | { |
|---|
| 186 | | -} |
|---|
| 279 | + struct irq_domain *domain; |
|---|
| 280 | + struct fwnode_handle *fn; |
|---|
| 281 | + int i; |
|---|
| 187 | 282 | |
|---|
| 188 | | -void install_ipi(void) |
|---|
| 189 | | -{ |
|---|
| 190 | | - int slice = LOCAL_HUB_L(PI_CPU_NUM); |
|---|
| 191 | | - int cpu = smp_processor_id(); |
|---|
| 192 | | - struct slice_data *si = cpu_data[cpu].data; |
|---|
| 193 | | - struct hub_data *hub = hub_data(cpu_to_node(cpu)); |
|---|
| 194 | | - int resched, call; |
|---|
| 283 | + mips_cpu_irq_init(); |
|---|
| 195 | 284 | |
|---|
| 196 | | - resched = CPU_RESCHED_A_IRQ + slice; |
|---|
| 197 | | - __set_bit(resched, hub->irq_alloc_mask); |
|---|
| 198 | | - __set_bit(resched, si->irq_enable_mask); |
|---|
| 199 | | - LOCAL_HUB_CLR_INTR(resched); |
|---|
| 285 | + /* |
|---|
| 286 | + * Some interrupts are reserved by hardware or by software convention. |
|---|
| 287 | + * Mark these as reserved right away so they won't be used accidentally |
|---|
| 288 | + * later. |
|---|
| 289 | + */ |
|---|
| 290 | + for (i = 0; i <= CPU_CALL_B_IRQ; i++) |
|---|
| 291 | + set_bit(i, hub_irq_map); |
|---|
| 200 | 292 | |
|---|
| 201 | | - call = CPU_CALL_A_IRQ + slice; |
|---|
| 202 | | - __set_bit(call, hub->irq_alloc_mask); |
|---|
| 203 | | - __set_bit(call, si->irq_enable_mask); |
|---|
| 204 | | - LOCAL_HUB_CLR_INTR(call); |
|---|
| 293 | + for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) |
|---|
| 294 | + set_bit(i, hub_irq_map); |
|---|
| 205 | 295 | |
|---|
| 206 | | - if (slice == 0) { |
|---|
| 207 | | - LOCAL_HUB_S(PI_INT_MASK0_A, si->irq_enable_mask[0]); |
|---|
| 208 | | - LOCAL_HUB_S(PI_INT_MASK1_A, si->irq_enable_mask[1]); |
|---|
| 209 | | - } else { |
|---|
| 210 | | - LOCAL_HUB_S(PI_INT_MASK0_B, si->irq_enable_mask[0]); |
|---|
| 211 | | - LOCAL_HUB_S(PI_INT_MASK1_B, si->irq_enable_mask[1]); |
|---|
| 212 | | - } |
|---|
| 296 | + fn = irq_domain_alloc_named_fwnode("HUB"); |
|---|
| 297 | + WARN_ON(fn == NULL); |
|---|
| 298 | + if (!fn) |
|---|
| 299 | + return; |
|---|
| 300 | + domain = irq_domain_create_linear(fn, IP27_HUB_IRQ_COUNT, |
|---|
| 301 | + &hub_domain_ops, NULL); |
|---|
| 302 | + WARN_ON(domain == NULL); |
|---|
| 303 | + if (!domain) |
|---|
| 304 | + return; |
|---|
| 305 | + |
|---|
| 306 | + irq_set_default_host(domain); |
|---|
| 307 | + |
|---|
| 308 | + irq_set_percpu_devid(IP27_HUB_PEND0_IRQ); |
|---|
| 309 | + irq_set_chained_handler_and_data(IP27_HUB_PEND0_IRQ, ip27_do_irq_mask0, |
|---|
| 310 | + domain); |
|---|
| 311 | + irq_set_percpu_devid(IP27_HUB_PEND1_IRQ); |
|---|
| 312 | + irq_set_chained_handler_and_data(IP27_HUB_PEND1_IRQ, ip27_do_irq_mask1, |
|---|
| 313 | + domain); |
|---|
| 213 | 314 | } |
|---|