Blame view

arch/arm/mach-at91/irq.c 4.37 KB
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
1
  /*
9d0412680   Andrew Victor   [ARM] 4124/1: Ren...
2
   * linux/arch/arm/mach-at91/irq.c
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
   *
   *  Copyright (C) 2004 SAN People
   *  Copyright (C) 2004 ATMEL
   *  Copyright (C) Rick Bronson
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
22
23
24
25
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/mm.h>
  #include <linux/types.h>
a09e64fbc   Russell King   [ARM] Move includ...
26
  #include <mach/hardware.h>
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
27
  #include <asm/irq.h>
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
28
29
30
31
32
  #include <asm/setup.h>
  
  #include <asm/mach/arch.h>
  #include <asm/mach/irq.h>
  #include <asm/mach/map.h>
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
33
  void __iomem *at91_aic_base;
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
34

da0f9403d   Lennert Buytenhek   ARM: at91: irq_da...
35
  static void at91_aic_mask_irq(struct irq_data *d)
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
36
37
  {
  	/* Disable interrupt on AIC */
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
38
  	at91_aic_write(AT91_AIC_IDCR, 1 << d->irq);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
39
  }
da0f9403d   Lennert Buytenhek   ARM: at91: irq_da...
40
  static void at91_aic_unmask_irq(struct irq_data *d)
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
41
42
  {
  	/* Enable interrupt on AIC */
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
43
  	at91_aic_write(AT91_AIC_IECR, 1 << d->irq);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
44
  }
1f4fd0a0d   Andrew Victor   [ARM] 3946/1: AT9...
45
46
47
  unsigned int at91_extern_irq;
  
  #define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq)
da0f9403d   Lennert Buytenhek   ARM: at91: irq_da...
48
  static int at91_aic_set_type(struct irq_data *d, unsigned type)
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
49
50
  {
  	unsigned int smr, srctype;
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
51
  	switch (type) {
6cab48602   Dmitry Eremin-Solenikov   [ARM] 5179/1: Rep...
52
  	case IRQ_TYPE_LEVEL_HIGH:
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
53
54
  		srctype = AT91_AIC_SRCTYPE_HIGH;
  		break;
6cab48602   Dmitry Eremin-Solenikov   [ARM] 5179/1: Rep...
55
  	case IRQ_TYPE_EDGE_RISING:
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
56
57
  		srctype = AT91_AIC_SRCTYPE_RISING;
  		break;
6cab48602   Dmitry Eremin-Solenikov   [ARM] 5179/1: Rep...
58
  	case IRQ_TYPE_LEVEL_LOW:
da0f9403d   Lennert Buytenhek   ARM: at91: irq_da...
59
  		if ((d->irq == AT91_ID_FIQ) || is_extern_irq(d->irq))		/* only supported on external interrupts */
1f4fd0a0d   Andrew Victor   [ARM] 3946/1: AT9...
60
61
  			srctype = AT91_AIC_SRCTYPE_LOW;
  		else
37f2e4bc1   Andrew Victor   [ARM] 3582/1: AT9...
62
  			return -EINVAL;
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
63
  		break;
6cab48602   Dmitry Eremin-Solenikov   [ARM] 5179/1: Rep...
64
  	case IRQ_TYPE_EDGE_FALLING:
da0f9403d   Lennert Buytenhek   ARM: at91: irq_da...
65
  		if ((d->irq == AT91_ID_FIQ) || is_extern_irq(d->irq))		/* only supported on external interrupts */
1f4fd0a0d   Andrew Victor   [ARM] 3946/1: AT9...
66
67
  			srctype = AT91_AIC_SRCTYPE_FALLING;
  		else
37f2e4bc1   Andrew Victor   [ARM] 3582/1: AT9...
68
  			return -EINVAL;
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
69
70
71
72
  		break;
  	default:
  		return -EINVAL;
  	}
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
73
74
  	smr = at91_aic_read(AT91_AIC_SMR(d->irq)) & ~AT91_AIC_SRCTYPE;
  	at91_aic_write(AT91_AIC_SMR(d->irq), smr | srctype);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
75
76
  	return 0;
  }
683c66bf7   Andrew Victor   [ARM] 3583/1: AT9...
77
78
79
80
  #ifdef CONFIG_PM
  
  static u32 wakeups;
  static u32 backups;
