OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * Moschip MCS814x generic interrupt controller routines |
||
3 | * |
||
4 | * Copyright (C) 2012, Florian Fainelli <florian@openwrt.org> |
||
5 | * |
||
6 | * Licensed under the GPLv2 |
||
7 | */ |
||
8 | #include <linux/init.h> |
||
9 | #include <linux/irq.h> |
||
10 | #include <linux/io.h> |
||
11 | #include <linux/of.h> |
||
12 | #include <linux/of_address.h> |
||
13 | #include <linux/irqdomain.h> |
||
14 | |||
15 | #include <asm/exception.h> |
||
16 | #include <asm/mach/irq.h> |
||
17 | #include <mach/mcs814x.h> |
||
18 | |||
19 | static void __iomem *mcs814x_intc_base; |
||
20 | static struct irq_domain *domain; |
||
21 | |||
22 | static void __init mcs814x_alloc_gc(void __iomem *base, unsigned int irq_start, |
||
23 | unsigned int num) |
||
24 | { |
||
25 | struct irq_chip_generic *gc; |
||
26 | struct irq_chip_type *ct; |
||
27 | |||
28 | if (irq_alloc_domain_generic_chips(domain, num, 1, "mcs814x-intc", handle_level_irq, |
||
29 | IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0)) |
||
30 | panic("unable to allocate domain generic irq chip"); |
||
31 | |||
32 | gc = irq_get_domain_generic_chip(domain, irq_start); |
||
33 | if (!gc) |
||
34 | panic("unable to get generic irq chip"); |
||
35 | |||
36 | gc->reg_base = base; |
||
37 | ct = gc->chip_types; |
||
38 | ct->chip.irq_ack = irq_gc_unmask_enable_reg; |
||
39 | ct->chip.irq_mask = irq_gc_mask_clr_bit; |
||
40 | ct->chip.irq_unmask = irq_gc_mask_set_bit; |
||
41 | ct->regs.mask = MCS814X_IRQ_MASK; |
||
42 | ct->regs.enable = MCS814X_IRQ_ICR; |
||
43 | |||
44 | /* Clear all interrupts */ |
||
45 | writel_relaxed(0xffffffff, base + MCS814X_IRQ_ICR); |
||
46 | } |
||
47 | |||
48 | asmlinkage void __exception_irq_entry mcs814x_handle_irq(struct pt_regs *regs) |
||
49 | { |
||
50 | u32 status, irq; |
||
51 | |||
52 | do { |
||
53 | /* read the status register */ |
||
54 | status = __raw_readl(mcs814x_intc_base + MCS814X_IRQ_STS0); |
||
55 | if (!status) |
||
56 | break; |
||
57 | |||
58 | irq = ffs(status) - 1; |
||
59 | status |= (1 << irq); |
||
60 | /* clear the interrupt */ |
||
61 | __raw_writel(status, mcs814x_intc_base + MCS814X_IRQ_STS0); |
||
62 | /* call the generic handler */ |
||
63 | handle_domain_irq(domain, irq, regs); |
||
64 | |||
65 | } while (1); |
||
66 | } |
||
67 | |||
68 | static const struct of_device_id mcs814x_intc_ids[] = { |
||
69 | { .compatible = "moschip,mcs814x-intc" }, |
||
70 | { /* sentinel */ }, |
||
71 | }; |
||
72 | |||
73 | void __init mcs814x_of_irq_init(void) |
||
74 | { |
||
75 | struct device_node *np; |
||
76 | |||
77 | np = of_find_matching_node(NULL, mcs814x_intc_ids); |
||
78 | if (!np) |
||
79 | panic("unable to find compatible intc node in dtb\n"); |
||
80 | |||
81 | mcs814x_intc_base = of_iomap(np, 0); |
||
82 | if (!mcs814x_intc_base) |
||
83 | panic("unable to map intc cpu registers\n"); |
||
84 | |||
85 | domain = irq_domain_add_linear(np, 32, &irq_generic_chip_ops, NULL); |
||
86 | if (!domain) |
||
87 | panic("unable to add irq domain\n"); |
||
88 | irq_set_default_host(domain); |
||
89 | |||
90 | of_node_put(np); |
||
91 | |||
92 | mcs814x_alloc_gc(mcs814x_intc_base, 0, 32); |
||
93 | } |
||
94 |