Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
55e10798
K
Kernel
项目概览
openeuler
/
Kernel
接近 2 年 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
55e10798
编写于
2月 21, 2016
作者:
J
Jason Cooper
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'irqchip/tango' into irqchip/core
上级
e4e1c0ea
4bba6689
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
287 addition
and
0 deletion
+287
-0
Documentation/devicetree/bindings/interrupt-controller/sigma,smp8642-intc.txt
...tree/bindings/interrupt-controller/sigma,smp8642-intc.txt
+49
-0
drivers/irqchip/Kconfig
drivers/irqchip/Kconfig
+5
-0
drivers/irqchip/Makefile
drivers/irqchip/Makefile
+1
-0
drivers/irqchip/irq-tango.c
drivers/irqchip/irq-tango.c
+232
-0
未找到文件。
Documentation/devicetree/bindings/interrupt-controller/sigma,smp8642-intc.txt
0 → 100644
浏览文件 @
55e10798
Sigma Designs SMP86xx/SMP87xx secondary interrupt controller
Required properties:
- compatible: should be "sigma,smp8642-intc"
- reg: physical address of MMIO region
- ranges: address space mapping of child nodes
- interrupt-parent: phandle of parent interrupt controller
- interrupt-controller: boolean
- #address-cells: should be <1>
- #size-cells: should be <1>
One child node per control block with properties:
- reg: address of registers for this control block
- interrupt-controller: boolean
- #interrupt-cells: should be <2>, interrupt index and flags per interrupts.txt
- interrupts: interrupt spec of primary interrupt controller
Example:
interrupt-controller@6e000 {
compatible = "sigma,smp8642-intc";
reg = <0x6e000 0x400>;
ranges = <0x0 0x6e000 0x400>;
interrupt-parent = <&gic>;
interrupt-controller;
#address-cells = <1>;
#size-cells = <1>;
irq0: interrupt-controller@0 {
reg = <0x000 0x100>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
};
irq1: interrupt-controller@100 {
reg = <0x100 0x100>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
};
irq2: interrupt-controller@300 {
reg = <0x300 0x100>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
};
};
drivers/irqchip/Kconfig
浏览文件 @
55e10798
...
@@ -156,6 +156,11 @@ config ST_IRQCHIP
...
@@ -156,6 +156,11 @@ config ST_IRQCHIP
help
help
Enables SysCfg Controlled IRQs on STi based platforms.
Enables SysCfg Controlled IRQs on STi based platforms.
config TANGO_IRQ
bool
select IRQ_DOMAIN
select GENERIC_IRQ_CHIP
config TB10X_IRQC
config TB10X_IRQC
bool
bool
select IRQ_DOMAIN
select IRQ_DOMAIN
...
...
drivers/irqchip/Makefile
浏览文件 @
55e10798
...
@@ -40,6 +40,7 @@ obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
...
@@ -40,6 +40,7 @@ obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
obj-$(CONFIG_ARCH_NSPIRE)
+=
irq-zevio.o
obj-$(CONFIG_ARCH_NSPIRE)
+=
irq-zevio.o
obj-$(CONFIG_ARCH_VT8500)
+=
irq-vt8500.o
obj-$(CONFIG_ARCH_VT8500)
+=
irq-vt8500.o
obj-$(CONFIG_ST_IRQCHIP)
+=
irq-st.o
obj-$(CONFIG_ST_IRQCHIP)
+=
irq-st.o
obj-$(CONFIG_TANGO_IRQ)
+=
irq-tango.o
obj-$(CONFIG_TB10X_IRQC)
+=
irq-tb10x.o
obj-$(CONFIG_TB10X_IRQC)
+=
irq-tb10x.o
obj-$(CONFIG_TS4800_IRQ)
+=
irq-ts4800.o
obj-$(CONFIG_TS4800_IRQ)
+=
irq-ts4800.o
obj-$(CONFIG_XTENSA)
+=
irq-xtensa-pic.o
obj-$(CONFIG_XTENSA)
+=
irq-xtensa-pic.o
...
...
drivers/irqchip/irq-tango.c
0 → 100644
浏览文件 @
55e10798
/*
* Copyright (C) 2014 Mans Rullgard <mans@mansr.com>
*
* 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.
*/
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
#define IRQ0_CTL_BASE 0x0000
#define IRQ1_CTL_BASE 0x0100
#define EDGE_CTL_BASE 0x0200
#define IRQ2_CTL_BASE 0x0300
#define IRQ_CTL_HI 0x18
#define EDGE_CTL_HI 0x20
#define IRQ_STATUS 0x00
#define IRQ_RAWSTAT 0x04
#define IRQ_EN_SET 0x08
#define IRQ_EN_CLR 0x0c
#define IRQ_SOFT_SET 0x10
#define IRQ_SOFT_CLR 0x14
#define EDGE_STATUS 0x00
#define EDGE_RAWSTAT 0x04
#define EDGE_CFG_RISE 0x08
#define EDGE_CFG_FALL 0x0c
#define EDGE_CFG_RISE_SET 0x10
#define EDGE_CFG_RISE_CLR 0x14
#define EDGE_CFG_FALL_SET 0x18
#define EDGE_CFG_FALL_CLR 0x1c
struct
tangox_irq_chip
{
void
__iomem
*
base
;
unsigned
long
ctl
;
};
static
inline
u32
intc_readl
(
struct
tangox_irq_chip
*
chip
,
int
reg
)
{
return
readl_relaxed
(
chip
->
base
+
reg
);
}
static
inline
void
intc_writel
(
struct
tangox_irq_chip
*
chip
,
int
reg
,
u32
val
)
{
writel_relaxed
(
val
,
chip
->
base
+
reg
);
}
static
void
tangox_dispatch_irqs
(
struct
irq_domain
*
dom
,
unsigned
int
status
,
int
base
)
{
unsigned
int
hwirq
;
unsigned
int
virq
;
while
(
status
)
{
hwirq
=
__ffs
(
status
);
virq
=
irq_find_mapping
(
dom
,
base
+
hwirq
);
if
(
virq
)
generic_handle_irq
(
virq
);
status
&=
~
BIT
(
hwirq
);
}
}
static
void
tangox_irq_handler
(
struct
irq_desc
*
desc
)
{
struct
irq_domain
*
dom
=
irq_desc_get_handler_data
(
desc
);
struct
irq_chip
*
host_chip
=
irq_desc_get_chip
(
desc
);
struct
tangox_irq_chip
*
chip
=
dom
->
host_data
;
unsigned
int
status_lo
,
status_hi
;
chained_irq_enter
(
host_chip
,
desc
);
status_lo
=
intc_readl
(
chip
,
chip
->
ctl
+
IRQ_STATUS
);
status_hi
=
intc_readl
(
chip
,
chip
->
ctl
+
IRQ_CTL_HI
+
IRQ_STATUS
);
tangox_dispatch_irqs
(
dom
,
status_lo
,
0
);
tangox_dispatch_irqs
(
dom
,
status_hi
,
32
);
chained_irq_exit
(
host_chip
,
desc
);
}
static
int
tangox_irq_set_type
(
struct
irq_data
*
d
,
unsigned
int
flow_type
)
{
struct
irq_chip_generic
*
gc
=
irq_data_get_irq_chip_data
(
d
);
struct
tangox_irq_chip
*
chip
=
gc
->
domain
->
host_data
;
struct
irq_chip_regs
*
regs
=
&
gc
->
chip_types
[
0
].
regs
;
switch
(
flow_type
&
IRQ_TYPE_SENSE_MASK
)
{
case
IRQ_TYPE_EDGE_RISING
:
intc_writel
(
chip
,
regs
->
type
+
EDGE_CFG_RISE_SET
,
d
->
mask
);
intc_writel
(
chip
,
regs
->
type
+
EDGE_CFG_FALL_CLR
,
d
->
mask
);
break
;
case
IRQ_TYPE_EDGE_FALLING
:
intc_writel
(
chip
,
regs
->
type
+
EDGE_CFG_RISE_CLR
,
d
->
mask
);
intc_writel
(
chip
,
regs
->
type
+
EDGE_CFG_FALL_SET
,
d
->
mask
);
break
;
case
IRQ_TYPE_LEVEL_HIGH
:
intc_writel
(
chip
,
regs
->
type
+
EDGE_CFG_RISE_CLR
,
d
->
mask
);
intc_writel
(
chip
,
regs
->
type
+
EDGE_CFG_FALL_CLR
,
d
->
mask
);
break
;
case
IRQ_TYPE_LEVEL_LOW
:
intc_writel
(
chip
,
regs
->
type
+
EDGE_CFG_RISE_SET
,
d
->
mask
);
intc_writel
(
chip
,
regs
->
type
+
EDGE_CFG_FALL_SET
,
d
->
mask
);
break
;
default:
pr_err
(
"Invalid trigger mode %x for IRQ %d
\n
"
,
flow_type
,
d
->
irq
);
return
-
EINVAL
;
}
return
irq_setup_alt_chip
(
d
,
flow_type
);
}
static
void
__init
tangox_irq_init_chip
(
struct
irq_chip_generic
*
gc
,
unsigned
long
ctl_offs
,
unsigned
long
edge_offs
)
{
struct
tangox_irq_chip
*
chip
=
gc
->
domain
->
host_data
;
struct
irq_chip_type
*
ct
=
gc
->
chip_types
;
unsigned
long
ctl_base
=
chip
->
ctl
+
ctl_offs
;
unsigned
long
edge_base
=
EDGE_CTL_BASE
+
edge_offs
;
int
i
;
gc
->
reg_base
=
chip
->
base
;
gc
->
unused
=
0
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
ct
[
i
].
chip
.
irq_ack
=
irq_gc_ack_set_bit
;
ct
[
i
].
chip
.
irq_mask
=
irq_gc_mask_disable_reg
;
ct
[
i
].
chip
.
irq_mask_ack
=
irq_gc_mask_disable_reg_and_ack
;
ct
[
i
].
chip
.
irq_unmask
=
irq_gc_unmask_enable_reg
;
ct
[
i
].
chip
.
irq_set_type
=
tangox_irq_set_type
;
ct
[
i
].
chip
.
name
=
gc
->
domain
->
name
;
ct
[
i
].
regs
.
enable
=
ctl_base
+
IRQ_EN_SET
;
ct
[
i
].
regs
.
disable
=
ctl_base
+
IRQ_EN_CLR
;
ct
[
i
].
regs
.
ack
=
edge_base
+
EDGE_RAWSTAT
;
ct
[
i
].
regs
.
type
=
edge_base
;
}
ct
[
0
].
type
=
IRQ_TYPE_LEVEL_MASK
;
ct
[
0
].
handler
=
handle_level_irq
;
ct
[
1
].
type
=
IRQ_TYPE_EDGE_BOTH
;
ct
[
1
].
handler
=
handle_edge_irq
;
intc_writel
(
chip
,
ct
->
regs
.
disable
,
0xffffffff
);
intc_writel
(
chip
,
ct
->
regs
.
ack
,
0xffffffff
);
}
static
void
__init
tangox_irq_domain_init
(
struct
irq_domain
*
dom
)
{
struct
irq_chip_generic
*
gc
;
int
i
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
gc
=
irq_get_domain_generic_chip
(
dom
,
i
*
32
);
tangox_irq_init_chip
(
gc
,
i
*
IRQ_CTL_HI
,
i
*
EDGE_CTL_HI
);
}
}
static
int
__init
tangox_irq_init
(
void
__iomem
*
base
,
struct
resource
*
baseres
,
struct
device_node
*
node
)
{
struct
tangox_irq_chip
*
chip
;
struct
irq_domain
*
dom
;
struct
resource
res
;
int
irq
;
int
err
;
irq
=
irq_of_parse_and_map
(
node
,
0
);
if
(
!
irq
)
panic
(
"%s: failed to get IRQ"
,
node
->
name
);
err
=
of_address_to_resource
(
node
,
0
,
&
res
);
if
(
err
)
panic
(
"%s: failed to get address"
,
node
->
name
);
chip
=
kzalloc
(
sizeof
(
*
chip
),
GFP_KERNEL
);
chip
->
ctl
=
res
.
start
-
baseres
->
start
;
chip
->
base
=
base
;
dom
=
irq_domain_add_linear
(
node
,
64
,
&
irq_generic_chip_ops
,
chip
);
if
(
!
dom
)
panic
(
"%s: failed to create irqdomain"
,
node
->
name
);
err
=
irq_alloc_domain_generic_chips
(
dom
,
32
,
2
,
node
->
name
,
handle_level_irq
,
0
,
0
,
0
);
if
(
err
)
panic
(
"%s: failed to allocate irqchip"
,
node
->
name
);
tangox_irq_domain_init
(
dom
);
irq_set_chained_handler
(
irq
,
tangox_irq_handler
);
irq_set_handler_data
(
irq
,
dom
);
return
0
;
}
static
int
__init
tangox_of_irq_init
(
struct
device_node
*
node
,
struct
device_node
*
parent
)
{
struct
device_node
*
c
;
struct
resource
res
;
void
__iomem
*
base
;
base
=
of_iomap
(
node
,
0
);
if
(
!
base
)
panic
(
"%s: of_iomap failed"
,
node
->
name
);
of_address_to_resource
(
node
,
0
,
&
res
);
for_each_child_of_node
(
node
,
c
)
tangox_irq_init
(
base
,
&
res
,
c
);
return
0
;
}
IRQCHIP_DECLARE
(
tangox_intc
,
"sigma,smp8642-intc"
,
tangox_of_irq_init
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录