Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
41bd61a8
Commit
41bd61a8
authored
Oct 15, 2007
by
Ralf Baechle
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[MIPS] Alchemy: cleanup interrupt code.
Signed-off-by:
Ralf Baechle
<
ralf@linux-mips.org
>
parent
a5ccfe5c
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
313 additions
and
341 deletions
+313
-341
arch/mips/au1000/common/irq.c
arch/mips/au1000/common/irq.c
+313
-341
No files found.
arch/mips/au1000/common/irq.c
View file @
41bd61a8
...
...
@@ -26,39 +26,18 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/
errno
.h>
#include <linux/
bitops
.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/timex.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/delay.h>
#include <linux/bitops.h>
#include <linux/irq.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
#include <asm/mach-au1x00/au1000.h>
#ifdef CONFIG_MIPS_PB1000
#include <asm/mach-pb1x00/pb1000.h>
#endif
#undef DEBUG_IRQ
#ifdef DEBUG_IRQ
/* note: prints function name for you */
#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
#else
#define DPRINTK(fmt, args...)
#endif
#define EXT_INTC0_REQ0 2
/* IP 2 */
#define EXT_INTC0_REQ1 3
/* IP 3 */
#define EXT_INTC1_REQ0 4
/* IP 4 */
...
...
@@ -69,16 +48,98 @@ void (*board_init_irq)(void);
static
DEFINE_SPINLOCK
(
irq_lock
);
#ifdef CONFIG_PM
/*
* Save/restore the interrupt controller state.
* Called from the save/restore core registers as part of the
* au_sleep function in power.c.....maybe I should just pm_register()
* them instead?
*/
static
unsigned
int
sleep_intctl_config0
[
2
];
static
unsigned
int
sleep_intctl_config1
[
2
];
static
unsigned
int
sleep_intctl_config2
[
2
];
static
unsigned
int
sleep_intctl_src
[
2
];
static
unsigned
int
sleep_intctl_assign
[
2
];
static
unsigned
int
sleep_intctl_wake
[
2
];
static
unsigned
int
sleep_intctl_mask
[
2
];
void
save_au1xxx_intctl
(
void
)
{
sleep_intctl_config0
[
0
]
=
au_readl
(
IC0_CFG0RD
);
sleep_intctl_config1
[
0
]
=
au_readl
(
IC0_CFG1RD
);
sleep_intctl_config2
[
0
]
=
au_readl
(
IC0_CFG2RD
);
sleep_intctl_src
[
0
]
=
au_readl
(
IC0_SRCRD
);
sleep_intctl_assign
[
0
]
=
au_readl
(
IC0_ASSIGNRD
);
sleep_intctl_wake
[
0
]
=
au_readl
(
IC0_WAKERD
);
sleep_intctl_mask
[
0
]
=
au_readl
(
IC0_MASKRD
);
sleep_intctl_config0
[
1
]
=
au_readl
(
IC1_CFG0RD
);
sleep_intctl_config1
[
1
]
=
au_readl
(
IC1_CFG1RD
);
sleep_intctl_config2
[
1
]
=
au_readl
(
IC1_CFG2RD
);
sleep_intctl_src
[
1
]
=
au_readl
(
IC1_SRCRD
);
sleep_intctl_assign
[
1
]
=
au_readl
(
IC1_ASSIGNRD
);
sleep_intctl_wake
[
1
]
=
au_readl
(
IC1_WAKERD
);
sleep_intctl_mask
[
1
]
=
au_readl
(
IC1_MASKRD
);
}
/*
* For most restore operations, we clear the entire register and
* then set the bits we found during the save.
*/
void
restore_au1xxx_intctl
(
void
)
{
au_writel
(
0xffffffff
,
IC0_MASKCLR
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_CFG0CLR
);
au_sync
();
au_writel
(
sleep_intctl_config0
[
0
],
IC0_CFG0SET
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_CFG1CLR
);
au_sync
();
au_writel
(
sleep_intctl_config1
[
0
],
IC0_CFG1SET
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_CFG2CLR
);
au_sync
();
au_writel
(
sleep_intctl_config2
[
0
],
IC0_CFG2SET
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_SRCCLR
);
au_sync
();
au_writel
(
sleep_intctl_src
[
0
],
IC0_SRCSET
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_ASSIGNCLR
);
au_sync
();
au_writel
(
sleep_intctl_assign
[
0
],
IC0_ASSIGNSET
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_WAKECLR
);
au_sync
();
au_writel
(
sleep_intctl_wake
[
0
],
IC0_WAKESET
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_RISINGCLR
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_FALLINGCLR
);
au_sync
();
au_writel
(
0x00000000
,
IC0_TESTBIT
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_MASKCLR
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_CFG0CLR
);
au_sync
();
au_writel
(
sleep_intctl_config0
[
1
],
IC1_CFG0SET
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_CFG1CLR
);
au_sync
();
au_writel
(
sleep_intctl_config1
[
1
],
IC1_CFG1SET
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_CFG2CLR
);
au_sync
();
au_writel
(
sleep_intctl_config2
[
1
],
IC1_CFG2SET
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_SRCCLR
);
au_sync
();
au_writel
(
sleep_intctl_src
[
1
],
IC1_SRCSET
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_ASSIGNCLR
);
au_sync
();
au_writel
(
sleep_intctl_assign
[
1
],
IC1_ASSIGNSET
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_WAKECLR
);
au_sync
();
au_writel
(
sleep_intctl_wake
[
1
],
IC1_WAKESET
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_RISINGCLR
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_FALLINGCLR
);
au_sync
();
au_writel
(
0x00000000
,
IC1_TESTBIT
);
au_sync
();
au_writel
(
sleep_intctl_mask
[
1
],
IC1_MASKSET
);
au_sync
();
au_writel
(
sleep_intctl_mask
[
0
],
IC0_MASKSET
);
au_sync
();
}
#endif
/* CONFIG_PM */
inline
void
local_enable_irq
(
unsigned
int
irq_nr
)
{
if
(
irq_nr
>
AU1000_LAST_INTC0_INT
)
{
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_MASKSET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_WAKESET
);
}
else
{
au_writel
(
1
<<
irq_nr
,
IC0_MASKSET
);
au_writel
(
1
<<
irq_nr
,
IC0_WAKESET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_MASKSET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_WAKESET
);
}
else
{
au_writel
(
1
<<
irq_nr
,
IC0_MASKSET
);
au_writel
(
1
<<
irq_nr
,
IC0_WAKESET
);
}
au_sync
();
}
...
...
@@ -87,12 +148,11 @@ inline void local_enable_irq(unsigned int irq_nr)
inline
void
local_disable_irq
(
unsigned
int
irq_nr
)
{
if
(
irq_nr
>
AU1000_LAST_INTC0_INT
)
{
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_MASKCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_WAKECLR
);
}
else
{
au_writel
(
1
<<
irq_nr
,
IC0_MASKCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_WAKECLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_MASKCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_WAKECLR
);
}
else
{
au_writel
(
1
<<
irq_nr
,
IC0_MASKCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_WAKECLR
);
}
au_sync
();
}
...
...
@@ -101,12 +161,11 @@ inline void local_disable_irq(unsigned int irq_nr)
static
inline
void
mask_and_ack_rise_edge_irq
(
unsigned
int
irq_nr
)
{
if
(
irq_nr
>
AU1000_LAST_INTC0_INT
)
{
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_RISINGCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_MASKCLR
);
}
else
{
au_writel
(
1
<<
irq_nr
,
IC0_RISINGCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_MASKCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_RISINGCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_MASKCLR
);
}
else
{
au_writel
(
1
<<
irq_nr
,
IC0_RISINGCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_MASKCLR
);
}
au_sync
();
}
...
...
@@ -115,12 +174,11 @@ static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr)
static
inline
void
mask_and_ack_fall_edge_irq
(
unsigned
int
irq_nr
)
{
if
(
irq_nr
>
AU1000_LAST_INTC0_INT
)
{
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_FALLINGCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_MASKCLR
);
}
else
{
au_writel
(
1
<<
irq_nr
,
IC0_FALLINGCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_MASKCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_FALLINGCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_MASKCLR
);
}
else
{
au_writel
(
1
<<
irq_nr
,
IC0_FALLINGCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_MASKCLR
);
}
au_sync
();
}
...
...
@@ -132,14 +190,13 @@ static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
* both edges at once, or if we do, that we don't care.
*/
if
(
irq_nr
>
AU1000_LAST_INTC0_INT
)
{
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_FALLINGCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_RISINGCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_MASKCLR
);
}
else
{
au_writel
(
1
<<
irq_nr
,
IC0_FALLINGCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_RISINGCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_MASKCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_FALLINGCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_RISINGCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_MASKCLR
);
}
else
{
au_writel
(
1
<<
irq_nr
,
IC0_FALLINGCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_RISINGCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_MASKCLR
);
}
au_sync
();
}
...
...
@@ -162,9 +219,9 @@ static inline void mask_and_ack_level_irq(unsigned int irq_nr)
static
void
end_irq
(
unsigned
int
irq_nr
)
{
if
(
!
(
irq_desc
[
irq_nr
].
status
&
(
IRQ_DISABLED
|
IRQ_INPROGRESS
)))
{
if
(
!
(
irq_desc
[
irq_nr
].
status
&
(
IRQ_DISABLED
|
IRQ_INPROGRESS
)))
local_enable_irq
(
irq_nr
);
}
#if defined(CONFIG_MIPS_PB1000)
if
(
irq_nr
==
AU1000_GPIO_15
)
{
au_writel
(
0x4000
,
PB1000_MDR
);
/* enable int */
...
...
@@ -181,15 +238,12 @@ unsigned long save_local_and_disable(int controller)
spin_lock_irqsave
(
&
irq_lock
,
flags
);
if
(
controller
)
{
mask
=
au_readl
(
IC1_MASKSET
);
for
(
i
=
32
;
i
<
64
;
i
++
)
{
for
(
i
=
32
;
i
<
64
;
i
++
)
local_disable_irq
(
i
);
}
}
else
{
}
else
{
mask
=
au_readl
(
IC0_MASKSET
);
for
(
i
=
0
;
i
<
32
;
i
++
)
{
for
(
i
=
0
;
i
<
32
;
i
++
)
local_disable_irq
(
i
);
}
}
spin_unlock_irqrestore
(
&
irq_lock
,
flags
);
...
...
@@ -202,10 +256,10 @@ void restore_local_and_enable(int controller, unsigned long mask)
unsigned
long
flags
,
new_mask
;
spin_lock_irqsave
(
&
irq_lock
,
flags
);
for
(
i
=
0
;
i
<
32
;
i
++
)
{
if
(
mask
&
(
1
<<
i
))
{
for
(
i
=
0
;
i
<
32
;
i
++
)
{
if
(
mask
&
(
1
<<
i
))
{
if
(
controller
)
local_enable_irq
(
i
+
32
);
local_enable_irq
(
i
+
32
);
else
local_enable_irq
(
i
);
}
...
...
@@ -220,39 +274,39 @@ void restore_local_and_enable(int controller, unsigned long mask)
static
struct
irq_chip
rise_edge_irq_type
=
{
.
name
=
"Au1000 Rise Edge"
,
.
ack
=
mask_and_ack_rise_edge_irq
,
.
mask
=
local_disable_irq
,
.
mask_ack
=
mask_and_ack_rise_edge_irq
,
.
unmask
=
local_enable_irq
,
.
end
=
end_irq
,
.
name
=
"Au1000 Rise Edge"
,
.
ack
=
mask_and_ack_rise_edge_irq
,
.
mask
=
local_disable_irq
,
.
mask_ack
=
mask_and_ack_rise_edge_irq
,
.
unmask
=
local_enable_irq
,
.
end
=
end_irq
,
};
static
struct
irq_chip
fall_edge_irq_type
=
{
.
name
=
"Au1000 Fall Edge"
,
.
ack
=
mask_and_ack_fall_edge_irq
,
.
mask
=
local_disable_irq
,
.
mask_ack
=
mask_and_ack_fall_edge_irq
,
.
unmask
=
local_enable_irq
,
.
end
=
end_irq
,
.
name
=
"Au1000 Fall Edge"
,
.
ack
=
mask_and_ack_fall_edge_irq
,
.
mask
=
local_disable_irq
,
.
mask_ack
=
mask_and_ack_fall_edge_irq
,
.
unmask
=
local_enable_irq
,
.
end
=
end_irq
,
};
static
struct
irq_chip
either_edge_irq_type
=
{
.
name
=
"Au1000 Rise or Fall Edge"
,
.
ack
=
mask_and_ack_either_edge_irq
,
.
mask
=
local_disable_irq
,
.
mask_ack
=
mask_and_ack_either_edge_irq
,
.
unmask
=
local_enable_irq
,
.
end
=
end_irq
,
.
name
=
"Au1000 Rise or Fall Edge"
,
.
ack
=
mask_and_ack_either_edge_irq
,
.
mask
=
local_disable_irq
,
.
mask_ack
=
mask_and_ack_either_edge_irq
,
.
unmask
=
local_enable_irq
,
.
end
=
end_irq
,
};
static
struct
irq_chip
level_irq_type
=
{
.
name
=
"Au1000 Level"
,
.
ack
=
mask_and_ack_level_irq
,
.
mask
=
local_disable_irq
,
.
mask_ack
=
mask_and_ack_level_irq
,
.
unmask
=
local_enable_irq
,
.
end
=
end_irq
,
.
name
=
"Au1000 Level"
,
.
ack
=
mask_and_ack_level_irq
,
.
mask
=
local_disable_irq
,
.
mask_ack
=
mask_and_ack_level_irq
,
.
unmask
=
local_enable_irq
,
.
end
=
end_irq
,
};
#ifdef CONFIG_PM
...
...
@@ -263,7 +317,8 @@ void startup_match20_interrupt(irq_handler_t handler)
static
struct
irqaction
action
;
memset
(
&
action
,
0
,
sizeof
(
struct
irqaction
));
/* This is a big problem.... since we didn't use request_irq
/*
* This is a big problem.... since we didn't use request_irq
* when kernel/irq.c calls probe_irq_xxx this interrupt will
* be probed for usage. This will end up disabling the device :(
* Give it a bogus "action" pointer -- this will keep it from
...
...
@@ -292,173 +347,112 @@ static void setup_local_irq(unsigned int irq_nr, int type, int int_req)
/* Config2[n], Config1[n], Config0[n] */
if
(
irq_nr
>
AU1000_LAST_INTC0_INT
)
{
switch
(
type
)
{
case
INTC_INT_RISE_EDGE
:
/* 0:0:1 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0SET
);
set_irq_chip
(
irq_nr
,
&
rise_edge_irq_type
);
break
;
case
INTC_INT_FALL_EDGE
:
/* 0:1:0 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1SET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0CLR
);
set_irq_chip
(
irq_nr
,
&
fall_edge_irq_type
);
break
;
case
INTC_INT_RISE_AND_FALL_EDGE
:
/* 0:1:1 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1SET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0SET
);
set_irq_chip
(
irq_nr
,
&
either_edge_irq_type
);
break
;
case
INTC_INT_HIGH_LEVEL
:
/* 1:0:1 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2SET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0SET
);
set_irq_chip
(
irq_nr
,
&
level_irq_type
);
break
;
case
INTC_INT_LOW_LEVEL
:
/* 1:1:0 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2SET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1SET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0CLR
);
set_irq_chip
(
irq_nr
,
&
level_irq_type
);
break
;
case
INTC_INT_DISABLED
:
/* 0:0:0 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2CLR
);
break
;
default:
/* disable the interrupt */
printk
(
"unexpected int type %d (irq %d)
\n
"
,
type
,
irq_nr
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2CLR
);
return
;
case
INTC_INT_RISE_EDGE
:
/* 0:0:1 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0SET
);
set_irq_chip
(
irq_nr
,
&
rise_edge_irq_type
);
break
;
case
INTC_INT_FALL_EDGE
:
/* 0:1:0 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1SET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0CLR
);
set_irq_chip
(
irq_nr
,
&
fall_edge_irq_type
);
break
;
case
INTC_INT_RISE_AND_FALL_EDGE
:
/* 0:1:1 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1SET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0SET
);
set_irq_chip
(
irq_nr
,
&
either_edge_irq_type
);
break
;
case
INTC_INT_HIGH_LEVEL
:
/* 1:0:1 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2SET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0SET
);
set_irq_chip
(
irq_nr
,
&
level_irq_type
);
break
;
case
INTC_INT_LOW_LEVEL
:
/* 1:1:0 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2SET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1SET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0CLR
);
set_irq_chip
(
irq_nr
,
&
level_irq_type
);
break
;
case
INTC_INT_DISABLED
:
/* 0:0:0 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2CLR
);
break
;
default:
/* disable the interrupt */
printk
(
KERN_WARNING
"unexpected int type %d (irq %d)
\n
"
,
type
,
irq_nr
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG0CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG1CLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_CFG2CLR
);
return
;
}
if
(
int_req
)
/* assign to interrupt request 1 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_ASSIGNCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_ASSIGNCLR
);
else
/* assign to interrupt request 0 */
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_ASSIGNSET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_SRCSET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_MASKCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_WAKECLR
);
}
else
{
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_ASSIGNSET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_SRCSET
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_MASKCLR
);
au_writel
(
1
<<
(
irq_nr
-
32
),
IC1_WAKECLR
);
}
else
{
switch
(
type
)
{
case
INTC_INT_RISE_EDGE
:
/* 0:0:1 */
au_writel
(
1
<<
irq_nr
,
IC0_CFG2CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG0SET
);
set_irq_chip
(
irq_nr
,
&
rise_edge_irq_type
);
break
;
case
INTC_INT_FALL_EDGE
:
/* 0:1:0 */
au_writel
(
1
<<
irq_nr
,
IC0_CFG2CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1SET
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG0CLR
);
set_irq_chip
(
irq_nr
,
&
fall_edge_irq_type
);
break
;
case
INTC_INT_RISE_AND_FALL_EDGE
:
/* 0:1:1 */
au_writel
(
1
<<
irq_nr
,
IC0_CFG2CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1SET
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG0SET
);
set_irq_chip
(
irq_nr
,
&
either_edge_irq_type
);
break
;
case
INTC_INT_HIGH_LEVEL
:
/* 1:0:1 */
au_writel
(
1
<<
irq_nr
,
IC0_CFG2SET
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG0SET
);
set_irq_chip
(
irq_nr
,
&
level_irq_type
);
break
;
case
INTC_INT_LOW_LEVEL
:
/* 1:1:0 */
au_writel
(
1
<<
irq_nr
,
IC0_CFG2SET
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1SET
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG0CLR
);
set_irq_chip
(
irq_nr
,
&
level_irq_type
);
break
;
case
INTC_INT_DISABLED
:
/* 0:0:0 */
au_writel
(
1
<<
irq_nr
,
IC0_CFG0CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG2CLR
);
break
;
default:
/* disable the interrupt */
printk
(
"unexpected int type %d (irq %d)
\n
"
,
type
,
irq_nr
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG0CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG2CLR
);
return
;
case
INTC_INT_RISE_EDGE
:
/* 0:0:1 */
au_writel
(
1
<<
irq_nr
,
IC0_CFG2CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG0SET
);
set_irq_chip
(
irq_nr
,
&
rise_edge_irq_type
);
break
;
case
INTC_INT_FALL_EDGE
:
/* 0:1:0 */
au_writel
(
1
<<
irq_nr
,
IC0_CFG2CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1SET
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG0CLR
);
set_irq_chip
(
irq_nr
,
&
fall_edge_irq_type
);
break
;
case
INTC_INT_RISE_AND_FALL_EDGE
:
/* 0:1:1 */
au_writel
(
1
<<
irq_nr
,
IC0_CFG2CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1SET
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG0SET
);
set_irq_chip
(
irq_nr
,
&
either_edge_irq_type
);
break
;
case
INTC_INT_HIGH_LEVEL
:
/* 1:0:1 */
au_writel
(
1
<<
irq_nr
,
IC0_CFG2SET
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG0SET
);
set_irq_chip
(
irq_nr
,
&
level_irq_type
);
break
;
case
INTC_INT_LOW_LEVEL
:
/* 1:1:0 */
au_writel
(
1
<<
irq_nr
,
IC0_CFG2SET
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1SET
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG0CLR
);
set_irq_chip
(
irq_nr
,
&
level_irq_type
);
break
;
case
INTC_INT_DISABLED
:
/* 0:0:0 */
au_writel
(
1
<<
irq_nr
,
IC0_CFG0CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG2CLR
);
break
;
default:
/* disable the interrupt */
printk
(
KERN_WARNING
"unexpected int type %d (irq %d)
\n
"
,
type
,
irq_nr
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG0CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG1CLR
);
au_writel
(
1
<<
irq_nr
,
IC0_CFG2CLR
);
return
;
}
if
(
int_req
)
/* assign to interrupt request 1 */
au_writel
(
1
<<
irq_nr
,
IC0_ASSIGNCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_ASSIGNCLR
);
else
/* assign to interrupt request 0 */
au_writel
(
1
<<
irq_nr
,
IC0_ASSIGNSET
);
au_writel
(
1
<<
irq_nr
,
IC0_SRCSET
);
au_writel
(
1
<<
irq_nr
,
IC0_MASKCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_WAKECLR
);
au_writel
(
1
<<
irq_nr
,
IC0_ASSIGNSET
);
au_writel
(
1
<<
irq_nr
,
IC0_SRCSET
);
au_writel
(
1
<<
irq_nr
,
IC0_MASKCLR
);
au_writel
(
1
<<
irq_nr
,
IC0_WAKECLR
);
}
au_sync
();
}
void
__init
arch_init_irq
(
void
)
{
int
i
;
unsigned
long
cp0_status
;
au1xxx_irq_map_t
*
imp
;
extern
au1xxx_irq_map_t
au1xxx_irq_map
[];
extern
au1xxx_irq_map_t
au1xxx_ic0_map
[];
extern
int
au1xxx_nr_irqs
;
extern
int
au1xxx_ic0_nr_irqs
;
cp0_status
=
read_c0_status
();
/* Initialize interrupt controllers to a safe state.
*/
au_writel
(
0xffffffff
,
IC0_CFG0CLR
);
au_writel
(
0xffffffff
,
IC0_CFG1CLR
);
au_writel
(
0xffffffff
,
IC0_CFG2CLR
);
au_writel
(
0xffffffff
,
IC0_MASKCLR
);
au_writel
(
0xffffffff
,
IC0_ASSIGNSET
);
au_writel
(
0xffffffff
,
IC0_WAKECLR
);
au_writel
(
0xffffffff
,
IC0_SRCSET
);
au_writel
(
0xffffffff
,
IC0_FALLINGCLR
);
au_writel
(
0xffffffff
,
IC0_RISINGCLR
);
au_writel
(
0x00000000
,
IC0_TESTBIT
);
au_writel
(
0xffffffff
,
IC1_CFG0CLR
);
au_writel
(
0xffffffff
,
IC1_CFG1CLR
);
au_writel
(
0xffffffff
,
IC1_CFG2CLR
);
au_writel
(
0xffffffff
,
IC1_MASKCLR
);
au_writel
(
0xffffffff
,
IC1_ASSIGNSET
);
au_writel
(
0xffffffff
,
IC1_WAKECLR
);
au_writel
(
0xffffffff
,
IC1_SRCSET
);
au_writel
(
0xffffffff
,
IC1_FALLINGCLR
);
au_writel
(
0xffffffff
,
IC1_RISINGCLR
);
au_writel
(
0x00000000
,
IC1_TESTBIT
);
/* Initialize IC0, which is fixed per processor.
*/
imp
=
au1xxx_ic0_map
;
for
(
i
=
0
;
i
<
au1xxx_ic0_nr_irqs
;
i
++
)
{
setup_local_irq
(
imp
->
im_irq
,
imp
->
im_type
,
imp
->
im_request
);
imp
++
;
}
/* Now set up the irq mapping for the board.
*/
imp
=
au1xxx_irq_map
;
for
(
i
=
0
;
i
<
au1xxx_nr_irqs
;
i
++
)
{
setup_local_irq
(
imp
->
im_irq
,
imp
->
im_type
,
imp
->
im_request
);
imp
++
;
}
set_c0_status
(
ALLINTS
);
/* Board specific IRQ initialization.
*/
if
(
board_init_irq
)
(
*
board_init_irq
)();
}
/*
* Interrupts are nested. Even if an interrupt handler is registered
* as "fast", we might get another interrupt before we return from
...
...
@@ -468,26 +462,27 @@ void __init arch_init_irq(void)
static
void
intc0_req0_irqdispatch
(
void
)
{
int
irq
=
0
;
static
unsigned
long
intc0_req0
=
0
;
static
unsigned
long
intc0_req0
;
intc0_req0
|=
au_readl
(
IC0_REQ0INT
);
if
(
!
intc0_req0
)
return
;
#ifdef AU1000_USB_DEV_REQ_INT
/*
* Because of the tight timing of SETUP token to reply
* transactions, the USB devices-side packet complete
* interrupt needs the highest priority.
*/
if
((
intc0_req0
&
(
1
<<
AU1000_USB_DEV_REQ_INT
)))
{
intc0_req0
&=
~
(
1
<<
AU1000_USB_DEV_REQ_INT
);
if
((
intc0_req0
&
(
1
<<
AU1000_USB_DEV_REQ_INT
)))
{
intc0_req0
&=
~
(
1
<<
AU1000_USB_DEV_REQ_INT
);
do_IRQ
(
AU1000_USB_DEV_REQ_INT
);
return
;
}
#endif
irq
=
au_ffs
(
intc0_req0
)
-
1
;
intc0_req0
&=
~
(
1
<<
irq
);
intc0_req0
&=
~
(
1
<<
irq
);
do_IRQ
(
irq
);
}
...
...
@@ -495,7 +490,7 @@ static void intc0_req0_irqdispatch(void)
static
void
intc0_req1_irqdispatch
(
void
)
{
int
irq
=
0
;
static
unsigned
long
intc0_req1
=
0
;
static
unsigned
long
intc0_req1
;
intc0_req1
|=
au_readl
(
IC0_REQ1INT
);
...
...
@@ -503,7 +498,7 @@ static void intc0_req1_irqdispatch(void)
return
;
irq
=
au_ffs
(
intc0_req1
)
-
1
;
intc0_req1
&=
~
(
1
<<
irq
);
intc0_req1
&=
~
(
1
<<
irq
);
do_IRQ
(
irq
);
}
...
...
@@ -515,7 +510,7 @@ static void intc0_req1_irqdispatch(void)
static
void
intc1_req0_irqdispatch
(
void
)
{
int
irq
=
0
;
static
unsigned
long
intc1_req0
=
0
;
static
unsigned
long
intc1_req0
;
intc1_req0
|=
au_readl
(
IC1_REQ0INT
);
...
...
@@ -523,7 +518,7 @@ static void intc1_req0_irqdispatch(void)
return
;
irq
=
au_ffs
(
intc1_req0
)
-
1
;
intc1_req0
&=
~
(
1
<<
irq
);
intc1_req0
&=
~
(
1
<<
irq
);
irq
+=
32
;
do_IRQ
(
irq
);
}
...
...
@@ -532,7 +527,7 @@ static void intc1_req0_irqdispatch(void)
static
void
intc1_req1_irqdispatch
(
void
)
{
int
irq
=
0
;
static
unsigned
long
intc1_req1
=
0
;
static
unsigned
long
intc1_req1
;
intc1_req1
|=
au_readl
(
IC1_REQ1INT
);
...
...
@@ -540,94 +535,11 @@ static void intc1_req1_irqdispatch(void)
return
;
irq
=
au_ffs
(
intc1_req1
)
-
1
;
intc1_req1
&=
~
(
1
<<
irq
);
intc1_req1
&=
~
(
1
<<
irq
);
irq
+=
32
;
do_IRQ
(
irq
);
}
#ifdef CONFIG_PM
/* Save/restore the interrupt controller state.
* Called from the save/restore core registers as part of the
* au_sleep function in power.c.....maybe I should just pm_register()
* them instead?
*/
static
unsigned
int
sleep_intctl_config0
[
2
];
static
unsigned
int
sleep_intctl_config1
[
2
];
static
unsigned
int
sleep_intctl_config2
[
2
];
static
unsigned
int
sleep_intctl_src
[
2
];
static
unsigned
int
sleep_intctl_assign
[
2
];
static
unsigned
int
sleep_intctl_wake
[
2
];
static
unsigned
int
sleep_intctl_mask
[
2
];
void
save_au1xxx_intctl
(
void
)
{
sleep_intctl_config0
[
0
]
=
au_readl
(
IC0_CFG0RD
);
sleep_intctl_config1
[
0
]
=
au_readl
(
IC0_CFG1RD
);
sleep_intctl_config2
[
0
]
=
au_readl
(
IC0_CFG2RD
);
sleep_intctl_src
[
0
]
=
au_readl
(
IC0_SRCRD
);
sleep_intctl_assign
[
0
]
=
au_readl
(
IC0_ASSIGNRD
);
sleep_intctl_wake
[
0
]
=
au_readl
(
IC0_WAKERD
);
sleep_intctl_mask
[
0
]
=
au_readl
(
IC0_MASKRD
);
sleep_intctl_config0
[
1
]
=
au_readl
(
IC1_CFG0RD
);
sleep_intctl_config1
[
1
]
=
au_readl
(
IC1_CFG1RD
);
sleep_intctl_config2
[
1
]
=
au_readl
(
IC1_CFG2RD
);
sleep_intctl_src
[
1
]
=
au_readl
(
IC1_SRCRD
);
sleep_intctl_assign
[
1
]
=
au_readl
(
IC1_ASSIGNRD
);
sleep_intctl_wake
[
1
]
=
au_readl
(
IC1_WAKERD
);
sleep_intctl_mask
[
1
]
=
au_readl
(
IC1_MASKRD
);
}
/* For most restore operations, we clear the entire register and
* then set the bits we found during the save.
*/
void
restore_au1xxx_intctl
(
void
)
{
au_writel
(
0xffffffff
,
IC0_MASKCLR
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_CFG0CLR
);
au_sync
();
au_writel
(
sleep_intctl_config0
[
0
],
IC0_CFG0SET
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_CFG1CLR
);
au_sync
();
au_writel
(
sleep_intctl_config1
[
0
],
IC0_CFG1SET
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_CFG2CLR
);
au_sync
();
au_writel
(
sleep_intctl_config2
[
0
],
IC0_CFG2SET
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_SRCCLR
);
au_sync
();
au_writel
(
sleep_intctl_src
[
0
],
IC0_SRCSET
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_ASSIGNCLR
);
au_sync
();
au_writel
(
sleep_intctl_assign
[
0
],
IC0_ASSIGNSET
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_WAKECLR
);
au_sync
();
au_writel
(
sleep_intctl_wake
[
0
],
IC0_WAKESET
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_RISINGCLR
);
au_sync
();
au_writel
(
0xffffffff
,
IC0_FALLINGCLR
);
au_sync
();
au_writel
(
0x00000000
,
IC0_TESTBIT
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_MASKCLR
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_CFG0CLR
);
au_sync
();
au_writel
(
sleep_intctl_config0
[
1
],
IC1_CFG0SET
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_CFG1CLR
);
au_sync
();
au_writel
(
sleep_intctl_config1
[
1
],
IC1_CFG1SET
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_CFG2CLR
);
au_sync
();
au_writel
(
sleep_intctl_config2
[
1
],
IC1_CFG2SET
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_SRCCLR
);
au_sync
();
au_writel
(
sleep_intctl_src
[
1
],
IC1_SRCSET
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_ASSIGNCLR
);
au_sync
();
au_writel
(
sleep_intctl_assign
[
1
],
IC1_ASSIGNSET
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_WAKECLR
);
au_sync
();
au_writel
(
sleep_intctl_wake
[
1
],
IC1_WAKESET
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_RISINGCLR
);
au_sync
();
au_writel
(
0xffffffff
,
IC1_FALLINGCLR
);
au_sync
();
au_writel
(
0x00000000
,
IC1_TESTBIT
);
au_sync
();
au_writel
(
sleep_intctl_mask
[
1
],
IC1_MASKSET
);
au_sync
();
au_writel
(
sleep_intctl_mask
[
0
],
IC0_MASKSET
);
au_sync
();
}
#endif
/* CONFIG_PM */
asmlinkage
void
plat_irq_dispatch
(
void
)
{
unsigned
int
pending
=
read_c0_status
()
&
read_c0_cause
()
&
ST0_IM
;
...
...
@@ -645,3 +557,63 @@ asmlinkage void plat_irq_dispatch(void)
else
spurious_interrupt
();
}
void
__init
arch_init_irq
(
void
)
{
int
i
;
unsigned
long
cp0_status
;
au1xxx_irq_map_t
*
imp
;
extern
au1xxx_irq_map_t
au1xxx_irq_map
[];
extern
au1xxx_irq_map_t
au1xxx_ic0_map
[];
extern
int
au1xxx_nr_irqs
;
extern
int
au1xxx_ic0_nr_irqs
;
cp0_status
=
read_c0_status
();
/* Initialize interrupt controllers to a safe state.
*/
au_writel
(
0xffffffff
,
IC0_CFG0CLR
);
au_writel
(
0xffffffff
,
IC0_CFG1CLR
);
au_writel
(
0xffffffff
,
IC0_CFG2CLR
);
au_writel
(
0xffffffff
,
IC0_MASKCLR
);
au_writel
(
0xffffffff
,
IC0_ASSIGNSET
);
au_writel
(
0xffffffff
,
IC0_WAKECLR
);
au_writel
(
0xffffffff
,
IC0_SRCSET
);
au_writel
(
0xffffffff
,
IC0_FALLINGCLR
);
au_writel
(
0xffffffff
,
IC0_RISINGCLR
);
au_writel
(
0x00000000
,
IC0_TESTBIT
);
au_writel
(
0xffffffff
,
IC1_CFG0CLR
);
au_writel
(
0xffffffff
,
IC1_CFG1CLR
);
au_writel
(
0xffffffff
,
IC1_CFG2CLR
);
au_writel
(
0xffffffff
,
IC1_MASKCLR
);
au_writel
(
0xffffffff
,
IC1_ASSIGNSET
);
au_writel
(
0xffffffff
,
IC1_WAKECLR
);
au_writel
(
0xffffffff
,
IC1_SRCSET
);
au_writel
(
0xffffffff
,
IC1_FALLINGCLR
);
au_writel
(
0xffffffff
,
IC1_RISINGCLR
);
au_writel
(
0x00000000
,
IC1_TESTBIT
);
/* Initialize IC0, which is fixed per processor.
*/
imp
=
au1xxx_ic0_map
;
for
(
i
=
0
;
i
<
au1xxx_ic0_nr_irqs
;
i
++
)
{
setup_local_irq
(
imp
->
im_irq
,
imp
->
im_type
,
imp
->
im_request
);
imp
++
;
}
/* Now set up the irq mapping for the board.
*/
imp
=
au1xxx_irq_map
;
for
(
i
=
0
;
i
<
au1xxx_nr_irqs
;
i
++
)
{
setup_local_irq
(
imp
->
im_irq
,
imp
->
im_type
,
imp
->
im_request
);
imp
++
;
}
set_c0_status
(
ALLINTS
);
/* Board specific IRQ initialization.
*/
if
(
board_init_irq
)
(
*
board_init_irq
)();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment