~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to arch/unicore32/kernel/irq.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * linux/arch/unicore32/kernel/irq.c
 
3
 *
 
4
 * Code specific to PKUnity SoC and UniCore ISA
 
5
 *
 
6
 * Copyright (C) 2001-2010 GUAN Xue-tao
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License version 2 as
 
10
 * published by the Free Software Foundation.
 
11
 */
 
12
#include <linux/kernel_stat.h>
 
13
#include <linux/module.h>
 
14
#include <linux/signal.h>
 
15
#include <linux/ioport.h>
 
16
#include <linux/interrupt.h>
 
17
#include <linux/irq.h>
 
18
#include <linux/random.h>
 
19
#include <linux/smp.h>
 
20
#include <linux/init.h>
 
21
#include <linux/seq_file.h>
 
22
#include <linux/errno.h>
 
23
#include <linux/list.h>
 
24
#include <linux/kallsyms.h>
 
25
#include <linux/proc_fs.h>
 
26
#include <linux/sysdev.h>
 
27
#include <linux/gpio.h>
 
28
 
 
29
#include <asm/system.h>
 
30
#include <mach/hardware.h>
 
31
 
 
32
#include "setup.h"
 
33
 
 
34
/*
 
35
 * PKUnity GPIO edge detection for IRQs:
 
36
 * IRQs are generated on Falling-Edge, Rising-Edge, or both.
 
37
 * Use this instead of directly setting GRER/GFER.
 
38
 */
 
39
static int GPIO_IRQ_rising_edge;
 
40
static int GPIO_IRQ_falling_edge;
 
41
static int GPIO_IRQ_mask = 0;
 
42
 
 
43
#define GPIO_MASK(irq)          (1 << (irq - IRQ_GPIO0))
 
44
 
 
45
static int puv3_gpio_type(struct irq_data *d, unsigned int type)
 
46
{
 
47
        unsigned int mask;
 
48
 
 
49
        if (d->irq < IRQ_GPIOHIGH)
 
50
                mask = 1 << d->irq;
 
51
        else
 
52
                mask = GPIO_MASK(d->irq);
 
53
 
 
54
        if (type == IRQ_TYPE_PROBE) {
 
55
                if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
 
56
                        return 0;
 
57
                type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
 
58
        }
 
59
 
 
60
        if (type & IRQ_TYPE_EDGE_RISING)
 
61
                GPIO_IRQ_rising_edge |= mask;
 
62
        else
 
63
                GPIO_IRQ_rising_edge &= ~mask;
 
64
        if (type & IRQ_TYPE_EDGE_FALLING)
 
65
                GPIO_IRQ_falling_edge |= mask;
 
66
        else
 
67
                GPIO_IRQ_falling_edge &= ~mask;
 
68
 
 
69
        writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
 
70
        writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
 
71
 
 
72
        return 0;
 
73
}
 
74
 
 
75
/*
 
76
 * GPIO IRQs must be acknowledged.  This is for IRQs from 0 to 7.
 
77
 */
 
78
static void puv3_low_gpio_ack(struct irq_data *d)
 
79
{
 
80
        writel((1 << d->irq), GPIO_GEDR);
 
81
}
 
82
 
 
83
static void puv3_low_gpio_mask(struct irq_data *d)
 
84
{
 
85
        writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR);
 
86
}
 
87
 
 
88
static void puv3_low_gpio_unmask(struct irq_data *d)
 
89
{
 
90
        writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR);
 
91
}
 
92
 
 
93
static int puv3_low_gpio_wake(struct irq_data *d, unsigned int on)
 
94
{
 
95
        if (on)
 
96
                writel(readl(PM_PWER) | (1 << d->irq), PM_PWER);
 
97
        else
 
98
                writel(readl(PM_PWER) & ~(1 << d->irq), PM_PWER);
 
99
        return 0;
 
100
}
 
