]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/mips/ralink/irq.c
KVM: PPC: emulate dcbst
[karo-tx-linux.git] / arch / mips / ralink / irq.c
1 /*
2  * This program is free software; you can redistribute it and/or modify it
3  * under the terms of the GNU General Public License version 2 as published
4  * by the Free Software Foundation.
5  *
6  * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
7  * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
8  */
9
10 #include <linux/io.h>
11 #include <linux/bitops.h>
12 #include <linux/of_platform.h>
13 #include <linux/of_address.h>
14 #include <linux/of_irq.h>
15 #include <linux/irqdomain.h>
16 #include <linux/interrupt.h>
17
18 #include <asm/irq_cpu.h>
19 #include <asm/mipsregs.h>
20
21 #include "common.h"
22
23 /* INTC register offsets */
24 #define INTC_REG_STATUS0        0x00
25 #define INTC_REG_STATUS1        0x04
26 #define INTC_REG_TYPE           0x20
27 #define INTC_REG_RAW_STATUS     0x30
28 #define INTC_REG_ENABLE         0x34
29 #define INTC_REG_DISABLE        0x38
30
31 #define INTC_INT_GLOBAL         BIT(31)
32
33 #define RALINK_CPU_IRQ_INTC     (MIPS_CPU_IRQ_BASE + 2)
34 #define RALINK_CPU_IRQ_FE       (MIPS_CPU_IRQ_BASE + 5)
35 #define RALINK_CPU_IRQ_WIFI     (MIPS_CPU_IRQ_BASE + 6)
36 #define RALINK_CPU_IRQ_COUNTER  (MIPS_CPU_IRQ_BASE + 7)
37
38 /* we have a cascade of 8 irqs */
39 #define RALINK_INTC_IRQ_BASE    8
40
41 /* we have 32 SoC irqs */
42 #define RALINK_INTC_IRQ_COUNT   32
43
44 #define RALINK_INTC_IRQ_PERFC   (RALINK_INTC_IRQ_BASE + 9)
45
46 static void __iomem *rt_intc_membase;
47
48 static inline void rt_intc_w32(u32 val, unsigned reg)
49 {
50         __raw_writel(val, rt_intc_membase + reg);
51 }
52
53 static inline u32 rt_intc_r32(unsigned reg)
54 {
55         return __raw_readl(rt_intc_membase + reg);
56 }
57
58 static void ralink_intc_irq_unmask(struct irq_data *d)
59 {
60         rt_intc_w32(BIT(d->hwirq), INTC_REG_ENABLE);
61 }
62
63 static void ralink_intc_irq_mask(struct irq_data *d)
64 {
65         rt_intc_w32(BIT(d->hwirq), INTC_REG_DISABLE);
66 }
67
68 static struct irq_chip ralink_intc_irq_chip = {
69         .name           = "INTC",
70         .irq_unmask     = ralink_intc_irq_unmask,
71         .irq_mask       = ralink_intc_irq_mask,
72         .irq_mask_ack   = ralink_intc_irq_mask,
73 };
74
75 unsigned int __cpuinit get_c0_compare_int(void)
76 {
77         return CP0_LEGACY_COMPARE_IRQ;
78 }
79
80 static void ralink_intc_irq_handler(unsigned int irq, struct irq_desc *desc)
81 {
82         u32 pending = rt_intc_r32(INTC_REG_STATUS0);
83
84         if (pending) {
85                 struct irq_domain *domain = irq_get_handler_data(irq);
86                 generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
87         } else {
88                 spurious_interrupt();
89         }
90 }
91
92 asmlinkage void plat_irq_dispatch(void)
93 {
94         unsigned long pending;
95
96         pending = read_c0_status() & read_c0_cause() & ST0_IM;
97
98         if (pending & STATUSF_IP7)
99                 do_IRQ(RALINK_CPU_IRQ_COUNTER);
100
101         else if (pending & STATUSF_IP5)
102                 do_IRQ(RALINK_CPU_IRQ_FE);
103
104         else if (pending & STATUSF_IP6)
105                 do_IRQ(RALINK_CPU_IRQ_WIFI);
106
107         else if (pending & STATUSF_IP2)
108                 do_IRQ(RALINK_CPU_IRQ_INTC);
109
110         else
111                 spurious_interrupt();
112 }
113
114 static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
115 {
116         irq_set_chip_and_handler(irq, &ralink_intc_irq_chip, handle_level_irq);
117
118         return 0;
119 }
120
121 static const struct irq_domain_ops irq_domain_ops = {
122         .xlate = irq_domain_xlate_onecell,
123         .map = intc_map,
124 };
125
126 static int __init intc_of_init(struct device_node *node,
127                                struct device_node *parent)
128 {
129         struct resource res;
130         struct irq_domain *domain;
131         int irq;
132
133         irq = irq_of_parse_and_map(node, 0);
134         if (!irq)
135                 panic("Failed to get INTC IRQ");
136
137         if (of_address_to_resource(node, 0, &res))
138                 panic("Failed to get intc memory range");
139
140         if (request_mem_region(res.start, resource_size(&res),
141                                 res.name) < 0)
142                 pr_err("Failed to request intc memory");
143
144         rt_intc_membase = ioremap_nocache(res.start,
145                                         resource_size(&res));
146         if (!rt_intc_membase)
147                 panic("Failed to remap intc memory");
148
149         /* disable all interrupts */
150         rt_intc_w32(~0, INTC_REG_DISABLE);
151
152         /* route all INTC interrupts to MIPS HW0 interrupt */
153         rt_intc_w32(0, INTC_REG_TYPE);
154
155         domain = irq_domain_add_legacy(node, RALINK_INTC_IRQ_COUNT,
156                         RALINK_INTC_IRQ_BASE, 0, &irq_domain_ops, NULL);
157         if (!domain)
158                 panic("Failed to add irqdomain");
159
160         rt_intc_w32(INTC_INT_GLOBAL, INTC_REG_ENABLE);
161
162         irq_set_chained_handler(irq, ralink_intc_irq_handler);
163         irq_set_handler_data(irq, domain);
164
165         cp0_perfcount_irq = irq_create_mapping(domain, 9);
166
167         return 0;
168 }
169
170 static struct of_device_id __initdata of_irq_ids[] = {
171         { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init },
172         { .compatible = "ralink,rt2880-intc", .data = intc_of_init },
173         {},
174 };
175
176 void __init arch_init_irq(void)
177 {
178         of_irq_init(of_irq_ids);
179 }
180