root/drivers/irqchip/irq-ls1x.c

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

DEFINITIONS

This source file includes following definitions.
  1. ls1x_chained_handle_irq
  2. ls_intc_set_bit
  3. ls_intc_set_type
  4. ls1x_intc_of_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  *  Copyright (C) 2019, Jiaxun Yang <jiaxun.yang@flygoat.com>
   4  *  Loongson-1 platform IRQ support
   5  */
   6 
   7 #include <linux/errno.h>
   8 #include <linux/init.h>
   9 #include <linux/types.h>
  10 #include <linux/interrupt.h>
  11 #include <linux/ioport.h>
  12 #include <linux/irqchip.h>
  13 #include <linux/of_address.h>
  14 #include <linux/of_irq.h>
  15 #include <linux/io.h>
  16 #include <linux/irqchip/chained_irq.h>
  17 
  18 #define LS_REG_INTC_STATUS      0x00
  19 #define LS_REG_INTC_EN  0x04
  20 #define LS_REG_INTC_SET 0x08
  21 #define LS_REG_INTC_CLR 0x0c
  22 #define LS_REG_INTC_POL 0x10
  23 #define LS_REG_INTC_EDGE        0x14
  24 
  25 /**
  26  * struct ls1x_intc_priv - private ls1x-intc data.
  27  * @domain:             IRQ domain.
  28  * @intc_base:  IO Base of intc registers.
  29  */
  30 
  31 struct ls1x_intc_priv {
  32         struct irq_domain       *domain;
  33         void __iomem            *intc_base;
  34 };
  35 
  36 
  37 static void ls1x_chained_handle_irq(struct irq_desc *desc)
  38 {
  39         struct ls1x_intc_priv *priv = irq_desc_get_handler_data(desc);
  40         struct irq_chip *chip = irq_desc_get_chip(desc);
  41         u32 pending;
  42 
  43         chained_irq_enter(chip, desc);
  44         pending = readl(priv->intc_base + LS_REG_INTC_STATUS) &
  45                         readl(priv->intc_base + LS_REG_INTC_EN);
  46 
  47         if (!pending)
  48                 spurious_interrupt();
  49 
  50         while (pending) {
  51                 int bit = __ffs(pending);
  52 
  53                 generic_handle_irq(irq_find_mapping(priv->domain, bit));
  54                 pending &= ~BIT(bit);
  55         }
  56 
  57         chained_irq_exit(chip, desc);
  58 }
  59 
  60 static void ls_intc_set_bit(struct irq_chip_generic *gc,
  61                                                         unsigned int offset,
  62                                                         u32 mask, bool set)
  63 {
  64         if (set)
  65                 writel(readl(gc->reg_base + offset) | mask,
  66                 gc->reg_base + offset);
  67         else
  68                 writel(readl(gc->reg_base + offset) & ~mask,
  69                 gc->reg_base + offset);
  70 }
  71 
  72 static int ls_intc_set_type(struct irq_data *data, unsigned int type)
  73 {
  74         struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
  75         u32 mask = data->mask;
  76 
  77         switch (type) {
  78         case IRQ_TYPE_LEVEL_HIGH:
  79                 ls_intc_set_bit(gc, LS_REG_INTC_EDGE, mask, false);
  80                 ls_intc_set_bit(gc, LS_REG_INTC_POL, mask, true);
  81                 break;
  82         case IRQ_TYPE_LEVEL_LOW:
  83                 ls_intc_set_bit(gc, LS_REG_INTC_EDGE, mask, false);
  84                 ls_intc_set_bit(gc, LS_REG_INTC_POL, mask, false);
  85                 break;
  86         case IRQ_TYPE_EDGE_RISING:
  87                 ls_intc_set_bit(gc, LS_REG_INTC_EDGE, mask, true);
  88                 ls_intc_set_bit(gc, LS_REG_INTC_POL, mask, true);
  89                 break;
  90         case IRQ_TYPE_EDGE_FALLING:
  91                 ls_intc_set_bit(gc, LS_REG_INTC_EDGE, mask, true);
  92                 ls_intc_set_bit(gc, LS_REG_INTC_POL, mask, false);
  93                 break;
  94         default:
  95                 return -EINVAL;
  96         }
  97 
  98         irqd_set_trigger_type(data, type);
  99         return irq_setup_alt_chip(data, type);
 100 }
 101 
 102 
 103 static int __init ls1x_intc_of_init(struct device_node *node,
 104                                        struct device_node *parent)
 105 {
 106         struct irq_chip_generic *gc;
 107         struct irq_chip_type *ct;
 108         struct ls1x_intc_priv *priv;
 109         int parent_irq, err = 0;
 110 
 111         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 112         if (!priv)
 113                 return -ENOMEM;
 114 
 115         priv->intc_base = of_iomap(node, 0);
 116         if (!priv->intc_base) {
 117                 err = -ENODEV;
 118                 goto out_free_priv;
 119         }
 120 
 121         parent_irq = irq_of_parse_and_map(node, 0);
 122         if (!parent_irq) {
 123                 pr_err("ls1x-irq: unable to get parent irq\n");
 124                 err =  -ENODEV;
 125                 goto out_iounmap;
 126         }
 127 
 128         /* Set up an IRQ domain */
 129         priv->domain = irq_domain_add_linear(node, 32, &irq_generic_chip_ops,
 130                                              NULL);
 131         if (!priv->domain) {
 132                 pr_err("ls1x-irq: cannot add IRQ domain\n");
 133                 err = -ENOMEM;
 134                 goto out_iounmap;
 135         }
 136 
 137         err = irq_alloc_domain_generic_chips(priv->domain, 32, 2,
 138                 node->full_name, handle_level_irq,
 139                 IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN, 0,
 140                 IRQ_GC_INIT_MASK_CACHE);
 141         if (err) {
 142                 pr_err("ls1x-irq: unable to register IRQ domain\n");
 143                 goto out_free_domain;
 144         }
 145 
 146         /* Mask all irqs */
 147         writel(0x0, priv->intc_base + LS_REG_INTC_EN);
 148 
 149         /* Ack all irqs */
 150         writel(0xffffffff, priv->intc_base + LS_REG_INTC_CLR);
 151 
 152         /* Set all irqs to high level triggered */
 153         writel(0xffffffff, priv->intc_base + LS_REG_INTC_POL);
 154 
 155         gc = irq_get_domain_generic_chip(priv->domain, 0);
 156 
 157         gc->reg_base = priv->intc_base;
 158 
 159         ct = gc->chip_types;
 160         ct[0].type = IRQ_TYPE_LEVEL_MASK;
 161         ct[0].regs.mask = LS_REG_INTC_EN;
 162         ct[0].regs.ack = LS_REG_INTC_CLR;
 163         ct[0].chip.irq_unmask = irq_gc_mask_set_bit;
 164         ct[0].chip.irq_mask = irq_gc_mask_clr_bit;
 165         ct[0].chip.irq_ack = irq_gc_ack_set_bit;
 166         ct[0].chip.irq_set_type = ls_intc_set_type;
 167         ct[0].handler = handle_level_irq;
 168 
 169         ct[1].type = IRQ_TYPE_EDGE_BOTH;
 170         ct[1].regs.mask = LS_REG_INTC_EN;
 171         ct[1].regs.ack = LS_REG_INTC_CLR;
 172         ct[1].chip.irq_unmask = irq_gc_mask_set_bit;
 173         ct[1].chip.irq_mask = irq_gc_mask_clr_bit;
 174         ct[1].chip.irq_ack = irq_gc_ack_set_bit;
 175         ct[1].chip.irq_set_type = ls_intc_set_type;
 176         ct[1].handler = handle_edge_irq;
 177 
 178         irq_set_chained_handler_and_data(parent_irq,
 179                 ls1x_chained_handle_irq, priv);
 180 
 181         return 0;
 182 
 183 out_free_domain:
 184         irq_domain_remove(priv->domain);
 185 out_iounmap:
 186         iounmap(priv->intc_base);
 187 out_free_priv:
 188         kfree(priv);
 189 
 190         return err;
 191 }
 192 
 193 IRQCHIP_DECLARE(ls1x_intc, "loongson,ls1x-intc", ls1x_intc_of_init);

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