101
 
 
102
static struct irq_chip puv3_low_gpio_chip = {
 
103
        .name           = "GPIO-low",
 
104
        .irq_ack        = puv3_low_gpio_ack,
 
105
        .irq_mask       = puv3_low_gpio_mask,
 
106
        .irq_unmask     = puv3_low_gpio_unmask,
 
107
        .irq_set_type   = puv3_gpio_type,
 
108
        .irq_set_wake   = puv3_low_gpio_wake,
 
109
};
 
110
 
 
111
/*
 
112
 * IRQ8 (GPIO0 through 27) handler.  We enter here with the
 
113
 * irq_controller_lock held, and IRQs disabled.  Decode the IRQ
 
114
 * and call the handler.
 
115
 */
 
116
static void
 
117
puv3_gpio_handler(unsigned int irq, struct irq_desc *desc)
 
118
{
 
119
        unsigned int mask;
 
120
 
 
121
        mask = readl(GPIO_GEDR);
 
122
        do {
 
123
                /*
 
124
                 * clear down all currently active IRQ sources.
 
125
                 * We will be processing them all.
 
126
                 */
 
127
                writel(mask, GPIO_GEDR);
 
128
 
 
129
                irq = IRQ_GPIO0;
 
130
                do {
 
131
                        if (mask & 1)
 
132
                                generic_handle_irq(irq);
 
133
                        mask >>= 1;
 
134
                        irq++;
 
135
                } while (mask);
 
136
                mask = readl(GPIO_GEDR);
 
137
        } while (mask);
 
138
}
 
139
 
 
140
/*
 
141
 * GPIO0-27 edge IRQs need to be handled specially.
 
142
 * In addition, the IRQs are all collected up into one bit in the
 
143
 * interrupt controller registers.
 
144
 */
 
145
static void puv3_high_gpio_ack(struct irq_data *d)
 
146
{
 
147
        unsigned int mask = GPIO_MASK(d->irq);
 
148
 
 
149
        writel(mask, GPIO_GEDR);
 
150
}
 
151
 
 
152
static void puv3_high_gpio_mask(struct irq_data *d)
 
153
{
 
154
        unsigned int mask = GPIO_MASK(d->irq);
 
155
 
 
156
        GPIO_IRQ_mask &= ~mask;
 
157
 
 
158
        writel(readl(GPIO_GRER) & ~mask, GPIO_GRER);
 
159
        writel(readl(GPIO_GFER) & ~mask, GPIO_GFER);
 
160
}
 
161
 
 
162
static void puv3_high_gpio_unmask(struct irq_data *d)
 
163
{
 
164
        unsigned int mask = GPIO_MASK(d->irq);
 
165
 
 
166
        GPIO_IRQ_mask |= mask;
 
167
 
 
168
        writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
 
169
        writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
 
170
}
 
171
 
 
172
static int puv3_high_gpio_wake(struct irq_data *d, unsigned int on)
 
173
{
 
174
        if (on)
 
175
                writel(readl(PM_PWER) | PM_PWER_GPIOHIGH, PM_PWER);
 
176
        else
 
177
                writel(readl(PM_PWER) & ~PM_PWER_GPIOHIGH, PM_PWER);
 
178
        return 0;
 
179
}
 
180
 
 
181
static struct irq_chip puv3_high_gpio_chip = {
 
182
        .name           = "GPIO-high",
 
183
        .irq_ack        = puv3_high_gpio_ack,
 
184
        .irq_mask       = puv3_high_gpio_mask,
 
185
        .irq_unmask     = puv3_high_gpio_unmask,
 
186
        .irq_set_type   = puv3_gpio_type,
 
187
        .irq_set_wake   = puv3_high_gpio_wake,
 
188
};
 
189
 
 
190
/*
 
191
 * We don't need to ACK IRQs on the PKUnity unless they're GPIOs
 
192
 * this is for internal IRQs i.e. from 8 to 31.
 
193
 */
 
