1*08dbd0f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22ac211bcSRichard Kuo /*
32ac211bcSRichard Kuo * First-level interrupt controller model for Hexagon.
42ac211bcSRichard Kuo *
5e1858b2aSRichard Kuo * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
62ac211bcSRichard Kuo */
72ac211bcSRichard Kuo
82ac211bcSRichard Kuo #include <linux/interrupt.h>
92ac211bcSRichard Kuo #include <asm/irq.h>
102ac211bcSRichard Kuo #include <asm/hexagon_vm.h>
112ac211bcSRichard Kuo
mask_irq(struct irq_data * data)122ac211bcSRichard Kuo static void mask_irq(struct irq_data *data)
132ac211bcSRichard Kuo {
142ac211bcSRichard Kuo __vmintop_locdis((long) data->irq);
152ac211bcSRichard Kuo }
162ac211bcSRichard Kuo
mask_irq_num(unsigned int irq)172ac211bcSRichard Kuo static void mask_irq_num(unsigned int irq)
182ac211bcSRichard Kuo {
192ac211bcSRichard Kuo __vmintop_locdis((long) irq);
202ac211bcSRichard Kuo }
212ac211bcSRichard Kuo
unmask_irq(struct irq_data * data)222ac211bcSRichard Kuo static void unmask_irq(struct irq_data *data)
232ac211bcSRichard Kuo {
242ac211bcSRichard Kuo __vmintop_locen((long) data->irq);
252ac211bcSRichard Kuo }
262ac211bcSRichard Kuo
272ac211bcSRichard Kuo /* This is actually all we need for handle_fasteoi_irq */
eoi_irq(struct irq_data * data)282ac211bcSRichard Kuo static void eoi_irq(struct irq_data *data)
292ac211bcSRichard Kuo {
302ac211bcSRichard Kuo __vmintop_globen((long) data->irq);
312ac211bcSRichard Kuo }
322ac211bcSRichard Kuo
332ac211bcSRichard Kuo /* Power mamangement wake call. We don't need this, however,
342ac211bcSRichard Kuo * if this is absent, then an -ENXIO error is returned to the
352ac211bcSRichard Kuo * msm_serial driver, and it fails to correctly initialize.
362ac211bcSRichard Kuo * This is a bug in the msm_serial driver, but, for now, we
372ac211bcSRichard Kuo * work around it here, by providing this bogus handler.
382ac211bcSRichard Kuo * XXX FIXME!!! remove this when msm_serial is fixed.
392ac211bcSRichard Kuo */
set_wake(struct irq_data * data,unsigned int on)402ac211bcSRichard Kuo static int set_wake(struct irq_data *data, unsigned int on)
412ac211bcSRichard Kuo {
422ac211bcSRichard Kuo return 0;
432ac211bcSRichard Kuo }
442ac211bcSRichard Kuo
452ac211bcSRichard Kuo static struct irq_chip hexagon_irq_chip = {
462ac211bcSRichard Kuo .name = "HEXAGON",
472ac211bcSRichard Kuo .irq_mask = mask_irq,
482ac211bcSRichard Kuo .irq_unmask = unmask_irq,
492ac211bcSRichard Kuo .irq_set_wake = set_wake,
502ac211bcSRichard Kuo .irq_eoi = eoi_irq
512ac211bcSRichard Kuo };
522ac211bcSRichard Kuo
532ac211bcSRichard Kuo /**
542ac211bcSRichard Kuo * The hexagon core comes with a first-level interrupt controller
552ac211bcSRichard Kuo * with 32 total possible interrupts. When the core is embedded
562ac211bcSRichard Kuo * into different systems/platforms, it is typically wrapped by
572ac211bcSRichard Kuo * macro cells that provide one or more second-level interrupt
582ac211bcSRichard Kuo * controllers that are cascaded into one or more of the first-level
592ac211bcSRichard Kuo * interrupts handled here. The precise wiring of these other
602ac211bcSRichard Kuo * irqs varies from platform to platform, and are set up & configured
612ac211bcSRichard Kuo * in the platform-specific files.
622ac211bcSRichard Kuo *
632ac211bcSRichard Kuo * The first-level interrupt controller is wrapped by the VM, which
642ac211bcSRichard Kuo * virtualizes the interrupt controller for us. It provides a very
652ac211bcSRichard Kuo * simple, fast & efficient API, and so the fasteoi handler is
662ac211bcSRichard Kuo * appropriate for this case.
672ac211bcSRichard Kuo */
init_IRQ(void)682ac211bcSRichard Kuo void __init init_IRQ(void)
692ac211bcSRichard Kuo {
702ac211bcSRichard Kuo int irq;
712ac211bcSRichard Kuo
722ac211bcSRichard Kuo for (irq = 0; irq < HEXAGON_CPUINTS; irq++) {
732ac211bcSRichard Kuo mask_irq_num(irq);
742ac211bcSRichard Kuo irq_set_chip_and_handler(irq, &hexagon_irq_chip,
752ac211bcSRichard Kuo handle_fasteoi_irq);
762ac211bcSRichard Kuo }
772ac211bcSRichard Kuo }
78