0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/io.h>
0014 #include <linux/irq.h>
0015 #include <linux/irqchip.h>
0016 #include <linux/of.h>
0017 #include <linux/of_address.h>
0018 #include <linux/of_irq.h>
0019 #include <linux/mfd/syscon.h>
0020 #include <linux/regmap.h>
0021
0022 #include <asm/exception.h>
0023
0024 #define UC_IRQ_CONTROL 0x04
0025
0026 #define IC_FLAG_CLEAR_LO 0x00
0027 #define IC_FLAG_CLEAR_XLO 0x04
0028 #define IC_INT0ENABLE_LO 0x10
0029 #define IC_INT0ENABLE_XLO 0x14
0030 #define IC_INT0STATUS_LO 0x18
0031 #define IC_INT0STATUS_XLO 0x1c
0032
0033 static struct irq_domain *digicolor_irq_domain;
0034
0035 static void __exception_irq_entry digicolor_handle_irq(struct pt_regs *regs)
0036 {
0037 struct irq_domain_chip_generic *dgc = digicolor_irq_domain->gc;
0038 struct irq_chip_generic *gc = dgc->gc[0];
0039 u32 status, hwirq;
0040
0041 do {
0042 status = irq_reg_readl(gc, IC_INT0STATUS_LO);
0043 if (status) {
0044 hwirq = ffs(status) - 1;
0045 } else {
0046 status = irq_reg_readl(gc, IC_INT0STATUS_XLO);
0047 if (status)
0048 hwirq = ffs(status) - 1 + 32;
0049 else
0050 return;
0051 }
0052
0053 generic_handle_domain_irq(digicolor_irq_domain, hwirq);
0054 } while (1);
0055 }
0056
0057 static void __init digicolor_set_gc(void __iomem *reg_base, unsigned irq_base,
0058 unsigned en_reg, unsigned ack_reg)
0059 {
0060 struct irq_chip_generic *gc;
0061
0062 gc = irq_get_domain_generic_chip(digicolor_irq_domain, irq_base);
0063 gc->reg_base = reg_base;
0064 gc->chip_types[0].regs.ack = ack_reg;
0065 gc->chip_types[0].regs.mask = en_reg;
0066 gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
0067 gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
0068 gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
0069 }
0070
0071 static int __init digicolor_of_init(struct device_node *node,
0072 struct device_node *parent)
0073 {
0074 void __iomem *reg_base;
0075 unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
0076 struct regmap *ucregs;
0077 int ret;
0078
0079 reg_base = of_iomap(node, 0);
0080 if (!reg_base) {
0081 pr_err("%pOF: unable to map IC registers\n", node);
0082 return -ENXIO;
0083 }
0084
0085
0086 writel(0, reg_base + IC_INT0ENABLE_LO);
0087 writel(0, reg_base + IC_INT0ENABLE_XLO);
0088
0089 ucregs = syscon_regmap_lookup_by_phandle(node, "syscon");
0090 if (IS_ERR(ucregs)) {
0091 pr_err("%pOF: unable to map UC registers\n", node);
0092 return PTR_ERR(ucregs);
0093 }
0094
0095 regmap_write(ucregs, UC_IRQ_CONTROL, 1);
0096
0097 digicolor_irq_domain =
0098 irq_domain_add_linear(node, 64, &irq_generic_chip_ops, NULL);
0099 if (!digicolor_irq_domain) {
0100 pr_err("%pOF: unable to create IRQ domain\n", node);
0101 return -ENOMEM;
0102 }
0103
0104 ret = irq_alloc_domain_generic_chips(digicolor_irq_domain, 32, 1,
0105 "digicolor_irq", handle_level_irq,
0106 clr, 0, 0);
0107 if (ret) {
0108 pr_err("%pOF: unable to allocate IRQ gc\n", node);
0109 return ret;
0110 }
0111
0112 digicolor_set_gc(reg_base, 0, IC_INT0ENABLE_LO, IC_FLAG_CLEAR_LO);
0113 digicolor_set_gc(reg_base, 32, IC_INT0ENABLE_XLO, IC_FLAG_CLEAR_XLO);
0114
0115 set_handle_irq(digicolor_handle_irq);
0116
0117 return 0;
0118 }
0119 IRQCHIP_DECLARE(conexant_digicolor_ic, "cnxt,cx92755-ic", digicolor_of_init);