194
static void puv3_mask_irq(struct irq_data *d)
 
195
{
 
196
        writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR);
 
197
}
 
198
 
 
199
static void puv3_unmask_irq(struct irq_data *d)
 
200
{
 
201
        writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR);
 
202
}
 
203
 
 
204
/*
 
205
 * Apart form GPIOs, only the RTC alarm can be a wakeup event.
 
206
 */
 
207
static int puv3_set_wake(struct irq_data *d, unsigned int on)
 
208
{
 
209
        if (d->irq == IRQ_RTCAlarm) {
 
210
                if (on)
 
211
                        writel(readl(PM_PWER) | PM_PWER_RTC, PM_PWER);
 
212
                else
 
213
                        writel(readl(PM_PWER) & ~PM_PWER_RTC, PM_PWER);
 
214
                return 0;
 
215
        }
 
216
        return -EINVAL;
 
217
}
 
218
 
 
219
static struct irq_chip puv3_normal_chip = {
 
220
        .name           = "PKUnity-v3",
 
221
        .irq_ack        = puv3_mask_irq,
 
222
        .irq_mask       = puv3_mask_irq,
 
223
        .irq_unmask     = puv3_unmask_irq,
 
224
        .irq_set_wake   = puv3_set_wake,
 
225
};
 
226
 
 
227
static struct resource irq_resource = {
 
228
        .name   = "irqs",
 
229
        .start  = io_v2p(PKUNITY_INTC_BASE),
 
230
        .end    = io_v2p(PKUNITY_INTC_BASE) + 0xFFFFF,
 
231
};
 
232
 
 
233
static struct puv3_irq_state {
 
234
        unsigned int    saved;
 
235
        unsigned int    icmr;
 
236
        unsigned int    iclr;
 
237
        unsigned int    iccr;
 
238
} puv3_irq_state;
 
239
 
 
240
static int puv3_irq_suspend(struct sys_device *dev, pm_message_t state)
 
241
{
 
242
        struct puv3_irq_state *st = &puv3_irq_state;
 
243
 
 
244
        st->saved = 1;
 
245
        st->icmr = readl(INTC_ICMR);
 
246
        st->iclr = readl(INTC_ICLR);
 
247
        st->iccr = readl(INTC_ICCR);
 
248
 
 
249
        /*
 
250
         * Disable all GPIO-based interrupts.
 
251
         */
 
252
        writel(readl(INTC_ICMR) & ~(0x1ff), INTC_ICMR);
 
253
 
 
254
        /*
 
255
         * Set the appropriate edges for wakeup.
 
256
         */
 
257
        writel(readl(PM_PWER) & GPIO_IRQ_rising_edge, GPIO_GRER);
 
258
        writel(readl(PM_PWER) & GPIO_IRQ_falling_edge, GPIO_GFER);
 
259
 
 
260
        /*
 
261
         * Clear any pending GPIO interrupts.
 
262
         */
 
263
        writel(readl(GPIO_GEDR), GPIO_GEDR);
 
264
 
 
265
        return 0;
 
266
}
 
267
 
 
268
static int puv3_irq_resume(struct sys_device *dev)
 
269
{
 
270
        struct puv3_irq_state *st = &puv3_irq_state;
 
271
 
 
272
        if (st->saved) {
 
273
                writel(st->iccr, INTC_ICCR);
 
274
                writel(st->iclr, INTC_ICLR);
 
275
 
 
276
                writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
 
277
                writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
 
278
 
 
279
                writel(st->icmr, INTC_ICMR);
 
280
        }
 
281
        return 0;
 
282
}
 
283
 
 
284
static struct sysdev_class puv3_irq_sysclass = {
 
285
        .name           = "pkunity-irq",
 
286
        .suspend        = puv3_irq_suspend,
 
287
        .resume         = puv3_irq_resume,
 
288
};
 
289
 
 
290
static struct sys_device puv3_irq_device = {
 
291
        .id             = 0,
 
292
        .cls            = &puv3_irq_sysclass,
 
293
};
 
294
 
 
295
static int __init puv3_irq_init_devicefs(void)
 
296
{
 
297
        sysdev_class_register(&puv3_irq_sysclass);
 
298
        return sysdev_register(&puv3_irq_device);
 
299
}
 
300
 
 
301
device_initcall(puv3_irq_init_devicefs);
 
302
 
 
303
void __init init_IRQ(void)
 
304
{
 
305
        unsigned int irq;
 
306
 
 
307
        request_resource(&iomem_resource, &irq_resource);
 
308
 
 
309
        /* disable all IRQs */
 
310
        writel(0, INTC_ICMR);
 
311
 
 
312
        /* all IRQs are IRQ, not REAL */
 
313
        writel(0, INTC_ICLR);
 
314
 
 
315
        /* clear all GPIO edge detects */
 
316
        writel(FMASK(8, 0) & ~FIELD(1, 1, GPI_SOFF_REQ), GPIO_GPIR);
 
317
        writel(0, GPIO_GFER);
 
318
        writel(0, GPIO_GRER);
 
319
        writel(0x0FFFFFFF, GPIO_GEDR);
 
320
 
 
321
        writel(1, INTC_ICCR);
 
322
 
 
323
        for (irq = 0; irq < IRQ_GPIOHIGH; irq++) {
 
324
                irq_set_chip(irq, &puv3_low_gpio_chip);
 
325
                irq_set_handler(irq, handle_edge_irq);
 
326
                irq_modify_status(irq,
 
327
                        IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
 
328
                        0);
 
329
        }
 
330
 
 
331
        for (irq = IRQ_GPIOHIGH + 1; irq < IRQ_GPIO0; irq++) {
 
332
                irq_set_chip(irq, &puv3_normal_chip);
 
333
                irq_set_handler(irq, handle_level_irq);
 
334
                irq_modify_status(irq,
 
335
                        IRQ_NOREQUEST | IRQ_NOAUTOEN,
 
336
                        IRQ_NOPROBE);
 
337
        }
 
338
 
 
339
        for (irq = IRQ_GPIO0; irq <= IRQ_GPIO27; irq++) {
 
340
                irq_set_chip(irq, &puv3_high_gpio_chip);
 
341
                irq_set_handler(irq, handle_edge_irq);
 
342
                irq_modify_status(irq,
 
343
                        IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
 
344
                        0);
 
345
        }
 
346
 
 
347
        /*
 
348
         * Install handler for GPIO 0-27 edge detect interrupts
 
349
         */
 
350
        irq_set_chip(IRQ_GPIOHIGH, &puv3_normal_chip);
 
351
        irq_set_chained_handler(IRQ_GPIOHIGH, puv3_gpio_handler);
 
352
 
 
353
#ifdef CONFIG_PUV3_GPIO
 
354
        puv3_init_gpio();
 
355
#endif
 
356
}
 
357
 
 
358
/*
 
359
 * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
 
360
 * come via this function.  Instead, they should provide their
 
361
 * own 'handler'
 
362
 */
 
363
asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 
364
{
 
365
        struct pt_regs *old_regs = set_irq_regs(regs);
 
366
 
 
367
        irq_enter();
 
368
 
 
369
        /*
 
370
         * Some hardware gives randomly wrong interrupts.  Rather
 
371
         * than crashing, do something sensible.
 
372
         */
 
373
        if (unlikely(irq >= nr_irqs)) {
 
374
                if (printk_ratelimit())
 
375
                        printk(KERN_WARNING "Bad IRQ%u\n", irq);
 
376
                ack_bad_irq(irq);
 
377
        } else {
 
378
                generic_handle_irq(irq);
 
379
        }
 
380
 
 
381
        irq_exit();
 
382
        set_irq_regs(old_regs);
 
383
}
 
384