Blame view
drivers/irqchip/irq-ingenic.c
4.53 KB
9869848d1 MIPS: JZ4740: Add... |
1 2 3 4 5 |
/* * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> * JZ4740 platform IRQ support * * This program is free software; you can redistribute it and/or modify it |
703422879 MIPS: Whitespace ... |
6 |
* under the terms of the GNU General Public License as published by the |
9869848d1 MIPS: JZ4740: Add... |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
* Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include <linux/errno.h> #include <linux/init.h> #include <linux/types.h> #include <linux/interrupt.h> #include <linux/ioport.h> |
41a83e06e irqchip: Prepare ... |
21 |
#include <linux/irqchip.h> |
44e08e709 MIPS/IRQCHIP: Mov... |
22 |
#include <linux/irqchip/ingenic.h> |
3aa94590e MIPS: JZ4740: rea... |
23 |
#include <linux/of_address.h> |
adbdce77c MIPS: JZ4740: pro... |
24 |
#include <linux/of_irq.h> |
9869848d1 MIPS: JZ4740: Add... |
25 26 27 |
#include <linux/timex.h> #include <linux/slab.h> #include <linux/delay.h> |
9869848d1 MIPS: JZ4740: Add... |
28 |
#include <asm/io.h> |
942e22dff MIPS: JZ4740: Fix... |
29 |
#include <asm/mach-jz4740/irq.h> |
fe778ece8 MIPS: JZ4740: Rem... |
30 31 |
struct ingenic_intc_data { void __iomem *base; |
943d69c6c MIPS: JZ4740: sup... |
32 |
unsigned num_chips; |
fe778ece8 MIPS: JZ4740: Rem... |
33 |
}; |
9869848d1 MIPS: JZ4740: Add... |
34 35 36 37 38 39 |
#define JZ_REG_INTC_STATUS 0x00 #define JZ_REG_INTC_MASK 0x04 #define JZ_REG_INTC_SET_MASK 0x08 #define JZ_REG_INTC_CLEAR_MASK 0x0c #define JZ_REG_INTC_PENDING 0x10 |
943d69c6c MIPS: JZ4740: sup... |
40 |
#define CHIP_SIZE 0x20 |
9869848d1 MIPS: JZ4740: Add... |
41 |
|
2da018849 MIPS: JZ4740: Avo... |
42 |
static irqreturn_t intc_cascade(int irq, void *data) |
9869848d1 MIPS: JZ4740: Add... |
43 |
{ |
fe778ece8 MIPS: JZ4740: Rem... |
44 |
struct ingenic_intc_data *intc = irq_get_handler_data(irq); |
83bc76920 MIPS: JZ4740: Use... |
45 |
uint32_t irq_reg; |
943d69c6c MIPS: JZ4740: sup... |
46 |
unsigned i; |
9869848d1 MIPS: JZ4740: Add... |
47 |
|
943d69c6c MIPS: JZ4740: sup... |
48 49 50 51 52 |
for (i = 0; i < intc->num_chips; i++) { irq_reg = readl(intc->base + (i * CHIP_SIZE) + JZ_REG_INTC_PENDING); if (!irq_reg) continue; |
9869848d1 MIPS: JZ4740: Add... |
53 |
|
943d69c6c MIPS: JZ4740: sup... |
54 55 |
generic_handle_irq(__fls(irq_reg) + (i * 32) + JZ4740_IRQ_BASE); } |
83bc76920 MIPS: JZ4740: Use... |
56 57 |
return IRQ_HANDLED; |
42b64f388 MIPS: JZ4740: Con... |
58 |
} |
2da018849 MIPS: JZ4740: Avo... |
59 |
static void intc_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask) |
9869848d1 MIPS: JZ4740: Add... |
60 |
{ |
83bc76920 MIPS: JZ4740: Use... |
61 |
struct irq_chip_regs *regs = &gc->chip_types->regs; |
9869848d1 MIPS: JZ4740: Add... |
62 |
|
83bc76920 MIPS: JZ4740: Use... |
63 64 |
writel(mask, gc->reg_base + regs->enable); writel(~mask, gc->reg_base + regs->disable); |
9869848d1 MIPS: JZ4740: Add... |
65 |
} |
2da018849 MIPS: JZ4740: Avo... |
66 |
void ingenic_intc_irq_suspend(struct irq_data *data) |
9869848d1 MIPS: JZ4740: Add... |
67 |
{ |
83bc76920 MIPS: JZ4740: Use... |
68 |
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); |
2da018849 MIPS: JZ4740: Avo... |
69 |
intc_irq_set_mask(gc, gc->wake_active); |
83bc76920 MIPS: JZ4740: Use... |
70 |
} |
9869848d1 MIPS: JZ4740: Add... |
71 |
|
2da018849 MIPS: JZ4740: Avo... |
72 |
void ingenic_intc_irq_resume(struct irq_data *data) |
83bc76920 MIPS: JZ4740: Use... |
73 74 |
{ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); |
2da018849 MIPS: JZ4740: Avo... |
75 |
intc_irq_set_mask(gc, gc->mask_cache); |
9869848d1 MIPS: JZ4740: Add... |
76 |
} |
2da018849 MIPS: JZ4740: Avo... |
77 78 79 |
static struct irqaction intc_cascade_action = { .handler = intc_cascade, .name = "SoC intc cascade interrupt", |
9869848d1 MIPS: JZ4740: Add... |
80 |
}; |
943d69c6c MIPS: JZ4740: sup... |
81 82 |
static int __init ingenic_intc_of_init(struct device_node *node, unsigned num_chips) |
9869848d1 MIPS: JZ4740: Add... |
83 |
{ |
fe778ece8 MIPS: JZ4740: Rem... |
84 |
struct ingenic_intc_data *intc; |
83bc76920 MIPS: JZ4740: Use... |
85 86 |
struct irq_chip_generic *gc; struct irq_chip_type *ct; |
638c88518 MIPS: JZ4740: reg... |
87 |
struct irq_domain *domain; |
fe778ece8 MIPS: JZ4740: Rem... |
88 |
int parent_irq, err = 0; |
943d69c6c MIPS: JZ4740: sup... |
89 |
unsigned i; |
fe778ece8 MIPS: JZ4740: Rem... |
90 91 92 93 94 95 |
intc = kzalloc(sizeof(*intc), GFP_KERNEL); if (!intc) { err = -ENOMEM; goto out_err; } |
69ce4b228 MIPS: JZ4740: par... |
96 97 |
parent_irq = irq_of_parse_and_map(node, 0); |
fe778ece8 MIPS: JZ4740: Rem... |
98 99 100 101 |
if (!parent_irq) { err = -EINVAL; goto out_free; } |
83bc76920 MIPS: JZ4740: Use... |
102 |
|
fe778ece8 MIPS: JZ4740: Rem... |
103 104 105 |
err = irq_set_handler_data(parent_irq, intc); if (err) goto out_unmap_irq; |
943d69c6c MIPS: JZ4740: sup... |
106 |
intc->num_chips = num_chips; |
3aa94590e MIPS: JZ4740: rea... |
107 108 109 110 111 |
intc->base = of_iomap(node, 0); if (!intc->base) { err = -ENODEV; goto out_unmap_irq; } |
9869848d1 MIPS: JZ4740: Add... |
112 |
|
943d69c6c MIPS: JZ4740: sup... |
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
for (i = 0; i < num_chips; i++) { /* Mask all irqs */ writel(0xffffffff, intc->base + (i * CHIP_SIZE) + JZ_REG_INTC_SET_MASK); gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE + (i * 32), intc->base + (i * CHIP_SIZE), handle_level_irq); gc->wake_enabled = IRQ_MSK(32); ct = gc->chip_types; ct->regs.enable = JZ_REG_INTC_CLEAR_MASK; ct->regs.disable = JZ_REG_INTC_SET_MASK; ct->chip.irq_unmask = irq_gc_unmask_enable_reg; ct->chip.irq_mask = irq_gc_mask_disable_reg; ct->chip.irq_mask_ack = irq_gc_mask_disable_reg; ct->chip.irq_set_wake = irq_gc_set_wake; |
2da018849 MIPS: JZ4740: Avo... |
132 133 |
ct->chip.irq_suspend = ingenic_intc_irq_suspend; ct->chip.irq_resume = ingenic_intc_irq_resume; |
943d69c6c MIPS: JZ4740: sup... |
134 135 136 137 |
irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL); } |
9869848d1 MIPS: JZ4740: Add... |
138 |
|
638c88518 MIPS: JZ4740: reg... |
139 140 141 142 143 |
domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0, &irq_domain_simple_ops, NULL); if (!domain) pr_warn("unable to register IRQ domain "); |
2da018849 MIPS: JZ4740: Avo... |
144 |
setup_irq(parent_irq, &intc_cascade_action); |
adbdce77c MIPS: JZ4740: pro... |
145 |
return 0; |
fe778ece8 MIPS: JZ4740: Rem... |
146 147 148 149 150 151 152 |
out_unmap_irq: irq_dispose_mapping(parent_irq); out_free: kfree(intc); out_err: return err; |
9869848d1 MIPS: JZ4740: Add... |
153 |
} |
943d69c6c MIPS: JZ4740: sup... |
154 155 156 157 158 159 160 |
static int __init intc_1chip_of_init(struct device_node *node, struct device_node *parent) { return ingenic_intc_of_init(node, 1); } IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", intc_1chip_of_init); |
24ccfa06b MIPS: JZ4740: sup... |
161 162 163 164 165 166 167 168 169 |
static int __init intc_2chip_of_init(struct device_node *node, struct device_node *parent) { return ingenic_intc_of_init(node, 2); } IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init); IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init); IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init); |