da0f9403d   Lennert Buytenhek   ARM: at91: irq_da...
81
  static int at91_aic_set_wake(struct irq_data *d, unsigned value)
683c66bf7   Andrew Victor   [ARM] 3583/1: AT9...
82
  {
da0f9403d   Lennert Buytenhek   ARM: at91: irq_da...
83
  	if (unlikely(d->irq >= 32))
683c66bf7   Andrew Victor   [ARM] 3583/1: AT9...
84
85
86
  		return -EINVAL;
  
  	if (value)
da0f9403d   Lennert Buytenhek   ARM: at91: irq_da...
87
  		wakeups |= (1 << d->irq);
683c66bf7   Andrew Victor   [ARM] 3583/1: AT9...
88
  	else
da0f9403d   Lennert Buytenhek   ARM: at91: irq_da...
89
  		wakeups &= ~(1 << d->irq);
683c66bf7   Andrew Victor   [ARM] 3583/1: AT9...
90
91
92
93
94
95
  
  	return 0;
  }
  
  void at91_irq_suspend(void)
  {
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
96
97
98
  	backups = at91_aic_read(AT91_AIC_IMR);
  	at91_aic_write(AT91_AIC_IDCR, backups);
  	at91_aic_write(AT91_AIC_IECR, wakeups);
683c66bf7   Andrew Victor   [ARM] 3583/1: AT9...
99
100
101
102
  }
  
  void at91_irq_resume(void)
  {
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
103
104
  	at91_aic_write(AT91_AIC_IDCR, wakeups);
  	at91_aic_write(AT91_AIC_IECR, backups);
683c66bf7   Andrew Victor   [ARM] 3583/1: AT9...
105
106
107
  }
  
  #else
ba854e184   Andrew Victor   [ARM] 3711/1: AT9...
108
  #define at91_aic_set_wake	NULL
683c66bf7   Andrew Victor   [ARM] 3583/1: AT9...
109
  #endif
38c677cb9   David Brownell   [ARM] 3739/1: gen...
110
111
  static struct irq_chip at91_aic_chip = {
  	.name		= "AIC",
da0f9403d   Lennert Buytenhek   ARM: at91: irq_da...
112
113
114
115
116
  	.irq_ack	= at91_aic_mask_irq,
  	.irq_mask	= at91_aic_mask_irq,
  	.irq_unmask	= at91_aic_unmask_irq,
  	.irq_set_type	= at91_aic_set_type,
  	.irq_set_wake	= at91_aic_set_wake,
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
117
118
119
120
121
  };
  
  /*
   * Initialize the AIC interrupt controller.
   */
ba854e184   Andrew Victor   [ARM] 3711/1: AT9...
122
  void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
123
124
  {
  	unsigned int i;
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
125
126
127
128
129
  	at91_aic_base = ioremap(AT91_AIC, 512);
  
  	if (!at91_aic_base)
  		panic("Impossible to ioremap AT91_AIC
  ");
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
130
131
132
133
134
135
  	/*
  	 * The IVR is used by macro get_irqnr_and_base to read and verify.
  	 * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
  	 */
  	for (i = 0; i < NR_AIC_IRQS; i++) {
  		/* Put irq number in Source Vector Register: */
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
136
  		at91_aic_write(AT91_AIC_SVR(i), i);
ba854e184   Andrew Victor   [ARM] 3711/1: AT9...
137
  		/* Active Low interrupt, with the specified priority */
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
138
  		at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
139

f38c02f3b   Thomas Gleixner   arm: Fold irq_set...
140
  		irq_set_chip_and_handler(i, &at91_aic_chip, handle_level_irq);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
141
142
143
144
  		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
  
  		/* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */
  		if (i < 8)
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
145
  			at91_aic_write(AT91_AIC_EOICR, 0);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
146
147
148
149
150
151
  	}
  
  	/*
  	 * Spurious Interrupt ID in Spurious Vector Register is NR_AIC_IRQS
  	 * When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU
  	 */
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
152
  	at91_aic_write(AT91_AIC_SPU, NR_AIC_IRQS);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
153
154
  
  	/* No debugging in AIC: Debug (Protect) Control Register */
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
155
  	at91_aic_write(AT91_AIC_DCR, 0);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
156
157
  
  	/* Disable and clear all interrupts initially */
be6d43217   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: make a...
158
159
  	at91_aic_write(AT91_AIC_IDCR, 0xFFFFFFFF);
  	at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
160
  }