Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
59603b9a
Commit
59603b9a
authored
Mar 09, 2010
by
Benjamin Herrenschmidt
Browse files
Options
Browse Files
Download
Plain Diff
Merge commit 'kumar/next' into merge
parents
57d54889
a1110654
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
1045 additions
and
174 deletions
+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
No files found.
arch/powerpc/boot/dts/gef_ppc9a.dts
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
=
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment