Lines Matching +full:int +full:- +full:fwd +full:- +full:mask
1 // SPDX-License-Identifier: GPL-2.0-only
40 unsigned int n_words;
80 static inline unsigned int reg_status(struct bcm7038_l1_chip *intc, in reg_status()
81 unsigned int word) in reg_status()
83 return (0 * intc->n_words + word) * sizeof(u32); in reg_status()
86 static inline unsigned int reg_mask_status(struct bcm7038_l1_chip *intc, in reg_mask_status()
87 unsigned int word) in reg_mask_status()
89 return (1 * intc->n_words + word) * sizeof(u32); in reg_mask_status()
92 static inline unsigned int reg_mask_set(struct bcm7038_l1_chip *intc, in reg_mask_set()
93 unsigned int word) in reg_mask_set()
95 return (2 * intc->n_words + word) * sizeof(u32); in reg_mask_set()
98 static inline unsigned int reg_mask_clr(struct bcm7038_l1_chip *intc, in reg_mask_clr()
99 unsigned int word) in reg_mask_clr()
101 return (3 * intc->n_words + word) * sizeof(u32); in reg_mask_clr()
125 unsigned int idx; in bcm7038_l1_irq_handle()
128 cpu = intc->cpus[cpu_logical_map(smp_processor_id())]; in bcm7038_l1_irq_handle()
130 cpu = intc->cpus[0]; in bcm7038_l1_irq_handle()
135 for (idx = 0; idx < intc->n_words; idx++) { in bcm7038_l1_irq_handle()
136 int base = idx * IRQS_PER_WORD; in bcm7038_l1_irq_handle()
138 int hwirq; in bcm7038_l1_irq_handle()
140 raw_spin_lock_irqsave(&intc->lock, flags); in bcm7038_l1_irq_handle()
141 pending = l1_readl(cpu->map_base + reg_status(intc, idx)) & in bcm7038_l1_irq_handle()
142 ~cpu->mask_cache[idx]; in bcm7038_l1_irq_handle()
143 raw_spin_unlock_irqrestore(&intc->lock, flags); in bcm7038_l1_irq_handle()
146 generic_handle_domain_irq(intc->domain, base + hwirq); in bcm7038_l1_irq_handle()
152 static void __bcm7038_l1_unmask(struct irq_data *d, unsigned int cpu_idx) in __bcm7038_l1_unmask()
155 u32 word = d->hwirq / IRQS_PER_WORD; in __bcm7038_l1_unmask()
156 u32 mask = BIT(d->hwirq % IRQS_PER_WORD); in __bcm7038_l1_unmask() local
158 intc->cpus[cpu_idx]->mask_cache[word] &= ~mask; in __bcm7038_l1_unmask()
159 l1_writel(mask, intc->cpus[cpu_idx]->map_base + in __bcm7038_l1_unmask()
163 static void __bcm7038_l1_mask(struct irq_data *d, unsigned int cpu_idx) in __bcm7038_l1_mask()
166 u32 word = d->hwirq / IRQS_PER_WORD; in __bcm7038_l1_mask()
167 u32 mask = BIT(d->hwirq % IRQS_PER_WORD); in __bcm7038_l1_mask() local
169 intc->cpus[cpu_idx]->mask_cache[word] |= mask; in __bcm7038_l1_mask()
170 l1_writel(mask, intc->cpus[cpu_idx]->map_base + in __bcm7038_l1_mask()
179 raw_spin_lock_irqsave(&intc->lock, flags); in bcm7038_l1_unmask()
180 __bcm7038_l1_unmask(d, intc->affinity[d->hwirq]); in bcm7038_l1_unmask()
181 raw_spin_unlock_irqrestore(&intc->lock, flags); in bcm7038_l1_unmask()
189 raw_spin_lock_irqsave(&intc->lock, flags); in bcm7038_l1_mask()
190 __bcm7038_l1_mask(d, intc->affinity[d->hwirq]); in bcm7038_l1_mask()
191 raw_spin_unlock_irqrestore(&intc->lock, flags); in bcm7038_l1_mask()
195 static int bcm7038_l1_set_affinity(struct irq_data *d, in bcm7038_l1_set_affinity()
201 irq_hw_number_t hw = d->hwirq; in bcm7038_l1_set_affinity()
203 u32 mask = BIT(hw % IRQS_PER_WORD); in bcm7038_l1_set_affinity() local
204 unsigned int first_cpu = cpumask_any_and(dest, cpu_online_mask); in bcm7038_l1_set_affinity()
207 raw_spin_lock_irqsave(&intc->lock, flags); in bcm7038_l1_set_affinity()
209 was_disabled = !!(intc->cpus[intc->affinity[hw]]->mask_cache[word] & in bcm7038_l1_set_affinity()
210 mask); in bcm7038_l1_set_affinity()
211 __bcm7038_l1_mask(d, intc->affinity[hw]); in bcm7038_l1_set_affinity()
212 intc->affinity[hw] = first_cpu; in bcm7038_l1_set_affinity()
216 raw_spin_unlock_irqrestore(&intc->lock, flags); in bcm7038_l1_set_affinity()
223 static int __init bcm7038_l1_init_one(struct device_node *dn, in bcm7038_l1_init_one()
224 unsigned int idx, in bcm7038_l1_init_one()
230 unsigned int i, n_words, parent_irq; in bcm7038_l1_init_one()
231 int ret; in bcm7038_l1_init_one()
234 return -EINVAL; in bcm7038_l1_init_one()
239 return -EINVAL; in bcm7038_l1_init_one()
240 else if (!intc->n_words) in bcm7038_l1_init_one()
241 intc->n_words = n_words; in bcm7038_l1_init_one()
242 else if (intc->n_words != n_words) in bcm7038_l1_init_one()
243 return -EINVAL; in bcm7038_l1_init_one()
245 ret = of_property_read_u32_array(dn , "brcm,int-fwd-mask", in bcm7038_l1_init_one()
246 intc->irq_fwd_mask, n_words); in bcm7038_l1_init_one()
247 if (ret != 0 && ret != -EINVAL) { in bcm7038_l1_init_one()
249 pr_err("invalid brcm,int-fwd-mask property\n"); in bcm7038_l1_init_one()
250 return -EINVAL; in bcm7038_l1_init_one()
253 cpu = intc->cpus[idx] = kzalloc(sizeof(*cpu) + n_words * sizeof(u32), in bcm7038_l1_init_one()
256 return -ENOMEM; in bcm7038_l1_init_one()
258 cpu->map_base = ioremap(res.start, sz); in bcm7038_l1_init_one()
259 if (!cpu->map_base) in bcm7038_l1_init_one()
260 return -ENOMEM; in bcm7038_l1_init_one()
263 l1_writel(~intc->irq_fwd_mask[i], in bcm7038_l1_init_one()
264 cpu->map_base + reg_mask_set(intc, i)); in bcm7038_l1_init_one()
265 l1_writel(intc->irq_fwd_mask[i], in bcm7038_l1_init_one()
266 cpu->map_base + reg_mask_clr(intc, i)); in bcm7038_l1_init_one()
267 cpu->mask_cache[i] = ~intc->irq_fwd_mask[i]; in bcm7038_l1_init_one()
273 return -EINVAL; in bcm7038_l1_init_one()
276 if (of_property_read_bool(dn, "brcm,irq-can-wake")) in bcm7038_l1_init_one()
296 static int bcm7038_l1_suspend(void) in bcm7038_l1_suspend()
299 int boot_cpu, word; in bcm7038_l1_suspend()
310 for (word = 0; word < intc->n_words; word++) { in bcm7038_l1_suspend()
311 val = intc->wake_mask[word] | intc->irq_fwd_mask[word]; in bcm7038_l1_suspend()
313 intc->cpus[boot_cpu]->map_base + reg_mask_set(intc, word)); in bcm7038_l1_suspend()
315 intc->cpus[boot_cpu]->map_base + reg_mask_clr(intc, word)); in bcm7038_l1_suspend()
325 int boot_cpu, word; in bcm7038_l1_resume()
334 for (word = 0; word < intc->n_words; word++) { in bcm7038_l1_resume()
335 l1_writel(intc->cpus[boot_cpu]->mask_cache[word], in bcm7038_l1_resume()
336 intc->cpus[boot_cpu]->map_base + reg_mask_set(intc, word)); in bcm7038_l1_resume()
337 l1_writel(~intc->cpus[boot_cpu]->mask_cache[word], in bcm7038_l1_resume()
338 intc->cpus[boot_cpu]->map_base + reg_mask_clr(intc, word)); in bcm7038_l1_resume()
348 static int bcm7038_l1_set_wake(struct irq_data *d, unsigned int on) in bcm7038_l1_set_wake()
352 u32 word = d->hwirq / IRQS_PER_WORD; in bcm7038_l1_set_wake()
353 u32 mask = BIT(d->hwirq % IRQS_PER_WORD); in bcm7038_l1_set_wake() local
355 raw_spin_lock_irqsave(&intc->lock, flags); in bcm7038_l1_set_wake()
357 intc->wake_mask[word] |= mask; in bcm7038_l1_set_wake()
359 intc->wake_mask[word] &= ~mask; in bcm7038_l1_set_wake()
360 raw_spin_unlock_irqrestore(&intc->lock, flags); in bcm7038_l1_set_wake()
367 .name = "bcm7038-l1",
378 static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq, in bcm7038_l1_map()
381 struct bcm7038_l1_chip *intc = d->host_data; in bcm7038_l1_map()
382 u32 mask = BIT(hw_irq % IRQS_PER_WORD); in bcm7038_l1_map() local
385 if (intc->irq_fwd_mask[word] & mask) in bcm7038_l1_map()
386 return -EPERM; in bcm7038_l1_map()
389 irq_set_chip_data(virq, d->host_data); in bcm7038_l1_map()
399 static int __init bcm7038_l1_of_init(struct device_node *dn, in bcm7038_l1_of_init()
403 int idx, ret; in bcm7038_l1_of_init()
407 return -ENOMEM; in bcm7038_l1_of_init()
409 raw_spin_lock_init(&intc->lock); in bcm7038_l1_of_init()
420 intc->domain = irq_domain_add_linear(dn, IRQS_PER_WORD * intc->n_words, in bcm7038_l1_of_init()
423 if (!intc->domain) { in bcm7038_l1_of_init()
424 ret = -ENOMEM; in bcm7038_l1_of_init()
431 list_add_tail(&intc->list, &bcm7038_l1_intcs_list); in bcm7038_l1_of_init()
439 dn, IRQS_PER_WORD * intc->n_words); in bcm7038_l1_of_init()
445 struct bcm7038_l1_cpu *cpu = intc->cpus[idx]; in bcm7038_l1_of_init()
448 if (cpu->map_base) in bcm7038_l1_of_init()
449 iounmap(cpu->map_base); in bcm7038_l1_of_init()
459 IRQCHIP_MATCH("brcm,bcm7038-l1-intc", bcm7038_l1_of_init)
461 MODULE_DESCRIPTION("Broadcom STB 7038-style L1/L2 interrupt controller");