root/drivers/irqchip/irq-jcore-aic.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. handle_jcore_irq
  2. jcore_aic_irqdomain_map
  3. noop
  4. aic_irq_of_init

   1 /*
   2  * J-Core SoC AIC driver
   3  *
   4  * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
   5  *
   6  * This file is subject to the terms and conditions of the GNU General Public
   7  * License.  See the file "COPYING" in the main directory of this archive
   8  * for more details.
   9  */
  10 
  11 #include <linux/irq.h>
  12 #include <linux/io.h>
  13 #include <linux/irqchip.h>
  14 #include <linux/irqdomain.h>
  15 #include <linux/cpu.h>
  16 #include <linux/of.h>
  17 #include <linux/of_address.h>
  18 #include <linux/of_irq.h>
  19 
  20 #define JCORE_AIC_MAX_HWIRQ     127
  21 #define JCORE_AIC1_MIN_HWIRQ    16
  22 #define JCORE_AIC2_MIN_HWIRQ    64
  23 
  24 #define JCORE_AIC1_INTPRI_REG   8
  25 
  26 static struct irq_chip jcore_aic;
  27 
  28 /*
  29  * The J-Core AIC1 and AIC2 are cpu-local interrupt controllers and do
  30  * not distinguish or use distinct irq number ranges for per-cpu event
  31  * interrupts (timer, IPI). Since information to determine whether a
  32  * particular irq number should be treated as per-cpu is not available
  33  * at mapping time, we use a wrapper handler function which chooses
  34  * the right handler at runtime based on whether IRQF_PERCPU was used
  35  * when requesting the irq.
  36  */
  37 
  38 static void handle_jcore_irq(struct irq_desc *desc)
  39 {
  40         if (irqd_is_per_cpu(irq_desc_get_irq_data(desc)))
  41                 handle_percpu_irq(desc);
  42         else
  43                 handle_simple_irq(desc);
  44 }
  45 
  46 static int jcore_aic_irqdomain_map(struct irq_domain *d, unsigned int irq,
  47                                    irq_hw_number_t hwirq)
  48 {
  49         struct irq_chip *aic = d->host_data;
  50 
  51         irq_set_chip_and_handler(irq, aic, handle_jcore_irq);
  52 
  53         return 0;
  54 }
  55 
  56 static const struct irq_domain_ops jcore_aic_irqdomain_ops = {
  57         .map = jcore_aic_irqdomain_map,
  58         .xlate = irq_domain_xlate_onecell,
  59 };
  60 
  61 static void noop(struct irq_data *data)
  62 {
  63 }
  64 
  65 static int __init aic_irq_of_init(struct device_node *node,
  66                                   struct device_node *parent)
  67 {
  68         unsigned min_irq = JCORE_AIC2_MIN_HWIRQ;
  69         unsigned dom_sz = JCORE_AIC_MAX_HWIRQ+1;
  70         struct irq_domain *domain;
  71 
  72         pr_info("Initializing J-Core AIC\n");
  73 
  74         /* AIC1 needs priority initialization to receive interrupts. */
  75         if (of_device_is_compatible(node, "jcore,aic1")) {
  76                 unsigned cpu;
  77 
  78                 for_each_present_cpu(cpu) {
  79                         void __iomem *base = of_iomap(node, cpu);
  80 
  81                         if (!base) {
  82                                 pr_err("Unable to map AIC for cpu %u\n", cpu);
  83                                 return -ENOMEM;
  84                         }
  85                         __raw_writel(0xffffffff, base + JCORE_AIC1_INTPRI_REG);
  86                         iounmap(base);
  87                 }
  88                 min_irq = JCORE_AIC1_MIN_HWIRQ;
  89         }
  90 
  91         /*
  92          * The irq chip framework requires either mask/unmask or enable/disable
  93          * function pointers to be provided, but the hardware does not have any
  94          * such mechanism; the only interrupt masking is at the cpu level and
  95          * it affects all interrupts. We provide dummy mask/unmask. The hardware
  96          * handles all interrupt control and clears pending status when the cpu
  97          * accepts the interrupt.
  98          */
  99         jcore_aic.irq_mask = noop;
 100         jcore_aic.irq_unmask = noop;
 101         jcore_aic.name = "AIC";
 102 
 103         domain = irq_domain_add_linear(node, dom_sz, &jcore_aic_irqdomain_ops,
 104                                        &jcore_aic);
 105         if (!domain)
 106                 return -ENOMEM;
 107         irq_create_strict_mappings(domain, min_irq, min_irq, dom_sz - min_irq);
 108 
 109         return 0;
 110 }
 111 
 112 IRQCHIP_DECLARE(jcore_aic2, "jcore,aic2", aic_irq_of_init);
 113 IRQCHIP_DECLARE(jcore_aic1, "jcore,aic1", aic_irq_of_init);

/* [<][>][^][v][top][bottom][index][help] */