root/drivers/irqchip/irq-digicolor.c

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

DEFINITIONS

This source file includes following definitions.
  1. digicolor_handle_irq
  2. digicolor_set_gc
  3. digicolor_of_init

   1 /*
   2  * Conexant Digicolor SoCs IRQ chip driver
   3  *
   4  * Author: Baruch Siach <baruch@tkos.co.il>
   5  *
   6  * Copyright (C) 2014 Paradox Innovation Ltd.
   7  *
   8  * This file is licensed under the terms of the GNU General Public
   9  * License version 2.  This program is licensed "as is" without any
  10  * warranty of any kind, whether express or implied.
  11  */
  12 
  13 #include <linux/io.h>
  14 #include <linux/irq.h>
  15 #include <linux/irqchip.h>
  16 #include <linux/of.h>
  17 #include <linux/of_address.h>
  18 #include <linux/of_irq.h>
  19 #include <linux/mfd/syscon.h>
  20 #include <linux/regmap.h>
  21 
  22 #include <asm/exception.h>
  23 
  24 #define UC_IRQ_CONTROL          0x04
  25 
  26 #define IC_FLAG_CLEAR_LO        0x00
  27 #define IC_FLAG_CLEAR_XLO       0x04
  28 #define IC_INT0ENABLE_LO        0x10
  29 #define IC_INT0ENABLE_XLO       0x14
  30 #define IC_INT0STATUS_LO        0x18
  31 #define IC_INT0STATUS_XLO       0x1c
  32 
  33 static struct irq_domain *digicolor_irq_domain;
  34 
  35 static void __exception_irq_entry digicolor_handle_irq(struct pt_regs *regs)
  36 {
  37         struct irq_domain_chip_generic *dgc = digicolor_irq_domain->gc;
  38         struct irq_chip_generic *gc = dgc->gc[0];
  39         u32 status, hwirq;
  40 
  41         do {
  42                 status = irq_reg_readl(gc, IC_INT0STATUS_LO);
  43                 if (status) {
  44                         hwirq = ffs(status) - 1;
  45                 } else {
  46                         status = irq_reg_readl(gc, IC_INT0STATUS_XLO);
  47                         if (status)
  48                                 hwirq = ffs(status) - 1 + 32;
  49                         else
  50                                 return;
  51                 }
  52 
  53                 handle_domain_irq(digicolor_irq_domain, hwirq, regs);
  54         } while (1);
  55 }
  56 
  57 static void __init digicolor_set_gc(void __iomem *reg_base, unsigned irq_base,
  58                                     unsigned en_reg, unsigned ack_reg)
  59 {
  60         struct irq_chip_generic *gc;
  61 
  62         gc = irq_get_domain_generic_chip(digicolor_irq_domain, irq_base);
  63         gc->reg_base = reg_base;
  64         gc->chip_types[0].regs.ack = ack_reg;
  65         gc->chip_types[0].regs.mask = en_reg;
  66         gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
  67         gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
  68         gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
  69 }
  70 
  71 static int __init digicolor_of_init(struct device_node *node,
  72                                 struct device_node *parent)
  73 {
  74         void __iomem *reg_base;
  75         unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
  76         struct regmap *ucregs;
  77         int ret;
  78 
  79         reg_base = of_iomap(node, 0);
  80         if (!reg_base) {
  81                 pr_err("%pOF: unable to map IC registers\n", node);
  82                 return -ENXIO;
  83         }
  84 
  85         /* disable all interrupts */
  86         writel(0, reg_base + IC_INT0ENABLE_LO);
  87         writel(0, reg_base + IC_INT0ENABLE_XLO);
  88 
  89         ucregs = syscon_regmap_lookup_by_phandle(node, "syscon");
  90         if (IS_ERR(ucregs)) {
  91                 pr_err("%pOF: unable to map UC registers\n", node);
  92                 return PTR_ERR(ucregs);
  93         }
  94         /* channel 1, regular IRQs */
  95         regmap_write(ucregs, UC_IRQ_CONTROL, 1);
  96 
  97         digicolor_irq_domain =
  98                 irq_domain_add_linear(node, 64, &irq_generic_chip_ops, NULL);
  99         if (!digicolor_irq_domain) {
 100                 pr_err("%pOF: unable to create IRQ domain\n", node);
 101                 return -ENOMEM;
 102         }
 103 
 104         ret = irq_alloc_domain_generic_chips(digicolor_irq_domain, 32, 1,
 105                                              "digicolor_irq", handle_level_irq,
 106                                              clr, 0, 0);
 107         if (ret) {
 108                 pr_err("%pOF: unable to allocate IRQ gc\n", node);
 109                 return ret;
 110         }
 111 
 112         digicolor_set_gc(reg_base, 0, IC_INT0ENABLE_LO, IC_FLAG_CLEAR_LO);
 113         digicolor_set_gc(reg_base, 32, IC_INT0ENABLE_XLO, IC_FLAG_CLEAR_XLO);
 114 
 115         set_handle_irq(digicolor_handle_irq);
 116 
 117         return 0;
 118 }
 119 IRQCHIP_DECLARE(conexant_digicolor_ic, "cnxt,cx92755-ic", digicolor_of_init);

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