1/*
2 * arch/arm/mach-ns9xxx/irq.c
3 *
4 * Copyright (C) 2006,2007 by Digi International Inc.
5 * All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 */
11#include <linux/interrupt.h>
12#include <asm/mach/irq.h>
13#include <asm/mach-types.h>
14#include <asm/arch-ns9xxx/regs-sys.h>
15#include <asm/arch-ns9xxx/irqs.h>
16#include <asm/arch-ns9xxx/board.h>
17
18#include "generic.h"
19
20static void ns9xxx_ack_irq_timer(unsigned int irq)
21{
22	u32 tc = SYS_TC(irq - IRQ_TIMER0);
23
24	REGSET(tc, SYS_TCx, INTC, SET);
25	SYS_TC(irq - IRQ_TIMER0) = tc;
26
27	REGSET(tc, SYS_TCx, INTC, UNSET);
28	SYS_TC(irq - IRQ_TIMER0) = tc;
29}
30
31void (*ns9xxx_ack_irq_functions[NR_IRQS])(unsigned int) = {
32	[IRQ_TIMER0] = ns9xxx_ack_irq_timer,
33	[IRQ_TIMER1] = ns9xxx_ack_irq_timer,
34	[IRQ_TIMER2] = ns9xxx_ack_irq_timer,
35	[IRQ_TIMER3] = ns9xxx_ack_irq_timer,
36};
37
38static void ns9xxx_mask_irq(unsigned int irq)
39{
40	SYS_IC(irq / 4) &= ~(1 << (7 + 8 * (3 - (irq & 3))));
41}
42
43static void ns9xxx_ack_irq(unsigned int irq)
44{
45	if (!ns9xxx_ack_irq_functions[irq]) {
46		printk(KERN_ERR "no ack function for irq %u\n", irq);
47		BUG();
48	}
49
50	ns9xxx_ack_irq_functions[irq](irq);
51	SYS_ISRADDR = 0;
52}
53
54static void ns9xxx_maskack_irq(unsigned int irq)
55{
56	ns9xxx_mask_irq(irq);
57	ns9xxx_ack_irq(irq);
58}
59
60static void ns9xxx_unmask_irq(unsigned int irq)
61{
62	SYS_IC(irq / 4) |= 1 << (7 + 8 * (3 - (irq & 3)));
63}
64
65static struct irq_chip ns9xxx_chip = {
66	.ack		= ns9xxx_ack_irq,
67	.mask		= ns9xxx_mask_irq,
68	.mask_ack	= ns9xxx_maskack_irq,
69	.unmask		= ns9xxx_unmask_irq,
70};
71
72void __init ns9xxx_init_irq(void)
73{
74	int i;
75
76	/* disable all IRQs */
77	for (i = 0; i < 8; ++i)
78		SYS_IC(i) = (4 * i) << 24 | (4 * i + 1) << 16 |
79			(4 * i + 2) << 8 | (4 * i + 3);
80
81	/* simple interrupt prio table:
82	 * prio(x) < prio(y) <=> x < y
83	 */
84	for (i = 0; i < 32; ++i)
85		SYS_IVA(i) = i;
86
87	for (i = IRQ_WATCHDOG; i <= IRQ_EXT3; ++i) {
88		set_irq_chip(i, &ns9xxx_chip);
89		set_irq_handler(i, handle_level_irq);
90		set_irq_flags(i, IRQF_VALID);
91	}
92}
93