aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/variants/s6000/irq.c
blob: 81a241e790753e9510df234f28caa9003f8321c5 (plain)
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);
}