1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
/*
* s6000 irq crossbar
*
* Copyright (c) 2009 emlix GmbH
* Authors: Johannes Weiner <hannes@cmpxchg.org>
* Oskar Schirmer <oskar@scara.com>
*/
#include <linux/io.h>
#include <asm/irq.h>
#include <variant/hardware.h>
/* S6_REG_INTC */
#define INTC_STATUS 0x000
#define INTC_RAW 0x010
#define INTC_STATUS_AG 0x100
#define INTC_CFG(n) (0x200 + 4 * (n))
/*
* The s6000 has a crossbar that multiplexes interrupt output lines
* from the peripherals to input lines on the xtensa core.
*
* We leave the mapping decisions to the platform as it depends on the
* actually connected peripherals which distribution makes sense.
*/
extern const signed char *platform_irq_mappings[NR_IRQS];
static unsigned long scp_to_intc_enable[] = {
#define TO_INTC_ENABLE(n) (((n) << 1) + 1)
TO_INTC_ENABLE(0),
TO_INTC_ENABLE(1),
TO_INTC_ENABLE(2),
TO_INTC_ENABLE(3),
TO_INTC_ENABLE(4),
TO_INTC_ENABLE(5),
TO_INTC_ENABLE(6),
TO_INTC_ENABLE(7),
TO_INTC_ENABLE(8),
TO_INTC_ENABLE(9),
TO_INTC_ENABLE(10),
TO_INTC_ENABLE(11),
TO_INTC_ENABLE(12),
-1,
-1,
TO_INTC_ENABLE(13),
-1,
TO_INTC_ENABLE(14),
-1,
TO_INTC_ENABLE(15),
#undef TO_INTC_ENABLE
};
static void irq_set(unsigned int irq, int enable)
{
unsigned long en;
const signed char *m = platform_irq_mappings[irq];
if (!m)
return;
en = enable ? scp_to_intc_enable[irq] : 0;
while (*m >= 0) {
writel(en, S6_REG_INTC + INTC_CFG(*m));
m++;
}
}
void variant_irq_enable(unsigned int irq)
{
irq_set(irq, 1);
}
void variant_irq_disable(unsigned int irq)
{
irq_set(irq, 0);
}
|