Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
59603b9a
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 3 年多
通知
13
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
59603b9a
编写于
3月 09, 2010
作者:
B
Benjamin Herrenschmidt
浏览文件
操作
浏览文件
下载
差异文件
Merge commit 'kumar/next' into merge
上级
57d54889
a1110654
变更
22
隐藏空白更改
内联
并排
Showing
22 changed file
with
1045 addition
and
174 deletion
+1045
-174
arch/powerpc/boot/dts/gef_ppc9a.dts
arch/powerpc/boot/dts/gef_ppc9a.dts
+2
-2
arch/powerpc/boot/dts/gef_sbc310.dts
arch/powerpc/boot/dts/gef_sbc310.dts
+2
-2
arch/powerpc/boot/dts/gef_sbc610.dts
arch/powerpc/boot/dts/gef_sbc610.dts
+2
-2
arch/powerpc/include/asm/perf_event.h
arch/powerpc/include/asm/perf_event.h
+11
-98
arch/powerpc/include/asm/perf_event_fsl_emb.h
arch/powerpc/include/asm/perf_event_fsl_emb.h
+50
-0
arch/powerpc/include/asm/perf_event_server.h
arch/powerpc/include/asm/perf_event_server.h
+110
-0
arch/powerpc/include/asm/reg_fsl_emb.h
arch/powerpc/include/asm/reg_fsl_emb.h
+1
-1
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/Makefile
+6
-1
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/cputable.c
+1
-1
arch/powerpc/kernel/e500-pmu.c
arch/powerpc/kernel/e500-pmu.c
+129
-0
arch/powerpc/kernel/perf_event_fsl_emb.c
arch/powerpc/kernel/perf_event_fsl_emb.c
+654
-0
arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
+5
-5
arch/powerpc/platforms/85xx/socrates_fpga_pic.c
arch/powerpc/platforms/85xx/socrates_fpga_pic.c
+17
-17
arch/powerpc/platforms/86xx/Kconfig
arch/powerpc/platforms/86xx/Kconfig
+6
-6
arch/powerpc/platforms/86xx/gef_gpio.c
arch/powerpc/platforms/86xx/gef_gpio.c
+5
-5
arch/powerpc/platforms/86xx/gef_pic.c
arch/powerpc/platforms/86xx/gef_pic.c
+10
-10
arch/powerpc/platforms/86xx/gef_ppc9a.c
arch/powerpc/platforms/86xx/gef_ppc9a.c
+6
-6
arch/powerpc/platforms/86xx/gef_sbc310.c
arch/powerpc/platforms/86xx/gef_sbc310.c
+6
-6
arch/powerpc/platforms/86xx/gef_sbc610.c
arch/powerpc/platforms/86xx/gef_sbc610.c
+6
-6
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/Kconfig.cputype
+10
-0
arch/powerpc/sysdev/cpm2_pic.h
arch/powerpc/sysdev/cpm2_pic.h
+1
-1
arch/powerpc/sysdev/qe_lib/qe_ic.c
arch/powerpc/sysdev/qe_lib/qe_ic.c
+5
-5
未找到文件。
arch/powerpc/boot/dts/gef_ppc9a.dts
浏览文件 @
59603b9a
/*
*
GE
Fanuc
PPC9A
Device
Tree
Source
*
GE
PPC9A
Device
Tree
Source
*
*
Copyright
2008
GE
Fanuc
Intelligent
Platforms
Embedded
Systems
,
Inc
.
*
Copyright
2008
GE
Intelligent
Platforms
Embedded
Systems
,
Inc
.
*
*
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
...
...
arch/powerpc/boot/dts/gef_sbc310.dts
浏览文件 @
59603b9a
/*
*
GE
Fanuc
SBC310
Device
Tree
Source
*
GE
SBC310
Device
Tree
Source
*
*
Copyright
2008
GE
Fanuc
Intelligent
Platforms
Embedded
Systems
,
Inc
.
*
Copyright
2008
GE
Intelligent
Platforms
Embedded
Systems
,
Inc
.
*
*
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
...
...
arch/powerpc/boot/dts/gef_sbc610.dts
浏览文件 @
59603b9a
/*
*
GE
Fanuc
SBC610
Device
Tree
Source
*
GE
SBC610
Device
Tree
Source
*
*
Copyright
2008
GE
Fanuc
Intelligent
Platforms
Embedded
Systems
,
Inc
.
*
Copyright
2008
GE
Intelligent
Platforms
Embedded
Systems
,
Inc
.
*
*
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
...
...
arch/powerpc/include/asm/perf_event.h
浏览文件 @
59603b9a
/*
* Performance event support -
PowerPC-specific definitions.
* Performance event support -
hardware-specific disambiguation
*
* Copyright 2008-2009 Paul Mackerras, IBM Corporation.
* For now this is a compile-time decision, but eventually it should be
* runtime. This would allow multiplatform perf event support for e300 (fsl
* embedded perf counters) plus server/classic, and would accommodate
* devices other than the core which provide their own performance counters.
*
* Copyright 2010 Freescale Semiconductor, Inc.
*
* 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/types.h>
#include <asm/hw_irq.h>
#define MAX_HWEVENTS 8
#define MAX_EVENT_ALTERNATIVES 8
#define MAX_LIMITED_HWCOUNTERS 2
/*
* This struct provides the constants and functions needed to
* describe the PMU on a particular POWER-family CPU.
*/
struct
power_pmu
{
const
char
*
name
;
int
n_counter
;
int
max_alternatives
;
unsigned
long
add_fields
;
unsigned
long
test_adder
;
int
(
*
compute_mmcr
)(
u64
events
[],
int
n_ev
,
unsigned
int
hwc
[],
unsigned
long
mmcr
[]);
int
(
*
get_constraint
)(
u64
event_id
,
unsigned
long
*
mskp
,
unsigned
long
*
valp
);
int
(
*
get_alternatives
)(
u64
event_id
,
unsigned
int
flags
,
u64
alt
[]);
void
(
*
disable_pmc
)(
unsigned
int
pmc
,
unsigned
long
mmcr
[]);
int
(
*
limited_pmc_event
)(
u64
event_id
);
u32
flags
;
int
n_generic
;
int
*
generic_events
;
int
(
*
cache_events
)[
PERF_COUNT_HW_CACHE_MAX
]
[
PERF_COUNT_HW_CACHE_OP_MAX
]
[
PERF_COUNT_HW_CACHE_RESULT_MAX
];
};
/*
* Values for power_pmu.flags
*/
#define PPMU_LIMITED_PMC5_6 1
/* PMC5/6 have limited function */
#define PPMU_ALT_SIPR 2
/* uses alternate posn for SIPR/HV */
/*
* Values for flags to get_alternatives()
*/
#define PPMU_LIMITED_PMC_OK 1
/* can put this on a limited PMC */
#define PPMU_LIMITED_PMC_REQD 2
/* have to put this on a limited PMC */
#define PPMU_ONLY_COUNT_RUN 4
/* only counting in run state */
extern
int
register_power_pmu
(
struct
power_pmu
*
);
struct
pt_regs
;
extern
unsigned
long
perf_misc_flags
(
struct
pt_regs
*
regs
);
extern
unsigned
long
perf_instruction_pointer
(
struct
pt_regs
*
regs
);
#define PERF_EVENT_INDEX_OFFSET 1
/*
* Only override the default definitions in include/linux/perf_event.h
* if we have hardware PMU support.
*/
#ifdef CONFIG_PPC_PERF_CTRS
#
define perf_misc_flags(regs) perf_misc_flags(regs)
#
include <asm/perf_event_server.h>
#endif
/*
* The power_pmu.get_constraint function returns a 32/64-bit value and
* a 32/64-bit mask that express the constraints between this event_id and
* other events.
*
* The value and mask are divided up into (non-overlapping) bitfields
* of three different types:
*
* Select field: this expresses the constraint that some set of bits
* in MMCR* needs to be set to a specific value for this event_id. For a
* select field, the mask contains 1s in every bit of the field, and
* the value contains a unique value for each possible setting of the
* MMCR* bits. The constraint checking code will ensure that two events
* that set the same field in their masks have the same value in their
* value dwords.
*
* Add field: this expresses the constraint that there can be at most
* N events in a particular class. A field of k bits can be used for
* N <= 2^(k-1) - 1. The mask has the most significant bit of the field
* set (and the other bits 0), and the value has only the least significant
* bit of the field set. In addition, the 'add_fields' and 'test_adder'
* in the struct power_pmu for this processor come into play. The
* add_fields value contains 1 in the LSB of the field, and the
* test_adder contains 2^(k-1) - 1 - N in the field.
*
* NAND field: this expresses the constraint that you may not have events
* in all of a set of classes. (For example, on PPC970, you can't select
* events from the FPU, ISU and IDU simultaneously, although any two are
* possible.) For N classes, the field is N+1 bits wide, and each class
* is assigned one bit from the least-significant N bits. The mask has
* only the most-significant bit set, and the value has only the bit
* for the event_id's class set. The test_adder has the least significant
* bit set in the field.
*
* If an event_id is not subject to the constraint expressed by a particular
* field, then it will have 0 in both the mask and value for that field.
*/
#ifdef CONFIG_FSL_EMB_PERF_EVENT
#include <asm/perf_event_fsl_emb.h>
#endif
arch/powerpc/include/asm/perf_event_fsl_emb.h
0 → 100644
浏览文件 @
59603b9a
/*
* Performance event support - Freescale embedded specific definitions.
*
* Copyright 2008-2009 Paul Mackerras, IBM Corporation.
* Copyright 2010 Freescale Semiconductor, Inc.
*
* 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/types.h>
#include <asm/hw_irq.h>
#define MAX_HWEVENTS 4
/* event flags */
#define FSL_EMB_EVENT_VALID 1
#define FSL_EMB_EVENT_RESTRICTED 2
/* upper half of event flags is PMLCb */
#define FSL_EMB_EVENT_THRESHMUL 0x0000070000000000ULL
#define FSL_EMB_EVENT_THRESH 0x0000003f00000000ULL
struct
fsl_emb_pmu
{
const
char
*
name
;
int
n_counter
;
/* total number of counters */
/*
* The number of contiguous counters starting at zero that
* can hold restricted events, or zero if there are no
* restricted events.
*
* This isn't a very flexible method of expressing constraints,
* but it's very simple and is adequate for existing chips.
*/
int
n_restricted
;
/* Returns event flags and PMLCb (FSL_EMB_EVENT_*) */
u64
(
*
xlate_event
)(
u64
event_id
);
int
n_generic
;
int
*
generic_events
;
int
(
*
cache_events
)[
PERF_COUNT_HW_CACHE_MAX
]
[
PERF_COUNT_HW_CACHE_OP_MAX
]
[
PERF_COUNT_HW_CACHE_RESULT_MAX
];
};
int
register_fsl_emb_pmu
(
struct
fsl_emb_pmu
*
);
arch/powerpc/include/asm/perf_event_server.h
0 → 100644
浏览文件 @
59603b9a
/*
* Performance event support - PowerPC classic/server specific definitions.
*
* Copyright 2008-2009 Paul Mackerras, IBM Corporation.
*
* 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/types.h>
#include <asm/hw_irq.h>
#define MAX_HWEVENTS 8
#define MAX_EVENT_ALTERNATIVES 8
#define MAX_LIMITED_HWCOUNTERS 2
/*
* This struct provides the constants and functions needed to
* describe the PMU on a particular POWER-family CPU.
*/
struct
power_pmu
{
const
char
*
name
;
int
n_counter
;
int
max_alternatives
;
unsigned
long
add_fields
;
unsigned
long
test_adder
;
int
(
*
compute_mmcr
)(
u64
events
[],
int
n_ev
,
unsigned
int
hwc
[],
unsigned
long
mmcr
[]);
int
(
*
get_constraint
)(
u64
event_id
,
unsigned
long
*
mskp
,
unsigned
long
*
valp
);
int
(
*
get_alternatives
)(
u64
event_id
,
unsigned
int
flags
,
u64
alt
[]);
void
(
*
disable_pmc
)(
unsigned
int
pmc
,
unsigned
long
mmcr
[]);
int
(
*
limited_pmc_event
)(
u64
event_id
);
u32
flags
;
int
n_generic
;
int
*
generic_events
;
int
(
*
cache_events
)[
PERF_COUNT_HW_CACHE_MAX
]
[
PERF_COUNT_HW_CACHE_OP_MAX
]
[
PERF_COUNT_HW_CACHE_RESULT_MAX
];
};
/*
* Values for power_pmu.flags
*/
#define PPMU_LIMITED_PMC5_6 1
/* PMC5/6 have limited function */
#define PPMU_ALT_SIPR 2
/* uses alternate posn for SIPR/HV */
/*
* Values for flags to get_alternatives()
*/
#define PPMU_LIMITED_PMC_OK 1
/* can put this on a limited PMC */
#define PPMU_LIMITED_PMC_REQD 2
/* have to put this on a limited PMC */
#define PPMU_ONLY_COUNT_RUN 4
/* only counting in run state */
extern
int
register_power_pmu
(
struct
power_pmu
*
);
struct
pt_regs
;
extern
unsigned
long
perf_misc_flags
(
struct
pt_regs
*
regs
);
extern
unsigned
long
perf_instruction_pointer
(
struct
pt_regs
*
regs
);
#define PERF_EVENT_INDEX_OFFSET 1
/*
* Only override the default definitions in include/linux/perf_event.h
* if we have hardware PMU support.
*/
#ifdef CONFIG_PPC_PERF_CTRS
#define perf_misc_flags(regs) perf_misc_flags(regs)
#endif
/*
* The power_pmu.get_constraint function returns a 32/64-bit value and
* a 32/64-bit mask that express the constraints between this event_id and
* other events.
*
* The value and mask are divided up into (non-overlapping) bitfields
* of three different types:
*
* Select field: this expresses the constraint that some set of bits
* in MMCR* needs to be set to a specific value for this event_id. For a
* select field, the mask contains 1s in every bit of the field, and
* the value contains a unique value for each possible setting of the
* MMCR* bits. The constraint checking code will ensure that two events
* that set the same field in their masks have the same value in their
* value dwords.
*
* Add field: this expresses the constraint that there can be at most
* N events in a particular class. A field of k bits can be used for
* N <= 2^(k-1) - 1. The mask has the most significant bit of the field
* set (and the other bits 0), and the value has only the least significant
* bit of the field set. In addition, the 'add_fields' and 'test_adder'
* in the struct power_pmu for this processor come into play. The
* add_fields value contains 1 in the LSB of the field, and the
* test_adder contains 2^(k-1) - 1 - N in the field.
*
* NAND field: this expresses the constraint that you may not have events
* in all of a set of classes. (For example, on PPC970, you can't select
* events from the FPU, ISU and IDU simultaneously, although any two are
* possible.) For N classes, the field is N+1 bits wide, and each class
* is assigned one bit from the least-significant N bits. The mask has
* only the most-significant bit set, and the value has only the bit
* for the event_id's class set. The test_adder has the least significant
* bit set in the field.
*
* If an event_id is not subject to the constraint expressed by a particular
* field, then it will have 0 in both the mask and value for that field.
*/
arch/powerpc/include/asm/reg_fsl_emb.h
浏览文件 @
59603b9a
...
...
@@ -31,7 +31,7 @@
#define PMLCA_FCM0 0x08000000
/* Freeze when PMM==0 */
#define PMLCA_CE 0x04000000
/* Condition Enable */
#define PMLCA_EVENT_MASK 0x00
7
f0000
/* Event field */
#define PMLCA_EVENT_MASK 0x00
f
f0000
/* Event field */
#define PMLCA_EVENT_SHIFT 16
#define PMRN_PMLCB0 0x110
/* PM Local Control B0 */
...
...
arch/powerpc/kernel/Makefile
浏览文件 @
59603b9a
...
...
@@ -98,11 +98,16 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o
obj-$(CONFIG_DYNAMIC_FTRACE)
+=
ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER)
+=
ftrace.o
obj-$(CONFIG_PPC_PERF_CTRS)
+=
perf_event.o perf_callchain.o
obj-$(CONFIG_PERF_EVENTS)
+=
perf_callchain.o
obj-$(CONFIG_PPC_PERF_CTRS)
+=
perf_event.o
obj64-$(CONFIG_PPC_PERF_CTRS)
+=
power4-pmu.o ppc970-pmu.o power5-pmu.o
\
power5+-pmu.o power6-pmu.o power7-pmu.o
obj32-$(CONFIG_PPC_PERF_CTRS)
+=
mpc7450-pmu.o
obj-$(CONFIG_FSL_EMB_PERF_EVENT)
+=
perf_event_fsl_emb.o
obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500)
+=
e500-pmu.o
obj-$(CONFIG_8XX_MINIMAL_FPEMU)
+=
softemu8xx.o
ifneq
($(CONFIG_PPC_INDIRECT_IO),y)
...
...
arch/powerpc/kernel/cputable.c
浏览文件 @
59603b9a
...
...
@@ -1808,7 +1808,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.
icache_bsize
=
64
,
.
dcache_bsize
=
64
,
.
num_pmcs
=
4
,
.
oprofile_cpu_type
=
"ppc/e500
"
,
/* xxx - galak, e500mc? */
.
oprofile_cpu_type
=
"ppc/e500
mc"
,
.
oprofile_type
=
PPC_OPROFILE_FSL_EMB
,
.
cpu_setup
=
__setup_cpu_e500mc
,
.
machine_check
=
machine_check_e500
,
...
...
arch/powerpc/kernel/e500-pmu.c
0 → 100644
浏览文件 @
59603b9a
/*
* Performance counter support for e500 family processors.
*
* Copyright 2008-2009 Paul Mackerras, IBM Corporation.
* Copyright 2010 Freescale Semiconductor, Inc.
*
* 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/string.h>
#include <linux/perf_event.h>
#include <asm/reg.h>
#include <asm/cputable.h>
/*
* Map of generic hardware event types to hardware events
* Zero if unsupported
*/
static
int
e500_generic_events
[]
=
{
[
PERF_COUNT_HW_CPU_CYCLES
]
=
1
,
[
PERF_COUNT_HW_INSTRUCTIONS
]
=
2
,
[
PERF_COUNT_HW_CACHE_MISSES
]
=
41
,
/* Data L1 cache reloads */
[
PERF_COUNT_HW_BRANCH_INSTRUCTIONS
]
=
12
,
[
PERF_COUNT_HW_BRANCH_MISSES
]
=
15
,
};
#define C(x) PERF_COUNT_HW_CACHE_##x
/*
* Table of generalized cache-related events.
* 0 means not supported, -1 means nonsensical, other values
* are event codes.
*/
static
int
e500_cache_events
[
C
(
MAX
)][
C
(
OP_MAX
)][
C
(
RESULT_MAX
)]
=
{
/*
* D-cache misses are not split into read/write/prefetch;
* use raw event 41.
*/
[
C
(
L1D
)]
=
{
/* RESULT_ACCESS RESULT_MISS */
[
C
(
OP_READ
)]
=
{
27
,
0
},
[
C
(
OP_WRITE
)]
=
{
28
,
0
},
[
C
(
OP_PREFETCH
)]
=
{
29
,
0
},
},
[
C
(
L1I
)]
=
{
/* RESULT_ACCESS RESULT_MISS */
[
C
(
OP_READ
)]
=
{
2
,
60
},
[
C
(
OP_WRITE
)]
=
{
-
1
,
-
1
},
[
C
(
OP_PREFETCH
)]
=
{
0
,
0
},
},
/*
* Assuming LL means L2, it's not a good match for this model.
* It allocates only on L1 castout or explicit prefetch, and
* does not have separate read/write events (but it does have
* separate instruction/data events).
*/
[
C
(
LL
)]
=
{
/* RESULT_ACCESS RESULT_MISS */
[
C
(
OP_READ
)]
=
{
0
,
0
},
[
C
(
OP_WRITE
)]
=
{
0
,
0
},
[
C
(
OP_PREFETCH
)]
=
{
0
,
0
},
},
/*
* There are data/instruction MMU misses, but that's a miss on
* the chip's internal level-one TLB which is probably not
* what the user wants. Instead, unified level-two TLB misses
* are reported here.
*/
[
C
(
DTLB
)]
=
{
/* RESULT_ACCESS RESULT_MISS */
[
C
(
OP_READ
)]
=
{
26
,
66
},
[
C
(
OP_WRITE
)]
=
{
-
1
,
-
1
},
[
C
(
OP_PREFETCH
)]
=
{
-
1
,
-
1
},
},
[
C
(
BPU
)]
=
{
/* RESULT_ACCESS RESULT_MISS */
[
C
(
OP_READ
)]
=
{
12
,
15
},
[
C
(
OP_WRITE
)]
=
{
-
1
,
-
1
},
[
C
(
OP_PREFETCH
)]
=
{
-
1
,
-
1
},
},
};
static
int
num_events
=
128
;
/* Upper half of event id is PMLCb, for threshold events */
static
u64
e500_xlate_event
(
u64
event_id
)
{
u32
event_low
=
(
u32
)
event_id
;
u64
ret
;
if
(
event_low
>=
num_events
)
return
0
;
ret
=
FSL_EMB_EVENT_VALID
;
if
(
event_low
>=
76
&&
event_low
<=
81
)
{
ret
|=
FSL_EMB_EVENT_RESTRICTED
;
ret
|=
event_id
&
(
FSL_EMB_EVENT_THRESHMUL
|
FSL_EMB_EVENT_THRESH
);
}
else
if
(
event_id
&
(
FSL_EMB_EVENT_THRESHMUL
|
FSL_EMB_EVENT_THRESH
))
{
/* Threshold requested on non-threshold event */
return
0
;
}
return
ret
;
}
static
struct
fsl_emb_pmu
e500_pmu
=
{
.
name
=
"e500 family"
,
.
n_counter
=
4
,
.
n_restricted
=
2
,
.
xlate_event
=
e500_xlate_event
,
.
n_generic
=
ARRAY_SIZE
(
e500_generic_events
),
.
generic_events
=
e500_generic_events
,
.
cache_events
=
&
e500_cache_events
,
};
static
int
init_e500_pmu
(
void
)
{
if
(
!
cur_cpu_spec
->
oprofile_cpu_type
)
return
-
ENODEV
;
if
(
!
strcmp
(
cur_cpu_spec
->
oprofile_cpu_type
,
"ppc/e500mc"
))
num_events
=
256
;
else
if
(
strcmp
(
cur_cpu_spec
->
oprofile_cpu_type
,
"ppc/e500"
))
return
-
ENODEV
;
return
register_fsl_emb_pmu
(
&
e500_pmu
);
}
arch_initcall
(
init_e500_pmu
);
arch/powerpc/kernel/perf_event_fsl_emb.c
0 → 100644
浏览文件 @
59603b9a
/*
* Performance event support - Freescale Embedded Performance Monitor
*
* Copyright 2008-2009 Paul Mackerras, IBM Corporation.
* Copyright 2010 Freescale Semiconductor, Inc.
*
* 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/kernel.h>
#include <linux/sched.h>
#include <linux/perf_event.h>
#include <linux/percpu.h>
#include <linux/hardirq.h>
#include <asm/reg_fsl_emb.h>
#include <asm/pmc.h>
#include <asm/machdep.h>
#include <asm/firmware.h>
#include <asm/ptrace.h>
struct
cpu_hw_events
{
int
n_events
;
int
disabled
;
u8
pmcs_enabled
;
struct
perf_event
*
event
[
MAX_HWEVENTS
];
};
static
DEFINE_PER_CPU
(
struct
cpu_hw_events
,
cpu_hw_events
);
static
struct
fsl_emb_pmu
*
ppmu
;
/* Number of perf_events counting hardware events */
static
atomic_t
num_events
;
/* Used to avoid races in calling reserve/release_pmc_hardware */
static
DEFINE_MUTEX
(
pmc_reserve_mutex
);
/*
* If interrupts were soft-disabled when a PMU interrupt occurs, treat
* it as an NMI.
*/
static
inline
int
perf_intr_is_nmi
(
struct
pt_regs
*
regs
)
{
#ifdef __powerpc64__
return
!
regs
->
softe
;
#else
return
0
;
#endif
}
static
void
perf_event_interrupt
(
struct
pt_regs
*
regs
);
/*
* Read one performance monitor counter (PMC).
*/
static
unsigned
long
read_pmc
(
int
idx
)
{
unsigned
long
val
;
switch
(
idx
)
{
case
0
:
val
=
mfpmr
(
PMRN_PMC0
);
break
;
case
1
:
val
=
mfpmr
(
PMRN_PMC1
);
break
;
case
2
:
val
=
mfpmr
(
PMRN_PMC2
);
break
;
case
3
:
val
=
mfpmr
(
PMRN_PMC3
);
break
;
default:
printk
(
KERN_ERR
"oops trying to read PMC%d
\n
"
,
idx
);
val
=
0
;
}
return
val
;
}
/*
* Write one PMC.
*/
static
void
write_pmc
(
int
idx
,
unsigned
long
val
)
{
switch
(
idx
)
{
case
0
:
mtpmr
(
PMRN_PMC0
,
val
);
break
;
case
1
:
mtpmr
(
PMRN_PMC1
,
val
);
break
;
case
2
:
mtpmr
(
PMRN_PMC2
,
val
);
break
;
case
3
:
mtpmr
(
PMRN_PMC3
,
val
);
break
;
default:
printk
(
KERN_ERR
"oops trying to write PMC%d
\n
"
,
idx
);
}
isync
();
}
/*
* Write one local control A register
*/
static
void
write_pmlca
(
int
idx
,
unsigned
long
val
)
{
switch
(
idx
)
{
case
0
:
mtpmr
(
PMRN_PMLCA0
,
val
);
break
;
case
1
:
mtpmr
(
PMRN_PMLCA1
,
val
);
break
;
case
2
:
mtpmr
(
PMRN_PMLCA2
,
val
);
break
;
case
3
:
mtpmr
(
PMRN_PMLCA3
,
val
);
break
;
default:
printk
(
KERN_ERR
"oops trying to write PMLCA%d
\n
"
,
idx
);
}
isync
();
}
/*
* Write one local control B register
*/
static
void
write_pmlcb
(
int
idx
,
unsigned
long
val
)
{
switch
(
idx
)
{
case
0
:
mtpmr
(
PMRN_PMLCB0
,
val
);
break
;
case
1
:
mtpmr
(
PMRN_PMLCB1
,
val
);
break
;
case
2
:
mtpmr
(
PMRN_PMLCB2
,
val
);
break
;
case
3
:
mtpmr
(
PMRN_PMLCB3
,
val
);
break
;
default:
printk
(
KERN_ERR
"oops trying to write PMLCB%d
\n
"
,
idx
);
}
isync
();
}
static
void
fsl_emb_pmu_read
(
struct
perf_event
*
event
)
{
s64
val
,
delta
,
prev
;
/*
* Performance monitor interrupts come even when interrupts
* are soft-disabled, as long as interrupts are hard-enabled.
* Therefore we treat them like NMIs.
*/
do
{
prev
=
atomic64_read
(
&
event
->
hw
.
prev_count
);
barrier
();
val
=
read_pmc
(
event
->
hw
.
idx
);
}
while
(
atomic64_cmpxchg
(
&
event
->
hw
.
prev_count
,
prev
,
val
)
!=
prev
);
/* The counters are only 32 bits wide */
delta
=
(
val
-
prev
)
&
0xfffffffful
;
atomic64_add
(
delta
,
&
event
->
count
);
atomic64_sub
(
delta
,
&
event
->
hw
.
period_left
);
}
/*
* Disable all events to prevent PMU interrupts and to allow
* events to be added or removed.
*/
void
hw_perf_disable
(
void
)
{
struct
cpu_hw_events
*
cpuhw
;
unsigned
long
flags
;
local_irq_save
(
flags
);
cpuhw
=
&
__get_cpu_var
(
cpu_hw_events
);
if
(
!
cpuhw
->
disabled
)
{
cpuhw
->
disabled
=
1
;
/*
* Check if we ever enabled the PMU on this cpu.
*/
if
(
!
cpuhw
->
pmcs_enabled
)
{
ppc_enable_pmcs
();
cpuhw
->
pmcs_enabled
=
1
;
}
if
(
atomic_read
(
&
num_events
))
{
/*
* Set the 'freeze all counters' bit, and disable
* interrupts. The barrier is to make sure the
* mtpmr has been executed and the PMU has frozen
* the events before we return.
*/
mtpmr
(
PMRN_PMGC0
,
PMGC0_FAC
);
isync
();
}
}
local_irq_restore
(
flags
);
}
/*
* Re-enable all events if disable == 0.
* If we were previously disabled and events were added, then
* put the new config on the PMU.
*/
void
hw_perf_enable
(
void
)
{
struct
cpu_hw_events
*
cpuhw
;
unsigned
long
flags
;
local_irq_save
(
flags
);
cpuhw
=
&
__get_cpu_var
(
cpu_hw_events
);
if
(
!
cpuhw
->
disabled
)
goto
out
;
cpuhw
->
disabled
=
0
;
ppc_set_pmu_inuse
(
cpuhw
->
n_events
!=
0
);
if
(
cpuhw
->
n_events
>
0
)
{
mtpmr
(
PMRN_PMGC0
,
PMGC0_PMIE
|
PMGC0_FCECE
);
isync
();
}
out:
local_irq_restore
(
flags
);
}
static
int
collect_events
(
struct
perf_event
*
group
,
int
max_count
,
struct
perf_event
*
ctrs
[])
{
int
n
=
0
;
struct
perf_event
*
event
;
if
(
!
is_software_event
(
group
))
{
if
(
n
>=
max_count
)
return
-
1
;
ctrs
[
n
]
=
group
;
n
++
;
}
list_for_each_entry
(
event
,
&
group
->
sibling_list
,
group_entry
)
{
if
(
!
is_software_event
(
event
)
&&
event
->
state
!=
PERF_EVENT_STATE_OFF
)
{
if
(
n
>=
max_count
)
return
-
1
;
ctrs
[
n
]
=
event
;
n
++
;
}
}
return
n
;
}
/* perf must be disabled, context locked on entry */
static
int
fsl_emb_pmu_enable
(
struct
perf_event
*
event
)
{
struct
cpu_hw_events
*
cpuhw
;
int
ret
=
-
EAGAIN
;
int
num_counters
=
ppmu
->
n_counter
;
u64
val
;
int
i
;
cpuhw
=
&
get_cpu_var
(
cpu_hw_events
);
if
(
event
->
hw
.
config
&
FSL_EMB_EVENT_RESTRICTED
)
num_counters
=
ppmu
->
n_restricted
;
/*
* Allocate counters from top-down, so that restricted-capable
* counters are kept free as long as possible.
*/
for
(
i
=
num_counters
-
1
;
i
>=
0
;
i
--
)
{
if
(
cpuhw
->
event
[
i
])
continue
;
break
;
}
if
(
i
<
0
)
goto
out
;
event
->
hw
.
idx
=
i
;
cpuhw
->
event
[
i
]
=
event
;
++
cpuhw
->
n_events
;
val
=
0
;
if
(
event
->
hw
.
sample_period
)
{
s64
left
=
atomic64_read
(
&
event
->
hw
.
period_left
);
if
(
left
<
0x80000000L
)
val
=
0x80000000L
-
left
;
}
atomic64_set
(
&
event
->
hw
.
prev_count
,
val
);
write_pmc
(
i
,
val
);
perf_event_update_userpage
(
event
);
write_pmlcb
(
i
,
event
->
hw
.
config
>>
32
);
write_pmlca
(
i
,
event
->
hw
.
config_base
);
ret
=
0
;
out:
put_cpu_var
(
cpu_hw_events
);
return
ret
;
}
/* perf must be disabled, context locked on entry */
static
void
fsl_emb_pmu_disable
(
struct
perf_event
*
event
)
{
struct
cpu_hw_events
*
cpuhw
;
int
i
=
event
->
hw
.
idx
;
if
(
i
<
0
)
goto
out
;
fsl_emb_pmu_read
(
event
);
cpuhw
=
&
get_cpu_var
(
cpu_hw_events
);
WARN_ON
(
event
!=
cpuhw
->
event
[
event
->
hw
.
idx
]);
write_pmlca
(
i
,
0
);
write_pmlcb
(
i
,
0
);
write_pmc
(
i
,
0
);
cpuhw
->
event
[
i
]
=
NULL
;
event
->
hw
.
idx
=
-
1
;
/*
* TODO: if at least one restricted event exists, and we
* just freed up a non-restricted-capable counter, and
* there is a restricted-capable counter occupied by
* a non-restricted event, migrate that event to the
* vacated counter.
*/
cpuhw
->
n_events
--
;
out:
put_cpu_var
(
cpu_hw_events
);
}
/*
* Re-enable interrupts on a event after they were throttled
* because they were coming too fast.
*
* Context is locked on entry, but perf is not disabled.
*/
static
void
fsl_emb_pmu_unthrottle
(
struct
perf_event
*
event
)
{
s64
val
,
left
;
unsigned
long
flags
;
if
(
event
->
hw
.
idx
<
0
||
!
event
->
hw
.
sample_period
)
return
;
local_irq_save
(
flags
);
perf_disable
();
fsl_emb_pmu_read
(
event
);
left
=
event
->
hw
.
sample_period
;
event
->
hw
.
last_period
=
left
;
val
=
0
;
if
(
left
<
0x80000000L
)
val
=
0x80000000L
-
left
;
write_pmc
(
event
->
hw
.
idx
,
val
);
atomic64_set
(
&
event
->
hw
.
prev_count
,
val
);
atomic64_set
(
&
event
->
hw
.
period_left
,
left
);
perf_event_update_userpage
(
event
);
perf_enable
();
local_irq_restore
(
flags
);
}
static
struct
pmu
fsl_emb_pmu
=
{
.
enable
=
fsl_emb_pmu_enable
,
.
disable
=
fsl_emb_pmu_disable
,
.
read
=
fsl_emb_pmu_read
,
.
unthrottle
=
fsl_emb_pmu_unthrottle
,
};
/*
* Release the PMU if this is the last perf_event.
*/
static
void
hw_perf_event_destroy
(
struct
perf_event
*
event
)
{
if
(
!
atomic_add_unless
(
&
num_events
,
-
1
,
1
))
{
mutex_lock
(
&
pmc_reserve_mutex
);
if
(
atomic_dec_return
(
&
num_events
)
==
0
)
release_pmc_hardware
();
mutex_unlock
(
&
pmc_reserve_mutex
);
}
}
/*
* Translate a generic cache event_id config to a raw event_id code.
*/
static
int
hw_perf_cache_event
(
u64
config
,
u64
*
eventp
)
{
unsigned
long
type
,
op
,
result
;
int
ev
;
if
(
!
ppmu
->
cache_events
)
return
-
EINVAL
;
/* unpack config */
type
=
config
&
0xff
;
op
=
(
config
>>
8
)
&
0xff
;
result
=
(
config
>>
16
)
&
0xff
;
if
(
type
>=
PERF_COUNT_HW_CACHE_MAX
||
op
>=
PERF_COUNT_HW_CACHE_OP_MAX
||
result
>=
PERF_COUNT_HW_CACHE_RESULT_MAX
)
return
-
EINVAL
;
ev
=
(
*
ppmu
->
cache_events
)[
type
][
op
][
result
];
if
(
ev
==
0
)
return
-
EOPNOTSUPP
;
if
(
ev
==
-
1
)
return
-
EINVAL
;
*
eventp
=
ev
;
return
0
;
}
const
struct
pmu
*
hw_perf_event_init
(
struct
perf_event
*
event
)
{
u64
ev
;
struct
perf_event
*
events
[
MAX_HWEVENTS
];
int
n
;
int
err
;
int
num_restricted
;
int
i
;
switch
(
event
->
attr
.
type
)
{
case
PERF_TYPE_HARDWARE
:
ev
=
event
->
attr
.
config
;
if
(
ev
>=
ppmu
->
n_generic
||
ppmu
->
generic_events
[
ev
]
==
0
)
return
ERR_PTR
(
-
EOPNOTSUPP
);
ev
=
ppmu
->
generic_events
[
ev
];
break
;
case
PERF_TYPE_HW_CACHE
:
err
=
hw_perf_cache_event
(
event
->
attr
.
config
,
&
ev
);
if
(
err
)
return
ERR_PTR
(
err
);
break
;
case
PERF_TYPE_RAW
:
ev
=
event
->
attr
.
config
;
break
;
default:
return
ERR_PTR
(
-
EINVAL
);
}
event
->
hw
.
config
=
ppmu
->
xlate_event
(
ev
);
if
(
!
(
event
->
hw
.
config
&
FSL_EMB_EVENT_VALID
))
return
ERR_PTR
(
-
EINVAL
);
/*
* If this is in a group, check if it can go on with all the
* other hardware events in the group. We assume the event
* hasn't been linked into its leader's sibling list at this point.
*/
n
=
0
;
if
(
event
->
group_leader
!=
event
)
{
n
=
collect_events
(
event
->
group_leader
,
ppmu
->
n_counter
-
1
,
events
);
if
(
n
<
0
)
return
ERR_PTR
(
-
EINVAL
);
}
if
(
event
->
hw
.
config
&
FSL_EMB_EVENT_RESTRICTED
)
{
num_restricted
=
0
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
if
(
events
[
i
]
->
hw
.
config
&
FSL_EMB_EVENT_RESTRICTED
)
num_restricted
++
;
}
if
(
num_restricted
>=
ppmu
->
n_restricted
)
return
ERR_PTR
(
-
EINVAL
);
}
event
->
hw
.
idx
=
-
1
;
event
->
hw
.
config_base
=
PMLCA_CE
|
PMLCA_FCM1
|
(
u32
)((
ev
<<
16
)
&
PMLCA_EVENT_MASK
);
if
(
event
->
attr
.
exclude_user
)
event
->
hw
.
config_base
|=
PMLCA_FCU
;
if
(
event
->
attr
.
exclude_kernel
)
event
->
hw
.
config_base
|=
PMLCA_FCS
;
if
(
event
->
attr
.
exclude_idle
)
return
ERR_PTR
(
-
ENOTSUPP
);
event
->
hw
.
last_period
=
event
->
hw
.
sample_period
;
atomic64_set
(
&
event
->
hw
.
period_left
,
event
->
hw
.
last_period
);
/*
* See if we need to reserve the PMU.
* If no events are currently in use, then we have to take a
* mutex to ensure that we don't race with another task doing
* reserve_pmc_hardware or release_pmc_hardware.
*/
err
=
0
;
if
(
!
atomic_inc_not_zero
(
&
num_events
))
{
mutex_lock
(
&
pmc_reserve_mutex
);
if
(
atomic_read
(
&
num_events
)
==
0
&&
reserve_pmc_hardware
(
perf_event_interrupt
))
err
=
-
EBUSY
;
else
atomic_inc
(
&
num_events
);
mutex_unlock
(
&
pmc_reserve_mutex
);
mtpmr
(
PMRN_PMGC0
,
PMGC0_FAC
);
isync
();
}
event
->
destroy
=
hw_perf_event_destroy
;
if
(
err
)
return
ERR_PTR
(
err
);
return
&
fsl_emb_pmu
;
}
/*
* A counter has overflowed; update its count and record
* things if requested. Note that interrupts are hard-disabled
* here so there is no possibility of being interrupted.
*/
static
void
record_and_restart
(
struct
perf_event
*
event
,
unsigned
long
val
,
struct
pt_regs
*
regs
,
int
nmi
)
{
u64
period
=
event
->
hw
.
sample_period
;
s64
prev
,
delta
,
left
;
int
record
=
0
;
/* we don't have to worry about interrupts here */
prev
=
atomic64_read
(
&
event
->
hw
.
prev_count
);
delta
=
(
val
-
prev
)
&
0xfffffffful
;
atomic64_add
(
delta
,
&
event
->
count
);
/*
* See if the total period for this event has expired,
* and update for the next period.
*/
val
=
0
;
left
=
atomic64_read
(
&
event
->
hw
.
period_left
)
-
delta
;
if
(
period
)
{
if
(
left
<=
0
)
{
left
+=
period
;
if
(
left
<=
0
)
left
=
period
;
record
=
1
;
}
if
(
left
<
0x80000000LL
)
val
=
0x80000000LL
-
left
;
}
/*
* Finally record data if requested.
*/
if
(
record
)
{
struct
perf_sample_data
data
=
{
.
period
=
event
->
hw
.
last_period
,
};
if
(
perf_event_overflow
(
event
,
nmi
,
&
data
,
regs
))
{
/*
* Interrupts are coming too fast - throttle them
* by setting the event to 0, so it will be
* at least 2^30 cycles until the next interrupt
* (assuming each event counts at most 2 counts
* per cycle).
*/
val
=
0
;
left
=
~
0ULL
>>
1
;
}
}
write_pmc
(
event
->
hw
.
idx
,
val
);
atomic64_set
(
&
event
->
hw
.
prev_count
,
val
);
atomic64_set
(
&
event
->
hw
.
period_left
,
left
);
perf_event_update_userpage
(
event
);
}
static
void
perf_event_interrupt
(
struct
pt_regs
*
regs
)
{
int
i
;
struct
cpu_hw_events
*
cpuhw
=
&
__get_cpu_var
(
cpu_hw_events
);
struct
perf_event
*
event
;
unsigned
long
val
;
int
found
=
0
;
int
nmi
;
nmi
=
perf_intr_is_nmi
(
regs
);
if
(
nmi
)
nmi_enter
();
else
irq_enter
();
for
(
i
=
0
;
i
<
ppmu
->
n_counter
;
++
i
)
{
event
=
cpuhw
->
event
[
i
];
val
=
read_pmc
(
i
);
if
((
int
)
val
<
0
)
{
if
(
event
)
{
/* event has overflowed */
found
=
1
;
record_and_restart
(
event
,
val
,
regs
,
nmi
);
}
else
{
/*
* Disabled counter is negative,
* reset it just in case.
*/
write_pmc
(
i
,
0
);
}
}
}
/* PMM will keep counters frozen until we return from the interrupt. */
mtmsr
(
mfmsr
()
|
MSR_PMM
);
mtpmr
(
PMRN_PMGC0
,
PMGC0_PMIE
|
PMGC0_FCECE
);
isync
();
if
(
nmi
)
nmi_exit
();
else
irq_exit
();
}
void
hw_perf_event_setup
(
int
cpu
)
{
struct
cpu_hw_events
*
cpuhw
=
&
per_cpu
(
cpu_hw_events
,
cpu
);
memset
(
cpuhw
,
0
,
sizeof
(
*
cpuhw
));
}
int
register_fsl_emb_pmu
(
struct
fsl_emb_pmu
*
pmu
)
{
if
(
ppmu
)
return
-
EBUSY
;
/* something's already registered */
ppmu
=
pmu
;
pr_info
(
"%s performance monitor hardware support registered
\n
"
,
pmu
->
name
);
return
0
;
}
arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
浏览文件 @
59603b9a
...
...
@@ -24,7 +24,7 @@
#include "pq2.h"
static
DEFINE_SPINLOCK
(
pci_pic_lock
);
static
DEFINE_
RAW_
SPINLOCK
(
pci_pic_lock
);
struct
pq2ads_pci_pic
{
struct
device_node
*
node
;
...
...
@@ -45,12 +45,12 @@ static void pq2ads_pci_mask_irq(unsigned int virq)
if
(
irq
!=
-
1
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
pci_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
pci_pic_lock
,
flags
);
setbits32
(
&
priv
->
regs
->
mask
,
1
<<
irq
);
mb
();
spin_unlock_irqrestore
(
&
pci_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
pci_pic_lock
,
flags
);
}
}
...
...
@@ -62,9 +62,9 @@ static void pq2ads_pci_unmask_irq(unsigned int virq)
if
(
irq
!=
-
1
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
pci_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
pci_pic_lock
,
flags
);
clrbits32
(
&
priv
->
regs
->
mask
,
1
<<
irq
);
spin_unlock_irqrestore
(
&
pci_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
pci_pic_lock
,
flags
);
}
}
...
...
arch/powerpc/platforms/85xx/socrates_fpga_pic.c
浏览文件 @
59603b9a
...
...
@@ -50,7 +50,7 @@ static struct socrates_fpga_irq_info fpga_irqs[SOCRATES_FPGA_NUM_IRQS] = {
#define socrates_fpga_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
static
DEFINE_SPINLOCK
(
socrates_fpga_pic_lock
);
static
DEFINE_
RAW_
SPINLOCK
(
socrates_fpga_pic_lock
);
static
void
__iomem
*
socrates_fpga_pic_iobase
;
static
struct
irq_host
*
socrates_fpga_pic_irq_host
;
...
...
@@ -80,9 +80,9 @@ static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq)
if
(
i
==
3
)
return
NO_IRQ
;
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
cause
=
socrates_fpga_pic_read
(
FPGA_PIC_IRQMASK
(
i
));
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
for
(
i
=
SOCRATES_FPGA_NUM_IRQS
-
1
;
i
>=
0
;
i
--
)
{
if
(
cause
>>
(
i
+
16
))
break
;
...
...
@@ -116,12 +116,12 @@ static void socrates_fpga_pic_ack(unsigned int virq)
hwirq
=
socrates_fpga_irq_to_hw
(
virq
);
irq_line
=
fpga_irqs
[
hwirq
].
irq_line
;
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
mask
=
socrates_fpga_pic_read
(
FPGA_PIC_IRQMASK
(
irq_line
))
&
SOCRATES_FPGA_IRQ_MASK
;
mask
|=
(
1
<<
(
hwirq
+
16
));
socrates_fpga_pic_write
(
FPGA_PIC_IRQMASK
(
irq_line
),
mask
);
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
}
static
void
socrates_fpga_pic_mask
(
unsigned
int
virq
)
...
...
@@ -134,12 +134,12 @@ static void socrates_fpga_pic_mask(unsigned int virq)
hwirq
=
socrates_fpga_irq_to_hw
(
virq
);
irq_line
=
fpga_irqs
[
hwirq
].
irq_line
;
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
mask
=
socrates_fpga_pic_read
(
FPGA_PIC_IRQMASK
(
irq_line
))
&
SOCRATES_FPGA_IRQ_MASK
;
mask
&=
~
(
1
<<
hwirq
);
socrates_fpga_pic_write
(
FPGA_PIC_IRQMASK
(
irq_line
),
mask
);
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
}
static
void
socrates_fpga_pic_mask_ack
(
unsigned
int
virq
)
...
...
@@ -152,13 +152,13 @@ static void socrates_fpga_pic_mask_ack(unsigned int virq)
hwirq
=
socrates_fpga_irq_to_hw
(
virq
);
irq_line
=
fpga_irqs
[
hwirq
].
irq_line
;
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
mask
=
socrates_fpga_pic_read
(
FPGA_PIC_IRQMASK
(
irq_line
))
&
SOCRATES_FPGA_IRQ_MASK
;
mask
&=
~
(
1
<<
hwirq
);
mask
|=
(
1
<<
(
hwirq
+
16
));
socrates_fpga_pic_write
(
FPGA_PIC_IRQMASK
(
irq_line
),
mask
);
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
}
static
void
socrates_fpga_pic_unmask
(
unsigned
int
virq
)
...
...
@@ -171,12 +171,12 @@ static void socrates_fpga_pic_unmask(unsigned int virq)
hwirq
=
socrates_fpga_irq_to_hw
(
virq
);
irq_line
=
fpga_irqs
[
hwirq
].
irq_line
;
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
mask
=
socrates_fpga_pic_read
(
FPGA_PIC_IRQMASK
(
irq_line
))
&
SOCRATES_FPGA_IRQ_MASK
;
mask
|=
(
1
<<
hwirq
);
socrates_fpga_pic_write
(
FPGA_PIC_IRQMASK
(
irq_line
),
mask
);
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
}
static
void
socrates_fpga_pic_eoi
(
unsigned
int
virq
)
...
...
@@ -189,12 +189,12 @@ static void socrates_fpga_pic_eoi(unsigned int virq)
hwirq
=
socrates_fpga_irq_to_hw
(
virq
);
irq_line
=
fpga_irqs
[
hwirq
].
irq_line
;
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
mask
=
socrates_fpga_pic_read
(
FPGA_PIC_IRQMASK
(
irq_line
))
&
SOCRATES_FPGA_IRQ_MASK
;
mask
|=
(
1
<<
(
hwirq
+
16
));
socrates_fpga_pic_write
(
FPGA_PIC_IRQMASK
(
irq_line
),
mask
);
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
}
static
int
socrates_fpga_pic_set_type
(
unsigned
int
virq
,
...
...
@@ -220,14 +220,14 @@ static int socrates_fpga_pic_set_type(unsigned int virq,
default:
return
-
EINVAL
;
}
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
mask
=
socrates_fpga_pic_read
(
FPGA_PIC_IRQCFG
);
if
(
polarity
)
mask
|=
(
1
<<
hwirq
);
else
mask
&=
~
(
1
<<
hwirq
);
socrates_fpga_pic_write
(
FPGA_PIC_IRQCFG
,
mask
);
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
return
0
;
}
...
...
@@ -314,14 +314,14 @@ void socrates_fpga_pic_init(struct device_node *pic)
socrates_fpga_pic_iobase
=
of_iomap
(
pic
,
0
);
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
socrates_fpga_pic_lock
,
flags
);
socrates_fpga_pic_write
(
FPGA_PIC_IRQMASK
(
0
),
SOCRATES_FPGA_IRQ_MASK
<<
16
);
socrates_fpga_pic_write
(
FPGA_PIC_IRQMASK
(
1
),
SOCRATES_FPGA_IRQ_MASK
<<
16
);
socrates_fpga_pic_write
(
FPGA_PIC_IRQMASK
(
2
),
SOCRATES_FPGA_IRQ_MASK
<<
16
);
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
socrates_fpga_pic_lock
,
flags
);
pr_info
(
"FPGA PIC: Setting up Socrates FPGA PIC
\n
"
);
}
arch/powerpc/platforms/86xx/Kconfig
浏览文件 @
59603b9a
...
...
@@ -33,32 +33,32 @@ config MPC8610_HPCD
This option enables support for the MPC8610 HPCD board.
config GEF_PPC9A
bool "GE
Fanuc
PPC9A"
bool "GE PPC9A"
select DEFAULT_UIMAGE
select MMIO_NVRAM
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
help
This option enables support for
GE Fanuc's
PPC9A.
This option enables support for
the GE
PPC9A.
config GEF_SBC310
bool "GE
Fanuc
SBC310"
bool "GE SBC310"
select DEFAULT_UIMAGE
select MMIO_NVRAM
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
help
This option enables support for
GE Fanuc's
SBC310.
This option enables support for
the GE
SBC310.
config GEF_SBC610
bool "GE
Fanuc
SBC610"
bool "GE SBC610"
select DEFAULT_UIMAGE
select MMIO_NVRAM
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
select HAS_RAPIDIO
help
This option enables support for
GE Fanuc's
SBC610.
This option enables support for
the GE
SBC610.
endif
...
...
arch/powerpc/platforms/86xx/gef_gpio.c
浏览文件 @
59603b9a
/*
* Driver for GE F
anuc's FPGA based GPIO pins
* Driver for GE F
PGA based GPIO
*
* Author: Martyn Welch <martyn.welch@ge
fanuc
.com>
* Author: Martyn Welch <martyn.welch@ge.com>
*
* 2008 (c) GE
Fanuc
Intelligent Platforms Embedded Systems, Inc.
* 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
*
* 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
...
...
@@ -164,6 +164,6 @@ static int __init gef_gpio_init(void)
};
arch_initcall
(
gef_gpio_init
);
MODULE_DESCRIPTION
(
"GE
Fanuc
I/O FPGA GPIO driver"
);
MODULE_AUTHOR
(
"Martyn Welch <martyn.welch@ge
fanuc
.com"
);
MODULE_DESCRIPTION
(
"GE I/O FPGA GPIO driver"
);
MODULE_AUTHOR
(
"Martyn Welch <martyn.welch@ge.com"
);
MODULE_LICENSE
(
"GPL"
);
arch/powerpc/platforms/86xx/gef_pic.c
浏览文件 @
59603b9a
/*
* Interrupt handling for GE F
anuc's F
PGA based PIC
* Interrupt handling for GE FPGA based PIC
*
* Author: Martyn Welch <martyn.welch@ge
fanuc
.com>
* Author: Martyn Welch <martyn.welch@ge.com>
*
* 2008 (c) GE
Fanuc
Intelligent Platforms Embedded Systems, Inc.
* 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
*
* 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
...
...
@@ -49,7 +49,7 @@
#define gef_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
static
DEFINE_SPINLOCK
(
gef_pic_lock
);
static
DEFINE_
RAW_
SPINLOCK
(
gef_pic_lock
);
static
void
__iomem
*
gef_pic_irq_reg_base
;
static
struct
irq_host
*
gef_pic_irq_host
;
...
...
@@ -118,11 +118,11 @@ static void gef_pic_mask(unsigned int virq)
hwirq
=
gef_irq_to_hw
(
virq
);
spin_lock_irqsave
(
&
gef_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
gef_pic_lock
,
flags
);
mask
=
in_be32
(
gef_pic_irq_reg_base
+
GEF_PIC_INTR_MASK
(
0
));
mask
&=
~
(
1
<<
hwirq
);
out_be32
(
gef_pic_irq_reg_base
+
GEF_PIC_INTR_MASK
(
0
),
mask
);
spin_unlock_irqrestore
(
&
gef_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
gef_pic_lock
,
flags
);
}
static
void
gef_pic_mask_ack
(
unsigned
int
virq
)
...
...
@@ -141,11 +141,11 @@ static void gef_pic_unmask(unsigned int virq)
hwirq
=
gef_irq_to_hw
(
virq
);
spin_lock_irqsave
(
&
gef_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
gef_pic_lock
,
flags
);
mask
=
in_be32
(
gef_pic_irq_reg_base
+
GEF_PIC_INTR_MASK
(
0
));
mask
|=
(
1
<<
hwirq
);
out_be32
(
gef_pic_irq_reg_base
+
GEF_PIC_INTR_MASK
(
0
),
mask
);
spin_unlock_irqrestore
(
&
gef_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
gef_pic_lock
,
flags
);
}
static
struct
irq_chip
gef_pic_chip
=
{
...
...
@@ -199,7 +199,7 @@ void __init gef_pic_init(struct device_node *np)
/* Map the devices registers into memory */
gef_pic_irq_reg_base
=
of_iomap
(
np
,
0
);
spin_lock_irqsave
(
&
gef_pic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
gef_pic_lock
,
flags
);
/* Initialise everything as masked. */
out_be32
(
gef_pic_irq_reg_base
+
GEF_PIC_CPU0_INTR_MASK
,
0
);
...
...
@@ -208,7 +208,7 @@ void __init gef_pic_init(struct device_node *np)
out_be32
(
gef_pic_irq_reg_base
+
GEF_PIC_CPU0_MCP_MASK
,
0
);
out_be32
(
gef_pic_irq_reg_base
+
GEF_PIC_CPU1_MCP_MASK
,
0
);
spin_unlock_irqrestore
(
&
gef_pic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
gef_pic_lock
,
flags
);
/* Map controller */
gef_pic_cascade_irq
=
irq_of_parse_and_map
(
np
,
0
);
...
...
arch/powerpc/platforms/86xx/gef_ppc9a.c
浏览文件 @
59603b9a
/*
* GE
Fanuc
PPC9A board support
* GE PPC9A board support
*
* Author: Martyn Welch <martyn.welch@ge
fanuc
.com>
* Author: Martyn Welch <martyn.welch@ge.com>
*
* Copyright 2008 GE
Fanuc
Intelligent Platforms Embedded Systems, Inc.
* Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
*
* 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
...
...
@@ -82,7 +82,7 @@ static void __init gef_ppc9a_setup_arch(void)
}
#endif
printk
(
KERN_INFO
"GE
Fanuc
Intelligent Platforms PPC9A 6U VME SBC
\n
"
);
printk
(
KERN_INFO
"GE Intelligent Platforms PPC9A 6U VME SBC
\n
"
);
#ifdef CONFIG_SMP
mpc86xx_smp_init
();
...
...
@@ -151,7 +151,7 @@ static void gef_ppc9a_show_cpuinfo(struct seq_file *m)
{
uint
svid
=
mfspr
(
SPRN_SVR
);
seq_printf
(
m
,
"Vendor
\t\t
: GE
Fanuc
Intelligent Platforms
\n
"
);
seq_printf
(
m
,
"Vendor
\t\t
: GE Intelligent Platforms
\n
"
);
seq_printf
(
m
,
"Revision
\t
: %u%c
\n
"
,
gef_ppc9a_get_pcb_rev
(),
(
'A'
+
gef_ppc9a_get_board_rev
()));
...
...
@@ -235,7 +235,7 @@ static int __init declare_of_platform_devices(void)
machine_device_initcall
(
gef_ppc9a
,
declare_of_platform_devices
);
define_machine
(
gef_ppc9a
)
{
.
name
=
"GE
Fanuc
PPC9A"
,
.
name
=
"GE PPC9A"
,
.
probe
=
gef_ppc9a_probe
,
.
setup_arch
=
gef_ppc9a_setup_arch
,
.
init_IRQ
=
gef_ppc9a_init_irq
,
...
...
arch/powerpc/platforms/86xx/gef_sbc310.c
浏览文件 @
59603b9a
/*
* GE
Fanuc
SBC310 board support
* GE SBC310 board support
*
* Author: Martyn Welch <martyn.welch@ge
fanuc
.com>
* Author: Martyn Welch <martyn.welch@ge.com>
*
* Copyright 2008 GE
Fanuc
Intelligent Platforms Embedded Systems, Inc.
* Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
*
* 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
...
...
@@ -82,7 +82,7 @@ static void __init gef_sbc310_setup_arch(void)
}
#endif
printk
(
KERN_INFO
"GE
Fanuc
Intelligent Platforms SBC310 6U VPX SBC
\n
"
);
printk
(
KERN_INFO
"GE Intelligent Platforms SBC310 6U VPX SBC
\n
"
);
#ifdef CONFIG_SMP
mpc86xx_smp_init
();
...
...
@@ -142,7 +142,7 @@ static void gef_sbc310_show_cpuinfo(struct seq_file *m)
{
uint
svid
=
mfspr
(
SPRN_SVR
);
seq_printf
(
m
,
"Vendor
\t\t
: GE
Fanuc
Intelligent Platforms
\n
"
);
seq_printf
(
m
,
"Vendor
\t\t
: GE Intelligent Platforms
\n
"
);
seq_printf
(
m
,
"Board ID
\t
: 0x%2.2x
\n
"
,
gef_sbc310_get_board_id
());
seq_printf
(
m
,
"Revision
\t
: %u%c
\n
"
,
gef_sbc310_get_pcb_rev
(),
...
...
@@ -223,7 +223,7 @@ static int __init declare_of_platform_devices(void)
machine_device_initcall
(
gef_sbc310
,
declare_of_platform_devices
);
define_machine
(
gef_sbc310
)
{
.
name
=
"GE
Fanuc
SBC310"
,
.
name
=
"GE SBC310"
,
.
probe
=
gef_sbc310_probe
,
.
setup_arch
=
gef_sbc310_setup_arch
,
.
init_IRQ
=
gef_sbc310_init_irq
,
...
...
arch/powerpc/platforms/86xx/gef_sbc610.c
浏览文件 @
59603b9a
/*
* GE
Fanuc
SBC610 board support
* GE SBC610 board support
*
* Author: Martyn Welch <martyn.welch@ge
fanuc
.com>
* Author: Martyn Welch <martyn.welch@ge.com>
*
* Copyright 2008 GE
Fanuc
Intelligent Platforms Embedded Systems, Inc.
* Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
*
* 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
...
...
@@ -82,7 +82,7 @@ static void __init gef_sbc610_setup_arch(void)
}
#endif
printk
(
KERN_INFO
"GE
Fanuc
Intelligent Platforms SBC610 6U VPX SBC
\n
"
);
printk
(
KERN_INFO
"GE Intelligent Platforms SBC610 6U VPX SBC
\n
"
);
#ifdef CONFIG_SMP
mpc86xx_smp_init
();
...
...
@@ -133,7 +133,7 @@ static void gef_sbc610_show_cpuinfo(struct seq_file *m)
{
uint
svid
=
mfspr
(
SPRN_SVR
);
seq_printf
(
m
,
"Vendor
\t\t
: GE
Fanuc
Intelligent Platforms
\n
"
);
seq_printf
(
m
,
"Vendor
\t\t
: GE Intelligent Platforms
\n
"
);
seq_printf
(
m
,
"Revision
\t
: %u%c
\n
"
,
gef_sbc610_get_pcb_rev
(),
(
'A'
+
gef_sbc610_get_board_rev
()
-
1
));
...
...
@@ -212,7 +212,7 @@ static int __init declare_of_platform_devices(void)
machine_device_initcall
(
gef_sbc610
,
declare_of_platform_devices
);
define_machine
(
gef_sbc610
)
{
.
name
=
"GE
Fanuc
SBC610"
,
.
name
=
"GE SBC610"
,
.
probe
=
gef_sbc610_probe
,
.
setup_arch
=
gef_sbc610_setup_arch
,
.
init_IRQ
=
gef_sbc610_init_irq
,
...
...
arch/powerpc/platforms/Kconfig.cputype
浏览文件 @
59603b9a
...
...
@@ -144,6 +144,16 @@ config FSL_EMB_PERFMON
and some e300 cores (c3 and c4). Select this only if your
core supports the Embedded Performance Monitor APU
config FSL_EMB_PERF_EVENT
bool
depends on FSL_EMB_PERFMON && PERF_EVENTS && !PPC_PERF_CTRS
default y
config FSL_EMB_PERF_EVENT_E500
bool
depends on FSL_EMB_PERF_EVENT && E500
default y
config 4xx
bool
depends on 40x || 44x
...
...
arch/powerpc/sysdev/cpm2_pic.h
浏览文件 @
59603b9a
...
...
@@ -3,6 +3,6 @@
extern
unsigned
int
cpm2_get_irq
(
void
);
extern
void
cpm2_pic_init
(
struct
device_node
*
);
extern
void
cpm2_pic_init
(
struct
device_node
*
);
#endif
/* _PPC_KERNEL_CPM2_H */
arch/powerpc/sysdev/qe_lib/qe_ic.c
浏览文件 @
59603b9a
...
...
@@ -33,7 +33,7 @@
#include "qe_ic.h"
static
DEFINE_SPINLOCK
(
qe_ic_lock
);
static
DEFINE_
RAW_
SPINLOCK
(
qe_ic_lock
);
static
struct
qe_ic_info
qe_ic_info
[]
=
{
[
1
]
=
{
...
...
@@ -201,13 +201,13 @@ static void qe_ic_unmask_irq(unsigned int virq)
unsigned
long
flags
;
u32
temp
;
spin_lock_irqsave
(
&
qe_ic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
qe_ic_lock
,
flags
);
temp
=
qe_ic_read
(
qe_ic
->
regs
,
qe_ic_info
[
src
].
mask_reg
);
qe_ic_write
(
qe_ic
->
regs
,
qe_ic_info
[
src
].
mask_reg
,
temp
|
qe_ic_info
[
src
].
mask
);
spin_unlock_irqrestore
(
&
qe_ic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
qe_ic_lock
,
flags
);
}
static
void
qe_ic_mask_irq
(
unsigned
int
virq
)
...
...
@@ -217,7 +217,7 @@ static void qe_ic_mask_irq(unsigned int virq)
unsigned
long
flags
;
u32
temp
;
spin_lock_irqsave
(
&
qe_ic_lock
,
flags
);
raw_
spin_lock_irqsave
(
&
qe_ic_lock
,
flags
);
temp
=
qe_ic_read
(
qe_ic
->
regs
,
qe_ic_info
[
src
].
mask_reg
);
qe_ic_write
(
qe_ic
->
regs
,
qe_ic_info
[
src
].
mask_reg
,
...
...
@@ -233,7 +233,7 @@ static void qe_ic_mask_irq(unsigned int virq)
*/
mb
();
spin_unlock_irqrestore
(
&
qe_ic_lock
,
flags
);
raw_
spin_unlock_irqrestore
(
&
qe_ic_lock
,
flags
);
}
static
struct
irq_chip
qe_ic_irq_chip
=
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录