Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
1ad9a576
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看板
提交
1ad9a576
编写于
2月 21, 2016
作者:
J
Jason Cooper
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'irqchip/mvebu' into irqchip/core
上级
7cf03c9f
0407dace
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
284 addition
and
14 deletion
+284
-14
Documentation/devicetree/bindings/interrupt-controller/marvell,odmi-controller.txt
...bindings/interrupt-controller/marvell,odmi-controller.txt
+41
-0
drivers/irqchip/Kconfig
drivers/irqchip/Kconfig
+4
-0
drivers/irqchip/Makefile
drivers/irqchip/Makefile
+1
-0
drivers/irqchip/irq-gic-v2m.c
drivers/irqchip/irq-gic-v2m.c
+1
-13
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-gic.c
+1
-1
drivers/irqchip/irq-mvebu-odmi.c
drivers/irqchip/irq-mvebu-odmi.c
+236
-0
未找到文件。
Documentation/devicetree/bindings/interrupt-controller/marvell,odmi-controller.txt
0 → 100644
浏览文件 @
1ad9a576
* Marvell ODMI for MSI support
Some Marvell SoCs have an On-Die Message Interrupt (ODMI) controller
which can be used by on-board peripheral for MSI interrupts.
Required properties:
- compatible : The value here should contain "marvell,odmi-controller".
- interrupt,controller : Identifies the node as an interrupt controller.
- msi-controller : Identifies the node as an MSI controller.
- marvell,odmi-frames : Number of ODMI frames available. Each frame
provides a number of events.
- reg : List of register definitions, one for each
ODMI frame.
- marvell,spi-base : List of GIC base SPI interrupts, one for each
ODMI frame. Those SPI interrupts are 0-based,
i.e marvell,spi-base = <128> will use SPI #96.
See Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
for details about the GIC Device Tree binding.
- interrupt-parent : Reference to the parent interrupt controller.
Example:
odmi: odmi@300000 {
compatible = "marvell,odmi-controller";
interrupt-controller;
msi-controller;
marvell,odmi-frames = <4>;
reg = <0x300000 0x4000>,
<0x304000 0x4000>,
<0x308000 0x4000>,
<0x30C000 0x4000>;
marvell,spi-base = <128>, <136>, <144>, <152>;
};
drivers/irqchip/Kconfig
浏览文件 @
1ad9a576
...
...
@@ -229,3 +229,7 @@ config IRQ_MXS
def_bool y if MACH_ASM9260 || ARCH_MXS
select IRQ_DOMAIN
select STMP_DEVICE
config MVEBU_ODMI
bool
select GENERIC_MSI_IRQ_DOMAIN
drivers/irqchip/Makefile
浏览文件 @
1ad9a576
...
...
@@ -62,3 +62,4 @@ obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
obj-$(CONFIG_INGENIC_IRQ)
+=
irq-ingenic.o
obj-$(CONFIG_IMX_GPCV2)
+=
irq-imx-gpcv2.o
obj-$(CONFIG_PIC32_EVIC)
+=
irq-pic32-evic.o
obj-$(CONFIG_MVEBU_ODMI)
+=
irq-mvebu-odmi.o
drivers/irqchip/irq-gic-v2m.c
浏览文件 @
1ad9a576
...
...
@@ -92,18 +92,6 @@ static struct msi_domain_info gicv2m_msi_domain_info = {
.
chip
=
&
gicv2m_msi_irq_chip
,
};
static
int
gicv2m_set_affinity
(
struct
irq_data
*
irq_data
,
const
struct
cpumask
*
mask
,
bool
force
)
{
int
ret
;
ret
=
irq_chip_set_affinity_parent
(
irq_data
,
mask
,
force
);
if
(
ret
==
IRQ_SET_MASK_OK
)
ret
=
IRQ_SET_MASK_OK_DONE
;
return
ret
;
}
static
void
gicv2m_compose_msi_msg
(
struct
irq_data
*
data
,
struct
msi_msg
*
msg
)
{
struct
v2m_data
*
v2m
=
irq_data_get_irq_chip_data
(
data
);
...
...
@@ -122,7 +110,7 @@ static struct irq_chip gicv2m_irq_chip = {
.
irq_mask
=
irq_chip_mask_parent
,
.
irq_unmask
=
irq_chip_unmask_parent
,
.
irq_eoi
=
irq_chip_eoi_parent
,
.
irq_set_affinity
=
gicv2m_set_affinity
,
.
irq_set_affinity
=
irq_chip_set_affinity_parent
,
.
irq_compose_msi_msg
=
gicv2m_compose_msi_msg
,
};
...
...
drivers/irqchip/irq-gic.c
浏览文件 @
1ad9a576
...
...
@@ -319,7 +319,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
writel_relaxed
(
val
|
bit
,
reg
);
raw_spin_unlock_irqrestore
(
&
irq_controller_lock
,
flags
);
return
IRQ_SET_MASK_OK
;
return
IRQ_SET_MASK_OK
_DONE
;
}
#endif
...
...
drivers/irqchip/irq-mvebu-odmi.c
0 → 100644
浏览文件 @
1ad9a576
/*
* Copyright (C) 2016 Marvell
*
* Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#define pr_fmt(fmt) "GIC-ODMI: " fmt
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/msi.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#define GICP_ODMIN_SET 0x40
#define GICP_ODMI_INT_NUM_SHIFT 12
#define GICP_ODMIN_GM_EP_R0 0x110
#define GICP_ODMIN_GM_EP_R1 0x114
#define GICP_ODMIN_GM_EA_R0 0x108
#define GICP_ODMIN_GM_EA_R1 0x118
/*
* We don't support the group events, so we simply have 8 interrupts
* per frame.
*/
#define NODMIS_SHIFT 3
#define NODMIS_PER_FRAME (1 << NODMIS_SHIFT)
#define NODMIS_MASK (NODMIS_PER_FRAME - 1)
struct
odmi_data
{
struct
resource
res
;
void
__iomem
*
base
;
unsigned
int
spi_base
;
};
static
struct
odmi_data
*
odmis
;
static
unsigned
long
*
odmis_bm
;
static
unsigned
int
odmis_count
;
/* Protects odmis_bm */
static
DEFINE_SPINLOCK
(
odmis_bm_lock
);
static
void
odmi_compose_msi_msg
(
struct
irq_data
*
d
,
struct
msi_msg
*
msg
)
{
struct
odmi_data
*
odmi
;
phys_addr_t
addr
;
unsigned
int
odmin
;
if
(
WARN_ON
(
d
->
hwirq
>=
odmis_count
*
NODMIS_PER_FRAME
))
return
;
odmi
=
&
odmis
[
d
->
hwirq
>>
NODMIS_SHIFT
];
odmin
=
d
->
hwirq
&
NODMIS_MASK
;
addr
=
odmi
->
res
.
start
+
GICP_ODMIN_SET
;
msg
->
address_hi
=
upper_32_bits
(
addr
);
msg
->
address_lo
=
lower_32_bits
(
addr
);
msg
->
data
=
odmin
<<
GICP_ODMI_INT_NUM_SHIFT
;
}
static
struct
irq_chip
odmi_irq_chip
=
{
.
name
=
"ODMI"
,
.
irq_mask
=
irq_chip_mask_parent
,
.
irq_unmask
=
irq_chip_unmask_parent
,
.
irq_eoi
=
irq_chip_eoi_parent
,
.
irq_set_affinity
=
irq_chip_set_affinity_parent
,
.
irq_compose_msi_msg
=
odmi_compose_msi_msg
,
};
static
int
odmi_irq_domain_alloc
(
struct
irq_domain
*
domain
,
unsigned
int
virq
,
unsigned
int
nr_irqs
,
void
*
args
)
{
struct
odmi_data
*
odmi
=
NULL
;
struct
irq_fwspec
fwspec
;
struct
irq_data
*
d
;
unsigned
int
hwirq
,
odmin
;
int
ret
;
spin_lock
(
&
odmis_bm_lock
);
hwirq
=
find_first_zero_bit
(
odmis_bm
,
NODMIS_PER_FRAME
*
odmis_count
);
if
(
hwirq
>=
NODMIS_PER_FRAME
*
odmis_count
)
{
spin_unlock
(
&
odmis_bm_lock
);
return
-
ENOSPC
;
}
__set_bit
(
hwirq
,
odmis_bm
);
spin_unlock
(
&
odmis_bm_lock
);
odmi
=
&
odmis
[
hwirq
>>
NODMIS_SHIFT
];
odmin
=
hwirq
&
NODMIS_MASK
;
fwspec
.
fwnode
=
domain
->
parent
->
fwnode
;
fwspec
.
param_count
=
3
;
fwspec
.
param
[
0
]
=
GIC_SPI
;
fwspec
.
param
[
1
]
=
odmi
->
spi_base
-
32
+
odmin
;
fwspec
.
param
[
2
]
=
IRQ_TYPE_EDGE_RISING
;
ret
=
irq_domain_alloc_irqs_parent
(
domain
,
virq
,
1
,
&
fwspec
);
if
(
ret
)
{
pr_err
(
"Cannot allocate parent IRQ
\n
"
);
spin_lock
(
&
odmis_bm_lock
);
__clear_bit
(
odmin
,
odmis_bm
);
spin_unlock
(
&
odmis_bm_lock
);
return
ret
;
}
/* Configure the interrupt line to be edge */
d
=
irq_domain_get_irq_data
(
domain
->
parent
,
virq
);
d
->
chip
->
irq_set_type
(
d
,
IRQ_TYPE_EDGE_RISING
);
irq_domain_set_hwirq_and_chip
(
domain
,
virq
,
hwirq
,
&
odmi_irq_chip
,
NULL
);
return
0
;
}
static
void
odmi_irq_domain_free
(
struct
irq_domain
*
domain
,
unsigned
int
virq
,
unsigned
int
nr_irqs
)
{
struct
irq_data
*
d
=
irq_domain_get_irq_data
(
domain
,
virq
);
if
(
d
->
hwirq
>=
odmis_count
*
NODMIS_PER_FRAME
)
{
pr_err
(
"Failed to teardown msi. Invalid hwirq %lu
\n
"
,
d
->
hwirq
);
return
;
}
irq_domain_free_irqs_parent
(
domain
,
virq
,
nr_irqs
);
/* Actually free the MSI */
spin_lock
(
&
odmis_bm_lock
);
__clear_bit
(
d
->
hwirq
,
odmis_bm
);
spin_unlock
(
&
odmis_bm_lock
);
}
static
const
struct
irq_domain_ops
odmi_domain_ops
=
{
.
alloc
=
odmi_irq_domain_alloc
,
.
free
=
odmi_irq_domain_free
,
};
static
struct
irq_chip
odmi_msi_irq_chip
=
{
.
name
=
"ODMI"
,
};
static
struct
msi_domain_ops
odmi_msi_ops
=
{
};
static
struct
msi_domain_info
odmi_msi_domain_info
=
{
.
flags
=
(
MSI_FLAG_USE_DEF_DOM_OPS
|
MSI_FLAG_USE_DEF_CHIP_OPS
),
.
ops
=
&
odmi_msi_ops
,
.
chip
=
&
odmi_msi_irq_chip
,
};
static
int
__init
mvebu_odmi_init
(
struct
device_node
*
node
,
struct
device_node
*
parent
)
{
struct
irq_domain
*
inner_domain
,
*
plat_domain
;
int
ret
,
i
;
if
(
of_property_read_u32
(
node
,
"marvell,odmi-frames"
,
&
odmis_count
))
return
-
EINVAL
;
odmis
=
kcalloc
(
odmis_count
,
sizeof
(
struct
odmi_data
),
GFP_KERNEL
);
if
(
!
odmis
)
return
-
ENOMEM
;
odmis_bm
=
kcalloc
(
BITS_TO_LONGS
(
odmis_count
*
NODMIS_PER_FRAME
),
sizeof
(
long
),
GFP_KERNEL
);
if
(
!
odmis_bm
)
{
ret
=
-
ENOMEM
;
goto
err_alloc
;
}
for
(
i
=
0
;
i
<
odmis_count
;
i
++
)
{
struct
odmi_data
*
odmi
=
&
odmis
[
i
];
ret
=
of_address_to_resource
(
node
,
i
,
&
odmi
->
res
);
if
(
ret
)
goto
err_unmap
;
odmi
->
base
=
of_io_request_and_map
(
node
,
i
,
"odmi"
);
if
(
IS_ERR
(
odmi
->
base
))
{
ret
=
PTR_ERR
(
odmi
->
base
);
goto
err_unmap
;
}
if
(
of_property_read_u32_index
(
node
,
"marvell,spi-base"
,
i
,
&
odmi
->
spi_base
))
{
ret
=
-
EINVAL
;
goto
err_unmap
;
}
}
inner_domain
=
irq_domain_create_linear
(
of_node_to_fwnode
(
node
),
odmis_count
*
NODMIS_PER_FRAME
,
&
odmi_domain_ops
,
NULL
);
if
(
!
inner_domain
)
{
ret
=
-
ENOMEM
;
goto
err_unmap
;
}
inner_domain
->
parent
=
irq_find_host
(
parent
);
plat_domain
=
platform_msi_create_irq_domain
(
of_node_to_fwnode
(
node
),
&
odmi_msi_domain_info
,
inner_domain
);
if
(
!
plat_domain
)
{
ret
=
-
ENOMEM
;
goto
err_remove_inner
;
}
return
0
;
err_remove_inner:
irq_domain_remove
(
inner_domain
);
err_unmap:
for
(
i
=
0
;
i
<
odmis_count
;
i
++
)
{
struct
odmi_data
*
odmi
=
&
odmis
[
i
];
if
(
odmi
->
base
&&
!
IS_ERR
(
odmi
->
base
))
iounmap
(
odmis
[
i
].
base
);
}
kfree
(
odmis_bm
);
err_alloc:
kfree
(
odmis
);
return
ret
;
}
IRQCHIP_DECLARE
(
mvebu_odmi
,
"marvell,odmi-controller"
,
mvebu_odmi_init
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录