Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
5e8bd41a
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
5e8bd41a
编写于
6月 10, 2013
作者:
G
Grant Likely
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'tip/irq/for-arm' into irqdomain/next
上级
317ddd25
e8bd834f
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
316 addition
and
50 deletion
+316
-50
include/linux/irq.h
include/linux/irq.h
+46
-1
include/linux/irqdomain.h
include/linux/irqdomain.h
+12
-0
kernel/irq/generic-chip.c
kernel/irq/generic-chip.c
+258
-43
kernel/irq/irqdomain.c
kernel/irq/irqdomain.c
+0
-6
未找到文件。
include/linux/irq.h
浏览文件 @
5e8bd41a
...
...
@@ -119,6 +119,7 @@ struct irq_domain;
/**
* struct irq_data - per irq and irq chip data passed down to chip functions
* @mask: precomputed bitmask for accessing the chip registers
* @irq: interrupt number
* @hwirq: hardware interrupt number, local to the interrupt domain
* @node: node index useful for balancing
...
...
@@ -138,6 +139,7 @@ struct irq_domain;
* irq_data.
*/
struct
irq_data
{
u32
mask
;
unsigned
int
irq
;
unsigned
long
hwirq
;
unsigned
int
node
;
...
...
@@ -294,6 +296,7 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
* @irq_suspend: function called from core code on suspend once per chip
* @irq_resume: function called from core code on resume once per chip
* @irq_pm_shutdown: function called from core code on shutdown once per chip
* @irq_calc_mask: Optional function to set irq_data.mask for special cases
* @irq_print_chip: optional to print special chip info in show_interrupts
* @flags: chip specific flags
*/
...
...
@@ -325,6 +328,8 @@ struct irq_chip {
void
(
*
irq_resume
)(
struct
irq_data
*
data
);
void
(
*
irq_pm_shutdown
)(
struct
irq_data
*
data
);
void
(
*
irq_calc_mask
)(
struct
irq_data
*
data
);
void
(
*
irq_print_chip
)(
struct
irq_data
*
data
,
struct
seq_file
*
p
);
unsigned
long
flags
;
...
...
@@ -644,6 +649,8 @@ struct irq_chip_regs {
* @regs: Register offsets for this chip
* @handler: Flow handler associated with this chip
* @type: Chip can handle these flow types
* @mask_cache_priv: Cached mask register private to the chip type
* @mask_cache: Pointer to cached mask register
*
* A irq_generic_chip can have several instances of irq_chip_type when
* it requires different functions and register offsets for different
...
...
@@ -654,6 +661,8 @@ struct irq_chip_type {
struct
irq_chip_regs
regs
;
irq_flow_handler_t
handler
;
u32
type
;
u32
mask_cache_priv
;
u32
*
mask_cache
;
};
/**
...
...
@@ -662,13 +671,16 @@ struct irq_chip_type {
* @reg_base: Register base address (virtual)
* @irq_base: Interrupt base nr for this chip
* @irq_cnt: Number of interrupts handled by this chip
* @mask_cache: Cached mask register
* @mask_cache: Cached mask register
shared between all chip types
* @type_cache: Cached type register
* @polarity_cache: Cached polarity register
* @wake_enabled: Interrupt can wakeup from suspend
* @wake_active: Interrupt is marked as an wakeup from suspend source
* @num_ct: Number of available irq_chip_type instances (usually 1)
* @private: Private data for non generic chip callbacks
* @installed: bitfield to denote installed interrupts
* @unused: bitfield to denote unused interrupts
* @domain: irq domain pointer
* @list: List head for keeping track of instances
* @chip_types: Array of interrupt irq_chip_types
*
...
...
@@ -690,6 +702,9 @@ struct irq_chip_generic {
u32
wake_active
;
unsigned
int
num_ct
;
void
*
private
;
unsigned
long
installed
;
unsigned
long
unused
;
struct
irq_domain
*
domain
;
struct
list_head
list
;
struct
irq_chip_type
chip_types
[
0
];
};
...
...
@@ -700,10 +715,32 @@ struct irq_chip_generic {
* @IRQ_GC_INIT_NESTED_LOCK: Set the lock class of the irqs to nested for
* irq chips which need to call irq_set_wake() on
* the parent irq. Usually GPIO implementations
* @IRQ_GC_MASK_CACHE_PER_TYPE: Mask cache is chip type private
* @IRQ_GC_NO_MASK: Do not calculate irq_data->mask
*/
enum
irq_gc_flags
{
IRQ_GC_INIT_MASK_CACHE
=
1
<<
0
,
IRQ_GC_INIT_NESTED_LOCK
=
1
<<
1
,
IRQ_GC_MASK_CACHE_PER_TYPE
=
1
<<
2
,
IRQ_GC_NO_MASK
=
1
<<
3
,
};
/*
* struct irq_domain_chip_generic - Generic irq chip data structure for irq domains
* @irqs_per_chip: Number of interrupts per chip
* @num_chips: Number of chips
* @irq_flags_to_set: IRQ* flags to set on irq setup
* @irq_flags_to_clear: IRQ* flags to clear on irq setup
* @gc_flags: Generic chip specific setup flags
* @gc: Array of pointers to generic interrupt chips
*/
struct
irq_domain_chip_generic
{
unsigned
int
irqs_per_chip
;
unsigned
int
num_chips
;
unsigned
int
irq_flags_to_clear
;
unsigned
int
irq_flags_to_set
;
enum
irq_gc_flags
gc_flags
;
struct
irq_chip_generic
*
gc
[
0
];
};
/* Generic chip callback functions */
...
...
@@ -729,6 +766,14 @@ int irq_setup_alt_chip(struct irq_data *d, unsigned int type);
void
irq_remove_generic_chip
(
struct
irq_chip_generic
*
gc
,
u32
msk
,
unsigned
int
clr
,
unsigned
int
set
);
struct
irq_chip_generic
*
irq_get_domain_generic_chip
(
struct
irq_domain
*
d
,
unsigned
int
hw_irq
);
int
irq_alloc_domain_generic_chips
(
struct
irq_domain
*
d
,
int
irqs_per_chip
,
int
num_ct
,
const
char
*
name
,
irq_flow_handler_t
handler
,
unsigned
int
clr
,
unsigned
int
set
,
enum
irq_gc_flags
flags
);
static
inline
struct
irq_chip_type
*
irq_data_get_chip_type
(
struct
irq_data
*
d
)
{
return
container_of
(
d
->
chip
,
struct
irq_chip_type
,
chip
);
...
...
include/linux/irqdomain.h
浏览文件 @
5e8bd41a
...
...
@@ -66,6 +66,10 @@ struct irq_domain_ops {
unsigned
long
*
out_hwirq
,
unsigned
int
*
out_type
);
};
extern
struct
irq_domain_ops
irq_generic_chip_ops
;
struct
irq_domain_chip_generic
;
/**
* struct irq_domain - Hardware interrupt number translation object
* @link: Element in global irq_domain list.
...
...
@@ -109,8 +113,16 @@ struct irq_domain {
/* Optional device node pointer */
struct
device_node
*
of_node
;
/* Optional pointer to generic interrupt chips */
struct
irq_domain_chip_generic
*
gc
;
};
#define IRQ_DOMAIN_MAP_LEGACY 0
/* driver allocated fixed range of irqs.
* ie. legacy 8259, gets irqs 1..15 */
#define IRQ_DOMAIN_MAP_NOMAP 1
/* no fast reverse mapping */
#define IRQ_DOMAIN_MAP_LINEAR 2
/* linear map of interrupts */
#define IRQ_DOMAIN_MAP_TREE 3
/* radix tree */
#ifdef CONFIG_IRQ_DOMAIN
struct
irq_domain
*
irq_domain_add_simple
(
struct
device_node
*
of_node
,
unsigned
int
size
,
...
...
kernel/irq/generic-chip.c
浏览文件 @
5e8bd41a
...
...
@@ -7,6 +7,7 @@
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/irqdomain.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/syscore_ops.h>
...
...
@@ -16,11 +17,6 @@
static
LIST_HEAD
(
gc_list
);
static
DEFINE_RAW_SPINLOCK
(
gc_lock
);
static
inline
struct
irq_chip_regs
*
cur_regs
(
struct
irq_data
*
d
)
{
return
&
container_of
(
d
->
chip
,
struct
irq_chip_type
,
chip
)
->
regs
;
}
/**
* irq_gc_noop - NOOP function
* @d: irq_data
...
...
@@ -39,11 +35,12 @@ void irq_gc_noop(struct irq_data *d)
void
irq_gc_mask_disable_reg
(
struct
irq_data
*
d
)
{
struct
irq_chip_generic
*
gc
=
irq_data_get_irq_chip_data
(
d
);
u32
mask
=
1
<<
(
d
->
irq
-
gc
->
irq_base
);
struct
irq_chip_type
*
ct
=
irq_data_get_chip_type
(
d
);
u32
mask
=
d
->
mask
;
irq_gc_lock
(
gc
);
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
ur_regs
(
d
)
->
disable
);
gc
->
mask_cache
&=
~
mask
;
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
t
->
regs
.
disable
);
*
ct
->
mask_cache
&=
~
mask
;
irq_gc_unlock
(
gc
);
}
...
...
@@ -57,11 +54,12 @@ void irq_gc_mask_disable_reg(struct irq_data *d)
void
irq_gc_mask_set_bit
(
struct
irq_data
*
d
)
{
struct
irq_chip_generic
*
gc
=
irq_data_get_irq_chip_data
(
d
);
u32
mask
=
1
<<
(
d
->
irq
-
gc
->
irq_base
);
struct
irq_chip_type
*
ct
=
irq_data_get_chip_type
(
d
);
u32
mask
=
d
->
mask
;
irq_gc_lock
(
gc
);
gc
->
mask_cache
|=
mask
;
irq_reg_writel
(
gc
->
mask_cache
,
gc
->
reg_base
+
cur_regs
(
d
)
->
mask
);
*
ct
->
mask_cache
|=
mask
;
irq_reg_writel
(
*
ct
->
mask_cache
,
gc
->
reg_base
+
ct
->
regs
.
mask
);
irq_gc_unlock
(
gc
);
}
...
...
@@ -75,11 +73,12 @@ void irq_gc_mask_set_bit(struct irq_data *d)
void
irq_gc_mask_clr_bit
(
struct
irq_data
*
d
)
{
struct
irq_chip_generic
*
gc
=
irq_data_get_irq_chip_data
(
d
);
u32
mask
=
1
<<
(
d
->
irq
-
gc
->
irq_base
);
struct
irq_chip_type
*
ct
=
irq_data_get_chip_type
(
d
);
u32
mask
=
d
->
mask
;
irq_gc_lock
(
gc
);
gc
->
mask_cache
&=
~
mask
;
irq_reg_writel
(
gc
->
mask_cache
,
gc
->
reg_base
+
cur_regs
(
d
)
->
mask
);
*
ct
->
mask_cache
&=
~
mask
;
irq_reg_writel
(
*
ct
->
mask_cache
,
gc
->
reg_base
+
ct
->
regs
.
mask
);
irq_gc_unlock
(
gc
);
}
...
...
@@ -93,11 +92,12 @@ void irq_gc_mask_clr_bit(struct irq_data *d)
void
irq_gc_unmask_enable_reg
(
struct
irq_data
*
d
)
{
struct
irq_chip_generic
*
gc
=
irq_data_get_irq_chip_data
(
d
);
u32
mask
=
1
<<
(
d
->
irq
-
gc
->
irq_base
);
struct
irq_chip_type
*
ct
=
irq_data_get_chip_type
(
d
);
u32
mask
=
d
->
mask
;
irq_gc_lock
(
gc
);
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
ur_regs
(
d
)
->
enable
);
gc
->
mask_cache
|=
mask
;
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
t
->
regs
.
enable
);
*
ct
->
mask_cache
|=
mask
;
irq_gc_unlock
(
gc
);
}
...
...
@@ -108,10 +108,11 @@ void irq_gc_unmask_enable_reg(struct irq_data *d)
void
irq_gc_ack_set_bit
(
struct
irq_data
*
d
)
{
struct
irq_chip_generic
*
gc
=
irq_data_get_irq_chip_data
(
d
);
u32
mask
=
1
<<
(
d
->
irq
-
gc
->
irq_base
);
struct
irq_chip_type
*
ct
=
irq_data_get_chip_type
(
d
);
u32
mask
=
d
->
mask
;
irq_gc_lock
(
gc
);
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
ur_regs
(
d
)
->
ack
);
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
t
->
regs
.
ack
);
irq_gc_unlock
(
gc
);
}
...
...
@@ -122,10 +123,11 @@ void irq_gc_ack_set_bit(struct irq_data *d)
void
irq_gc_ack_clr_bit
(
struct
irq_data
*
d
)
{
struct
irq_chip_generic
*
gc
=
irq_data_get_irq_chip_data
(
d
);
u32
mask
=
~
(
1
<<
(
d
->
irq
-
gc
->
irq_base
));
struct
irq_chip_type
*
ct
=
irq_data_get_chip_type
(
d
);
u32
mask
=
~
d
->
mask
;
irq_gc_lock
(
gc
);
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
ur_regs
(
d
)
->
ack
);
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
t
->
regs
.
ack
);
irq_gc_unlock
(
gc
);
}
...
...
@@ -136,11 +138,12 @@ void irq_gc_ack_clr_bit(struct irq_data *d)
void
irq_gc_mask_disable_reg_and_ack
(
struct
irq_data
*
d
)
{
struct
irq_chip_generic
*
gc
=
irq_data_get_irq_chip_data
(
d
);
u32
mask
=
1
<<
(
d
->
irq
-
gc
->
irq_base
);
struct
irq_chip_type
*
ct
=
irq_data_get_chip_type
(
d
);
u32
mask
=
d
->
mask
;
irq_gc_lock
(
gc
);
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
ur_regs
(
d
)
->
mask
);
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
ur_regs
(
d
)
->
ack
);
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
t
->
regs
.
mask
);
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
t
->
regs
.
ack
);
irq_gc_unlock
(
gc
);
}
...
...
@@ -151,10 +154,11 @@ void irq_gc_mask_disable_reg_and_ack(struct irq_data *d)
void
irq_gc_eoi
(
struct
irq_data
*
d
)
{
struct
irq_chip_generic
*
gc
=
irq_data_get_irq_chip_data
(
d
);
u32
mask
=
1
<<
(
d
->
irq
-
gc
->
irq_base
);
struct
irq_chip_type
*
ct
=
irq_data_get_chip_type
(
d
);
u32
mask
=
d
->
mask
;
irq_gc_lock
(
gc
);
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
ur_regs
(
d
)
->
eoi
);
irq_reg_writel
(
mask
,
gc
->
reg_base
+
c
t
->
regs
.
eoi
);
irq_gc_unlock
(
gc
);
}
...
...
@@ -169,7 +173,7 @@ void irq_gc_eoi(struct irq_data *d)
int
irq_gc_set_wake
(
struct
irq_data
*
d
,
unsigned
int
on
)
{
struct
irq_chip_generic
*
gc
=
irq_data_get_irq_chip_data
(
d
);
u32
mask
=
1
<<
(
d
->
irq
-
gc
->
irq_base
)
;
u32
mask
=
d
->
mask
;
if
(
!
(
mask
&
gc
->
wake_enabled
))
return
-
EINVAL
;
...
...
@@ -183,6 +187,19 @@ int irq_gc_set_wake(struct irq_data *d, unsigned int on)
return
0
;
}
static
void
irq_init_generic_chip
(
struct
irq_chip_generic
*
gc
,
const
char
*
name
,
int
num_ct
,
unsigned
int
irq_base
,
void
__iomem
*
reg_base
,
irq_flow_handler_t
handler
)
{
raw_spin_lock_init
(
&
gc
->
lock
);
gc
->
num_ct
=
num_ct
;
gc
->
irq_base
=
irq_base
;
gc
->
reg_base
=
reg_base
;
gc
->
chip_types
->
chip
.
name
=
name
;
gc
->
chip_types
->
handler
=
handler
;
}
/**
* irq_alloc_generic_chip - Allocate a generic chip and initialize it
* @name: Name of the irq chip
...
...
@@ -203,23 +220,184 @@ irq_alloc_generic_chip(const char *name, int num_ct, unsigned int irq_base,
gc
=
kzalloc
(
sz
,
GFP_KERNEL
);
if
(
gc
)
{
raw_spin_lock_init
(
&
gc
->
lock
);
gc
->
num_ct
=
num_ct
;
gc
->
irq_base
=
irq_base
;
gc
->
reg_base
=
reg_base
;
gc
->
chip_types
->
chip
.
name
=
name
;
gc
->
chip_types
->
handler
=
handler
;
irq_init_generic_chip
(
gc
,
name
,
num_ct
,
irq_base
,
reg_base
,
handler
);
}
return
gc
;
}
EXPORT_SYMBOL_GPL
(
irq_alloc_generic_chip
);
static
void
irq_gc_init_mask_cache
(
struct
irq_chip_generic
*
gc
,
enum
irq_gc_flags
flags
)
{
struct
irq_chip_type
*
ct
=
gc
->
chip_types
;
u32
*
mskptr
=
&
gc
->
mask_cache
,
mskreg
=
ct
->
regs
.
mask
;
int
i
;
for
(
i
=
0
;
i
<
gc
->
num_ct
;
i
++
)
{
if
(
flags
&
IRQ_GC_MASK_CACHE_PER_TYPE
)
{
mskptr
=
&
ct
[
i
].
mask_cache_priv
;
mskreg
=
ct
[
i
].
regs
.
mask
;
}
ct
[
i
].
mask_cache
=
mskptr
;
if
(
flags
&
IRQ_GC_INIT_MASK_CACHE
)
*
mskptr
=
irq_reg_readl
(
gc
->
reg_base
+
mskreg
);
}
}
/**
* irq_alloc_domain_generic_chip - Allocate generic chips for an irq domain
* @d: irq domain for which to allocate chips
* @irqs_per_chip: Number of interrupts each chip handles
* @num_ct: Number of irq_chip_type instances associated with this
* @name: Name of the irq chip
* @handler: Default flow handler associated with these chips
* @clr: IRQ_* bits to clear in the mapping function
* @set: IRQ_* bits to set in the mapping function
*/
int
irq_alloc_domain_generic_chips
(
struct
irq_domain
*
d
,
int
irqs_per_chip
,
int
num_ct
,
const
char
*
name
,
irq_flow_handler_t
handler
,
unsigned
int
clr
,
unsigned
int
set
,
enum
irq_gc_flags
gcflags
)
{
struct
irq_domain_chip_generic
*
dgc
;
struct
irq_chip_generic
*
gc
;
int
numchips
,
sz
,
i
;
unsigned
long
flags
;
void
*
tmp
;
if
(
d
->
gc
)
return
-
EBUSY
;
if
(
d
->
revmap_type
!=
IRQ_DOMAIN_MAP_LINEAR
)
return
-
EINVAL
;
numchips
=
d
->
revmap_data
.
linear
.
size
/
irqs_per_chip
;
if
(
!
numchips
)
return
-
EINVAL
;
/* Allocate a pointer, generic chip and chiptypes for each chip */
sz
=
sizeof
(
*
dgc
)
+
numchips
*
sizeof
(
gc
);
sz
+=
numchips
*
(
sizeof
(
*
gc
)
+
num_ct
*
sizeof
(
struct
irq_chip_type
));
tmp
=
dgc
=
kzalloc
(
sz
,
GFP_KERNEL
);
if
(
!
dgc
)
return
-
ENOMEM
;
dgc
->
irqs_per_chip
=
irqs_per_chip
;
dgc
->
num_chips
=
numchips
;
dgc
->
irq_flags_to_set
=
set
;
dgc
->
irq_flags_to_clear
=
clr
;
dgc
->
gc_flags
=
gcflags
;
d
->
gc
=
dgc
;
/* Calc pointer to the first generic chip */
tmp
+=
sizeof
(
*
dgc
)
+
numchips
*
sizeof
(
gc
);
for
(
i
=
0
;
i
<
numchips
;
i
++
)
{
/* Store the pointer to the generic chip */
dgc
->
gc
[
i
]
=
gc
=
tmp
;
irq_init_generic_chip
(
gc
,
name
,
num_ct
,
i
*
irqs_per_chip
,
NULL
,
handler
);
gc
->
domain
=
d
;
raw_spin_lock_irqsave
(
&
gc_lock
,
flags
);
list_add_tail
(
&
gc
->
list
,
&
gc_list
);
raw_spin_unlock_irqrestore
(
&
gc_lock
,
flags
);
/* Calc pointer to the next generic chip */
tmp
+=
sizeof
(
*
gc
)
+
num_ct
*
sizeof
(
struct
irq_chip_type
);
}
return
0
;
}
EXPORT_SYMBOL_GPL
(
irq_alloc_domain_generic_chips
);
/**
* irq_get_domain_generic_chip - Get a pointer to the generic chip of a hw_irq
* @d: irq domain pointer
* @hw_irq: Hardware interrupt number
*/
struct
irq_chip_generic
*
irq_get_domain_generic_chip
(
struct
irq_domain
*
d
,
unsigned
int
hw_irq
)
{
struct
irq_domain_chip_generic
*
dgc
=
d
->
gc
;
int
idx
;
if
(
!
dgc
)
return
NULL
;
idx
=
hw_irq
/
dgc
->
irqs_per_chip
;
if
(
idx
>=
dgc
->
num_chips
)
return
NULL
;
return
dgc
->
gc
[
idx
];
}
EXPORT_SYMBOL_GPL
(
irq_get_domain_generic_chip
);
/*
* Separate lockdep class for interrupt chip which can nest irq_desc
* lock.
*/
static
struct
lock_class_key
irq_nested_lock_class
;
/**
* irq_map_generic_chip - Map a generic chip for an irq domain
*/
static
int
irq_map_generic_chip
(
struct
irq_domain
*
d
,
unsigned
int
virq
,
irq_hw_number_t
hw_irq
)
{
struct
irq_data
*
data
=
irq_get_irq_data
(
virq
);
struct
irq_domain_chip_generic
*
dgc
=
d
->
gc
;
struct
irq_chip_generic
*
gc
;
struct
irq_chip_type
*
ct
;
struct
irq_chip
*
chip
;
unsigned
long
flags
;
int
idx
;
if
(
!
d
->
gc
)
return
-
ENODEV
;
idx
=
hw_irq
/
dgc
->
irqs_per_chip
;
if
(
idx
>=
dgc
->
num_chips
)
return
-
EINVAL
;
gc
=
dgc
->
gc
[
idx
];
idx
=
hw_irq
%
dgc
->
irqs_per_chip
;
if
(
test_bit
(
idx
,
&
gc
->
unused
))
return
-
ENOTSUPP
;
if
(
test_bit
(
idx
,
&
gc
->
installed
))
return
-
EBUSY
;
ct
=
gc
->
chip_types
;
chip
=
&
ct
->
chip
;
/* We only init the cache for the first mapping of a generic chip */
if
(
!
gc
->
installed
)
{
raw_spin_lock_irqsave
(
&
gc
->
lock
,
flags
);
irq_gc_init_mask_cache
(
gc
,
dgc
->
gc_flags
);
raw_spin_unlock_irqrestore
(
&
gc
->
lock
,
flags
);
}
/* Mark the interrupt as installed */
set_bit
(
idx
,
&
gc
->
installed
);
if
(
dgc
->
gc_flags
&
IRQ_GC_INIT_NESTED_LOCK
)
irq_set_lockdep_class
(
virq
,
&
irq_nested_lock_class
);
if
(
chip
->
irq_calc_mask
)
chip
->
irq_calc_mask
(
data
);
else
data
->
mask
=
1
<<
idx
;
irq_set_chip_and_handler
(
virq
,
chip
,
ct
->
handler
);
irq_set_chip_data
(
virq
,
gc
);
irq_modify_status
(
virq
,
dgc
->
irq_flags_to_clear
,
dgc
->
irq_flags_to_set
);
return
0
;
}
struct
irq_domain_ops
irq_generic_chip_ops
=
{
.
map
=
irq_map_generic_chip
,
.
xlate
=
irq_domain_xlate_onetwocell
,
};
EXPORT_SYMBOL_GPL
(
irq_generic_chip_ops
);
/**
* irq_setup_generic_chip - Setup a range of interrupts with a generic chip
* @gc: Generic irq chip holding all data
...
...
@@ -237,15 +415,14 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
unsigned
int
set
)
{
struct
irq_chip_type
*
ct
=
gc
->
chip_types
;
struct
irq_chip
*
chip
=
&
ct
->
chip
;
unsigned
int
i
;
raw_spin_lock
(
&
gc_lock
);
list_add_tail
(
&
gc
->
list
,
&
gc_list
);
raw_spin_unlock
(
&
gc_lock
);
/* Init mask cache ? */
if
(
flags
&
IRQ_GC_INIT_MASK_CACHE
)
gc
->
mask_cache
=
irq_reg_readl
(
gc
->
reg_base
+
ct
->
regs
.
mask
);
irq_gc_init_mask_cache
(
gc
,
flags
);
for
(
i
=
gc
->
irq_base
;
msk
;
msk
>>=
1
,
i
++
)
{
if
(
!
(
msk
&
0x01
))
...
...
@@ -254,7 +431,15 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
if
(
flags
&
IRQ_GC_INIT_NESTED_LOCK
)
irq_set_lockdep_class
(
i
,
&
irq_nested_lock_class
);
irq_set_chip_and_handler
(
i
,
&
ct
->
chip
,
ct
->
handler
);
if
(
!
(
flags
&
IRQ_GC_NO_MASK
))
{
struct
irq_data
*
d
=
irq_get_irq_data
(
i
);
if
(
chip
->
irq_calc_mask
)
chip
->
irq_calc_mask
(
d
);
else
d
->
mask
=
1
<<
(
i
-
gc
->
irq_base
);
}
irq_set_chip_and_handler
(
i
,
chip
,
ct
->
handler
);
irq_set_chip_data
(
i
,
gc
);
irq_modify_status
(
i
,
clr
,
set
);
}
...
...
@@ -317,6 +502,24 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
}
EXPORT_SYMBOL_GPL
(
irq_remove_generic_chip
);
static
struct
irq_data
*
irq_gc_get_irq_data
(
struct
irq_chip_generic
*
gc
)
{
unsigned
int
virq
;
if
(
!
gc
->
domain
)
return
irq_get_irq_data
(
gc
->
irq_base
);
/*
* We don't know which of the irqs has been actually
* installed. Use the first one.
*/
if
(
!
gc
->
installed
)
return
NULL
;
virq
=
irq_find_mapping
(
gc
->
domain
,
gc
->
irq_base
+
__ffs
(
gc
->
installed
));
return
virq
?
irq_get_irq_data
(
virq
)
:
NULL
;
}
#ifdef CONFIG_PM
static
int
irq_gc_suspend
(
void
)
{
...
...
@@ -325,8 +528,12 @@ static int irq_gc_suspend(void)
list_for_each_entry
(
gc
,
&
gc_list
,
list
)
{
struct
irq_chip_type
*
ct
=
gc
->
chip_types
;
if
(
ct
->
chip
.
irq_suspend
)
ct
->
chip
.
irq_suspend
(
irq_get_irq_data
(
gc
->
irq_base
));
if
(
ct
->
chip
.
irq_suspend
)
{
struct
irq_data
*
data
=
irq_gc_get_irq_data
(
gc
);
if
(
data
)
ct
->
chip
.
irq_suspend
(
data
);
}
}
return
0
;
}
...
...
@@ -338,8 +545,12 @@ static void irq_gc_resume(void)
list_for_each_entry
(
gc
,
&
gc_list
,
list
)
{
struct
irq_chip_type
*
ct
=
gc
->
chip_types
;
if
(
ct
->
chip
.
irq_resume
)
ct
->
chip
.
irq_resume
(
irq_get_irq_data
(
gc
->
irq_base
));
if
(
ct
->
chip
.
irq_resume
)
{
struct
irq_data
*
data
=
irq_gc_get_irq_data
(
gc
);
if
(
data
)
ct
->
chip
.
irq_resume
(
data
);
}
}
}
#else
...
...
@@ -354,8 +565,12 @@ static void irq_gc_shutdown(void)
list_for_each_entry
(
gc
,
&
gc_list
,
list
)
{
struct
irq_chip_type
*
ct
=
gc
->
chip_types
;
if
(
ct
->
chip
.
irq_pm_shutdown
)
ct
->
chip
.
irq_pm_shutdown
(
irq_get_irq_data
(
gc
->
irq_base
));
if
(
ct
->
chip
.
irq_pm_shutdown
)
{
struct
irq_data
*
data
=
irq_gc_get_irq_data
(
gc
);
if
(
data
)
ct
->
chip
.
irq_pm_shutdown
(
data
);
}
}
}
...
...
kernel/irq/irqdomain.c
浏览文件 @
5e8bd41a
...
...
@@ -16,12 +16,6 @@
#include <linux/smp.h>
#include <linux/fs.h>
#define IRQ_DOMAIN_MAP_LEGACY 0
/* driver allocated fixed range of irqs.
* ie. legacy 8259, gets irqs 1..15 */
#define IRQ_DOMAIN_MAP_NOMAP 1
/* no fast reverse mapping */
#define IRQ_DOMAIN_MAP_LINEAR 2
/* linear map of interrupts */
#define IRQ_DOMAIN_MAP_TREE 3
/* radix tree */
static
LIST_HEAD
(
irq_domain_list
);
static
DEFINE_MUTEX
(
irq_domain_mutex
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录