Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
arm
mach-gemini
irq.c
Go to the documentation of this file.
1
/*
2
* Interrupt routines for Gemini
3
*
4
* Copyright (C) 2001-2006 Storlink, Corp.
5
* Copyright (C) 2008-2009 Paulius Zaleckas <
[email protected]
>
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
11
*/
12
#include <
linux/init.h
>
13
#include <
linux/io.h
>
14
#include <
linux/ioport.h
>
15
#include <linux/stddef.h>
16
#include <linux/list.h>
17
#include <linux/sched.h>
18
#include <asm/irq.h>
19
#include <
asm/mach/irq.h
>
20
#include <asm/system_misc.h>
21
#include <mach/hardware.h>
22
23
#define IRQ_SOURCE(base_addr) (base_addr + 0x00)
24
#define IRQ_MASK(base_addr) (base_addr + 0x04)
25
#define IRQ_CLEAR(base_addr) (base_addr + 0x08)
26
#define IRQ_TMODE(base_addr) (base_addr + 0x0C)
27
#define IRQ_TLEVEL(base_addr) (base_addr + 0x10)
28
#define IRQ_STATUS(base_addr) (base_addr + 0x14)
29
#define FIQ_SOURCE(base_addr) (base_addr + 0x20)
30
#define FIQ_MASK(base_addr) (base_addr + 0x24)
31
#define FIQ_CLEAR(base_addr) (base_addr + 0x28)
32
#define FIQ_TMODE(base_addr) (base_addr + 0x2C)
33
#define FIQ_LEVEL(base_addr) (base_addr + 0x30)
34
#define FIQ_STATUS(base_addr) (base_addr + 0x34)
35
36
static
void
gemini_ack_irq(
struct
irq_data
*
d
)
37
{
38
__raw_writel
(1 << d->
irq
,
IRQ_CLEAR
(
IO_ADDRESS
(
GEMINI_INTERRUPT_BASE
)));
39
}
40
41
static
void
gemini_mask_irq(
struct
irq_data
*
d
)
42
{
43
unsigned
int
mask
;
44
45
mask =
__raw_readl
(
IRQ_MASK
(
IO_ADDRESS
(
GEMINI_INTERRUPT_BASE
)));
46
mask &= ~(1 << d->
irq
);
47
__raw_writel
(mask,
IRQ_MASK
(
IO_ADDRESS
(
GEMINI_INTERRUPT_BASE
)));
48
}
49
50
static
void
gemini_unmask_irq(
struct
irq_data
*d)
51
{
52
unsigned
int
mask
;
53
54
mask =
__raw_readl
(
IRQ_MASK
(
IO_ADDRESS
(
GEMINI_INTERRUPT_BASE
)));
55
mask |= (1 << d->
irq
);
56
__raw_writel
(mask,
IRQ_MASK
(
IO_ADDRESS
(
GEMINI_INTERRUPT_BASE
)));
57
}
58
59
static
struct
irq_chip
gemini_irq_chip = {
60
.name =
"INTC"
,
61
.irq_ack = gemini_ack_irq,
62
.irq_mask = gemini_mask_irq,
63
.irq_unmask = gemini_unmask_irq,
64
};
65
66
static
struct
resource
irq_resource = {
67
.name =
"irq_handler"
,
68
.start =
IO_ADDRESS
(
GEMINI_INTERRUPT_BASE
),
69
.end =
IO_ADDRESS
(
FIQ_STATUS
(
GEMINI_INTERRUPT_BASE
)) + 4,
70
};
71
72
void
__init
gemini_init_irq
(
void
)
73
{
74
unsigned
int
i
,
mode
= 0,
level
= 0;
75
76
/*
77
* Disable the idle handler by default since it is buggy
78
* For more info see arch/arm/mach-gemini/idle.c
79
*/
80
disable_hlt
();
81
82
request_resource
(&
iomem_resource
, &irq_resource);
83
84
for
(i = 0; i <
NR_IRQS
; i++) {
85
irq_set_chip
(i, &gemini_irq_chip);
86
if
((i >=
IRQ_TIMER1
&& i <=
IRQ_TIMER3
) || (i >=
IRQ_SERIRQ0
&& i <=
IRQ_SERIRQ1
)) {
87
irq_set_handler(i,
handle_edge_irq
);
88
mode |= 1 <<
i
;
89
level
|= 1 <<
i
;
90
}
else
{
91
irq_set_handler(i,
handle_level_irq
);
92
}
93
set_irq_flags
(i,
IRQF_VALID
|
IRQF_PROBE
);
94
}
95
96
/* Disable all interrupts */
97
__raw_writel
(0,
IRQ_MASK
(
IO_ADDRESS
(
GEMINI_INTERRUPT_BASE
)));
98
__raw_writel
(0,
FIQ_MASK
(
IO_ADDRESS
(
GEMINI_INTERRUPT_BASE
)));
99
100
/* Set interrupt mode */
101
__raw_writel
(mode,
IRQ_TMODE
(
IO_ADDRESS
(
GEMINI_INTERRUPT_BASE
)));
102
__raw_writel
(
level
,
IRQ_TLEVEL
(
IO_ADDRESS
(
GEMINI_INTERRUPT_BASE
)));
103
}
Generated on Thu Jan 10 2013 12:51:23 for Linux Kernel by
1.8.2