Merge tag 'sunxi-fixes-for-4.3' of https://git.kernel.org/pub/scm/linux/kernel/git...
[linux-drm-fsl-dcu.git] / drivers / irqchip / irq-metag.c
1 /*
2  * Meta internal (HWSTATMETA) interrupt code.
3  *
4  * Copyright (C) 2011-2012 Imagination Technologies Ltd.
5  *
6  * This code is based on the code in SoC/common/irq.c and SoC/comet/irq.c
7  * The code base could be generalised/merged as a lot of the functionality is
8  * similar. Until this is done, we try to keep the code simple here.
9  */
10
11 #include <linux/interrupt.h>
12 #include <linux/io.h>
13 #include <linux/irqdomain.h>
14
15 #include <asm/irq.h>
16 #include <asm/hwthread.h>
17
18 #define PERF0VECINT             0x04820580
19 #define PERF1VECINT             0x04820588
20 #define PERF0TRIG_OFFSET        16
21 #define PERF1TRIG_OFFSET        17
22
23 /**
24  * struct metag_internal_irq_priv - private meta internal interrupt data
25  * @domain:             IRQ domain for all internal Meta IRQs (HWSTATMETA)
26  * @unmasked:           Record of unmasked IRQs
27  */
28 struct metag_internal_irq_priv {
29         struct irq_domain       *domain;
30
31         unsigned long           unmasked;
32 };
33
34 /* Private data for the one and only internal interrupt controller */
35 static struct metag_internal_irq_priv metag_internal_irq_priv;
36
37 static unsigned int metag_internal_irq_startup(struct irq_data *data);
38 static void metag_internal_irq_shutdown(struct irq_data *data);
39 static void metag_internal_irq_ack(struct irq_data *data);
40 static void metag_internal_irq_mask(struct irq_data *data);
41 static void metag_internal_irq_unmask(struct irq_data *data);
42 #ifdef CONFIG_SMP
43 static int metag_internal_irq_set_affinity(struct irq_data *data,
44                         const struct cpumask *cpumask, bool force);
45 #endif
46
47 static struct irq_chip internal_irq_edge_chip = {
48         .name = "HWSTATMETA-IRQ",
49         .irq_startup = metag_internal_irq_startup,
50         .irq_shutdown = metag_internal_irq_shutdown,
51         .irq_ack = metag_internal_irq_ack,
52         .irq_mask = metag_internal_irq_mask,
53         .irq_unmask = metag_internal_irq_unmask,
54 #ifdef CONFIG_SMP
55         .irq_set_affinity = metag_internal_irq_set_affinity,
56 #endif
57 };
58
59 /*
60  *      metag_hwvec_addr - get the address of *VECINT regs of irq
61  *
62  *      This function is a table of supported triggers on HWSTATMETA
63  *      Could do with a structure, but better keep it simple. Changes
64  *      in this code should be rare.
65  */
66 static inline void __iomem *metag_hwvec_addr(irq_hw_number_t hw)
67 {
68         void __iomem *addr;
69
70         switch (hw) {
71         case PERF0TRIG_OFFSET:
72                 addr = (void __iomem *)PERF0VECINT;
73                 break;
74         case PERF1TRIG_OFFSET:
75                 addr = (void __iomem *)PERF1VECINT;
76                 break;
77         default:
78                 addr = NULL;
79                 break;
80         }
81         return addr;
82 }
83
84 /*
85  *      metag_internal_startup - setup an internal irq
86  *      @irq:   the irq to startup
87  *
88  *      Multiplex interrupts for @irq onto TR1. Clear any pending
89  *      interrupts.
90  */
91 static unsigned int metag_internal_irq_startup(struct irq_data *data)
92 {
93         /* Clear (toggle) the bit in HWSTATMETA for our interrupt. */
94         metag_internal_irq_ack(data);
95
96         /* Enable the interrupt by unmasking it */
97         metag_internal_irq_unmask(data);
98
99         return 0;
100 }
101
102 /*
103  *      metag_internal_irq_shutdown - turn off the irq
104  *      @irq:   the irq number to turn off
105  *
106  *      Mask @irq and clear any pending interrupts.
107  *      Stop muxing @irq onto TR1.
108  */
109 static void metag_internal_irq_shutdown(struct irq_data *data)
110 {
111         /* Disable the IRQ at the core by masking it. */
112         metag_internal_irq_mask(data);
113
114         /* Clear (toggle) the bit in HWSTATMETA for our interrupt. */
115         metag_internal_irq_ack(data);
116 }
117
118 /*
119  *      metag_internal_irq_ack - acknowledge irq
120  *      @irq:   the irq to ack
121  */
122 static void metag_internal_irq_ack(struct irq_data *data)
123 {
124         irq_hw_number_t hw = data->hwirq;
125         unsigned int bit = 1 << hw;
126
127         if (metag_in32(HWSTATMETA) & bit)
128                 metag_out32(bit, HWSTATMETA);
129 }
130
131 /**
132  * metag_internal_irq_mask() - mask an internal irq by unvectoring
133  * @data:       data for the internal irq to mask
134  *
135  * HWSTATMETA has no mask register. Instead the IRQ is unvectored from the core
136  * and retriggered if necessary later.
137  */
138 static void metag_internal_irq_mask(struct irq_data *data)
139 {
140         struct metag_internal_irq_priv *priv = &metag_internal_irq_priv;
141         irq_hw_number_t hw = data->hwirq;
142         void __iomem *vec_addr = metag_hwvec_addr(hw);
143
144         clear_bit(hw, &priv->unmasked);
145
146         /* there is no interrupt mask, so unvector the interrupt */
147         metag_out32(0, vec_addr);
148 }
149
150 /**
151  * meta_intc_unmask_edge_irq_nomask() - unmask an edge irq by revectoring
152  * @data:       data for the internal irq to unmask
153  *
154  * HWSTATMETA has no mask register. Instead the IRQ is revectored back to the
155  * core and retriggered if necessary.
156  */
157 static void metag_internal_irq_unmask(struct irq_data *data)
158 {
159         struct metag_internal_irq_priv *priv = &metag_internal_irq_priv;
160         irq_hw_number_t hw = data->hwirq;
161         unsigned int bit = 1 << hw;
162         void __iomem *vec_addr = metag_hwvec_addr(hw);
163         unsigned int thread = hard_processor_id();
164
165         set_bit(hw, &priv->unmasked);
166
167         /* there is no interrupt mask, so revector the interrupt */
168         metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR1(thread)), vec_addr);
169
170         /*
171          * Re-trigger interrupt
172          *
173          * Writing a 1 toggles, and a 0->1 transition triggers. We only
174          * retrigger if the status bit is already set, which means we
175          * need to clear it first. Retriggering is fundamentally racy
176          * because if the interrupt fires again after we clear it we
177          * could end up clearing it again and the interrupt handler
178          * thinking it hasn't fired. Therefore we need to keep trying to
179          * retrigger until the bit is set.
180          */
181         if (metag_in32(HWSTATMETA) & bit) {
182                 metag_out32(bit, HWSTATMETA);
183                 while (!(metag_in32(HWSTATMETA) & bit))
184                         metag_out32(bit, HWSTATMETA);
185         }
186 }
187
188 #ifdef CONFIG_SMP
189 /*
190  *      metag_internal_irq_set_affinity - set the affinity for an interrupt
191  */
192 static int metag_internal_irq_set_affinity(struct irq_data *data,
193                         const struct cpumask *cpumask, bool force)
194 {
195         unsigned int cpu, thread;
196         irq_hw_number_t hw = data->hwirq;
197         /*
198          * Wire up this interrupt from *VECINT to the Meta core.
199          *
200          * Note that we can't wire up *VECINT to interrupt more than
201          * one cpu (the interrupt code doesn't support it), so we just
202          * pick the first cpu we find in 'cpumask'.
203          */
204         cpu = cpumask_any_and(cpumask, cpu_online_mask);
205         thread = cpu_2_hwthread_id[cpu];
206
207         metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR1(thread)),
208                     metag_hwvec_addr(hw));
209
210         return 0;
211 }
212 #endif
213
214 /*
215  *      metag_internal_irq_demux - irq de-multiplexer
216  *      @irq:   the interrupt number
217  *      @desc:  the interrupt description structure for this irq
218  *
219  *      The cpu receives an interrupt on TR1 when an interrupt has
220  *      occurred. It is this function's job to demux this irq and
221  *      figure out exactly which trigger needs servicing.
222  */
223 static void metag_internal_irq_demux(struct irq_desc *desc)
224 {
225         struct metag_internal_irq_priv *priv = irq_desc_get_handler_data(desc);
226         irq_hw_number_t hw;
227         unsigned int irq_no;
228         u32 status;
229
230 recalculate:
231         status = metag_in32(HWSTATMETA) & priv->unmasked;
232
233         for (hw = 0; status != 0; status >>= 1, ++hw) {
234                 if (status & 0x1) {
235                         /*
236                          * Map the hardware IRQ number to a virtual Linux IRQ
237                          * number.
238                          */
239                         irq_no = irq_linear_revmap(priv->domain, hw);
240
241                         /*
242                          * Only fire off interrupts that are
243                          * registered to be handled by the kernel.
244                          * Other interrupts are probably being
245                          * handled by other Meta hardware threads.
246                          */
247                         generic_handle_irq(irq_no);
248
249                         /*
250                          * The handler may have re-enabled interrupts
251                          * which could have caused a nested invocation
252                          * of this code and make the copy of the
253                          * status register we are using invalid.
254                          */
255                         goto recalculate;
256                 }
257         }
258 }
259
260 /**
261  * internal_irq_map() - Map an internal meta IRQ to a virtual IRQ number.
262  * @hw:         Number of the internal IRQ. Must be in range.
263  *
264  * Returns:     The virtual IRQ number of the Meta internal IRQ specified by
265  *              @hw.
266  */
267 int internal_irq_map(unsigned int hw)
268 {
269         struct metag_internal_irq_priv *priv = &metag_internal_irq_priv;
270         if (!priv->domain)
271                 return -ENODEV;
272         return irq_create_mapping(priv->domain, hw);
273 }
274
275 /**
276  *      metag_internal_irq_init_cpu - regsister with the Meta cpu
277  *      @cpu:   the CPU to register on
278  *
279  *      Configure @cpu's TR1 irq so that we can demux irqs.
280  */
281 static void metag_internal_irq_init_cpu(struct metag_internal_irq_priv *priv,
282                                         int cpu)
283 {
284         unsigned int thread = cpu_2_hwthread_id[cpu];
285         unsigned int signum = TBID_SIGNUM_TR1(thread);
286         int irq = tbisig_map(signum);
287
288         /* Register the multiplexed IRQ handler */
289         irq_set_chained_handler_and_data(irq, metag_internal_irq_demux, priv);
290         irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
291 }
292
293 /**
294  * metag_internal_intc_map() - map an internal irq
295  * @d:          irq domain of internal trigger block
296  * @irq:        virtual irq number
297  * @hw:         hardware irq number within internal trigger block
298  *
299  * This sets up a virtual irq for a specified hardware interrupt. The irq chip
300  * and handler is configured.
301  */
302 static int metag_internal_intc_map(struct irq_domain *d, unsigned int irq,
303                                    irq_hw_number_t hw)
304 {
305         /* only register interrupt if it is mapped */
306         if (!metag_hwvec_addr(hw))
307                 return -EINVAL;
308
309         irq_set_chip_and_handler(irq, &internal_irq_edge_chip,
310                                  handle_edge_irq);
311         return 0;
312 }
313
314 static const struct irq_domain_ops metag_internal_intc_domain_ops = {
315         .map    = metag_internal_intc_map,
316 };
317
318 /**
319  *      metag_internal_irq_register - register internal IRQs
320  *
321  *      Register the irq chip and handler function for all internal IRQs
322  */
323 int __init init_internal_IRQ(void)
324 {
325         struct metag_internal_irq_priv *priv = &metag_internal_irq_priv;
326         unsigned int cpu;
327
328         /* Set up an IRQ domain */
329         priv->domain = irq_domain_add_linear(NULL, 32,
330                                              &metag_internal_intc_domain_ops,
331                                              priv);
332         if (unlikely(!priv->domain)) {
333                 pr_err("meta-internal-intc: cannot add IRQ domain\n");
334                 return -ENOMEM;
335         }
336
337         /* Setup TR1 for all cpus. */
338         for_each_possible_cpu(cpu)
339                 metag_internal_irq_init_cpu(priv, cpu);
340
341         return 0;
342 };