* [PATCH v4 10/11] powerpc/perf: add kconfig option for hypervisor provided counters
From: Cody P Schafer @ 2014-03-06 0:01 UTC (permalink / raw)
To: Linux PPC, Anshuman Khandual, Benjamin Herrenschmidt,
Cody P Schafer, Deepthi Dharwar, Gavin Shan, Lijun Pan, Li Zhong,
Michael Ellerman, Paul Bolle, Priyanka Jain, Srivatsa S. Bhat
Cc: Peter Zijlstra, LKML, Ingo Molnar, Paul Mackerras,
Arnaldo Carvalho de Melo, scottwood
In-Reply-To: <1394064082-6242-1-git-send-email-cody@linux.vnet.ibm.com>
Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
---
arch/powerpc/perf/Makefile | 2 ++
arch/powerpc/platforms/pseries/Kconfig | 12 ++++++++++++
2 files changed, 14 insertions(+)
diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile
index 60d71ee..f9c083a 100644
--- a/arch/powerpc/perf/Makefile
+++ b/arch/powerpc/perf/Makefile
@@ -11,5 +11,7 @@ obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o
obj-$(CONFIG_FSL_EMB_PERF_EVENT) += core-fsl-emb.o
obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o e6500-pmu.o
+obj-$(CONFIG_HV_PERF_CTRS) += hv-24x7.o hv-gpci.o hv-common.o
+
obj-$(CONFIG_PPC64) += $(obj64-y)
obj-$(CONFIG_PPC32) += $(obj32-y)
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 80b1d57..2cb8b77 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -111,6 +111,18 @@ config CMM
will be reused for other LPARs. The interface allows firmware to
balance memory across many LPARs.
+config HV_PERF_CTRS
+ bool "Hypervisor supplied PMU events (24x7 & GPCI)"
+ default y
+ depends on PERF_EVENTS && PPC_PSERIES
+ help
+ Enable access to hypervisor supplied counters in perf. Currently,
+ this enables code that uses the hcall GetPerfCounterInfo and 24x7
+ interfaces to retrieve counters. GPCI exists on Power 6 and later
+ systems. 24x7 is available on Power 8 systems.
+
+ If unsure, select Y.
+
config DTL
bool "Dispatch Trace Log"
depends on PPC_SPLPAR && DEBUG_FS
--
1.9.0
^ permalink raw reply related
* [PATCH v4 11/11] powerpc/perf/hv_{gpci, 24x7}: add documentation of device attributes
From: Cody P Schafer @ 2014-03-06 0:01 UTC (permalink / raw)
To: Linux PPC, Cody P Schafer
Cc: Rob Landley, linux-doc, Peter Zijlstra, LKML, Michael Ellerman,
Ingo Molnar, Paul Mackerras, Arnaldo Carvalho de Melo, scottwood
In-Reply-To: <1394064082-6242-1-git-send-email-cody@linux.vnet.ibm.com>
gpci and 24x7 expose some device specific attributes. Add some
documentation for them.
Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
---
.../testing/sysfs-bus-event_source-devices-hv_24x7 | 23 ++++++++++++
.../testing/sysfs-bus-event_source-devices-hv_gpci | 43 ++++++++++++++++++++++
2 files changed, 66 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7
create mode 100644 Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_gpci
diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7 b/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7
new file mode 100644
index 0000000..e78ee79
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7
@@ -0,0 +1,23 @@
+What: /sys/bus/event_source/devices/hv_24x7/interface/catalog
+Date: February 2014
+Contact: Cody P Schafer <cody@linux.vnet.ibm.com>
+Description:
+ Provides access to the binary "24x7 catalog" provided by the
+ hypervisor on POWER7 and 8 systems. This catalog lists events
+ avaliable from the powerpc "hv_24x7" pmu. Its format is
+ documented here:
+ https://raw.githubusercontent.com/jmesmon/catalog-24x7/master/hv-24x7-catalog.h
+
+What: /sys/bus/event_source/devices/hv_24x7/interface/catalog_length
+Date: February 2014
+Contact: Cody P Schafer <cody@linux.vnet.ibm.com>
+Description:
+ A number equal to the length in bytes of the catalog. This is
+ also extractable from the provided binary "catalog" sysfs entry.
+
+What: /sys/bus/event_source/devices/hv_24x7/interface/catalog_version
+Date: February 2014
+Contact: Cody P Schafer <cody@linux.vnet.ibm.com>
+Description:
+ Exposes the "version" field of the 24x7 catalog. This is also
+ extractable from the provided binary "catalog" sysfs entry.
diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_gpci b/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_gpci
new file mode 100644
index 0000000..3fa58c2
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_gpci
@@ -0,0 +1,43 @@
+What: /sys/bus/event_source/devices/hv_gpci/interface/collect_privileged
+Date: February 2014
+Contact: Cody P Schafer <cody@linux.vnet.ibm.com>
+Description:
+ '0' if the hypervisor is configured to forbid access to event
+ counters being accumulated by other guests and to physical
+ domain event counters.
+ '1' if that access is allowed.
+
+What: /sys/bus/event_source/devices/hv_gpci/interface/ga
+Date: February 2014
+Contact: Cody P Schafer <cody@linux.vnet.ibm.com>
+Description:
+ 0 or 1. Indicates whether we have access to "GA" events (listed
+ in arch/powerpc/perf/hv-gpci.h).
+
+What: /sys/bus/event_source/devices/hv_gpci/interface/expanded
+Date: February 2014
+Contact: Cody P Schafer <cody@linux.vnet.ibm.com>
+Description:
+ 0 or 1. Indicates whether we have access to "EXPANDED" events (listed
+ in arch/powerpc/perf/hv-gpci.h).
+
+What: /sys/bus/event_source/devices/hv_gpci/interface/lab
+Date: February 2014
+Contact: Cody P Schafer <cody@linux.vnet.ibm.com>
+Description:
+ 0 or 1. Indicates whether we have access to "LAB" events (listed
+ in arch/powerpc/perf/hv-gpci.h).
+
+What: /sys/bus/event_source/devices/hv_gpci/interface/version
+Date: February 2014
+Contact: Cody P Schafer <cody@linux.vnet.ibm.com>
+Description:
+ A number indicating the version of the gpci interface that the
+ hypervisor reports supporting.
+
+What: /sys/bus/event_source/devices/hv_gpci/interface/kernel_version
+Date: February 2014
+Contact: Cody P Schafer <cody@linux.vnet.ibm.com>
+Description:
+ A number indicating the latest version of the gpci interface
+ that the kernel is aware of.
--
1.9.0
^ permalink raw reply related
* Re: [PATCH v3 02/11] perf: add PMU_FORMAT_RANGE() helper for use by sw-like pmus
From: Cody P Schafer @ 2014-03-06 0:05 UTC (permalink / raw)
To: Michael Ellerman, Linux PPC, Arnaldo Carvalho de Melo,
Ingo Molnar, Paul Mackerras, Peter Zijlstra
Cc: Peter Zijlstra, scottwood, LKML
In-Reply-To: <53158A2F.8050605@linux.vnet.ibm.com>
On 03/04/2014 12:09 AM, Cody P Schafer wrote:
> On 03/03/2014 09:19 PM, Michael Ellerman wrote:
>> On Thu, 2014-27-02 at 21:04:55 UTC, Cody P Schafer wrote:
>>> Add PMU_FORMAT_RANGE() and PMU_FORMAT_RANGE_RESERVED() (for reserved
>>> areas) which generate functions to extract the relevent bits from
>>> event->attr.config{,1,2} for use by sw-like pmus where the
>>> 'config{,1,2}' values don't map directly to hardware registers.
>>>
>>> Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
>>> ---
>>> include/linux/perf_event.h | 17 +++++++++++++++++
>>> 1 file changed, 17 insertions(+)
>>>
>>> diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
>>> index e56b07f..3da5081 100644
>>> --- a/include/linux/perf_event.h
>>> +++ b/include/linux/perf_event.h
>>> @@ -871,4 +871,21 @@ _name##_show(struct device
>>> *dev, \
>>> \
>>> static struct device_attribute format_attr_##_name = __ATTR_RO(_name)
>>>
>>> +#define PMU_FORMAT_RANGE(name, attr_var, bit_start, bit_end) \
>>> +PMU_FORMAT_ATTR(name, #attr_var ":" #bit_start "-" #bit_end); \
>>> +PMU_FORMAT_RANGE_RESERVED(name, attr_var, bit_start, bit_end)
>>
>> I really think these should have event in the name.
>>
>> Someone looking at the code is going to see event_get_foo() and wonder
>> where
>> that is defined. Grep won't find a definition, tags won't find a
>> definition,
>> the least you can do is have the macro name give some hint.
>>
>
> That is a good point (grep-ability). Let me think about this. There is
> also the possibility that I could adjust the event_get_*() naming to
> something else. format_get_*()? event_get_format_*()? (these names keep
> growing...)
>
I've gone with a format_get(name, event) style macro (making it more
grep-able), in v4.
Feel free to direct further discussion to the v4 posting.
^ permalink raw reply
* [PATCH 0/2] perf: add documentation for sysfs interfaces
From: Cody P Schafer @ 2014-03-06 0:44 UTC (permalink / raw)
To: linux-doc, Arnaldo Carvalho de Melo, Cody P Schafer,
Michael Ellerman, Runzhen Wang, Sukadev Bhattiprolu
Cc: rob, Linux PPC, LKML, Arnaldo Carvalho de Melo
Documents <pmu>/event/<event>{,.scale,.units} and then removes the redundant
POWER docs.
Slightly restricts <event> names to avoid API funkyness when we add new
<event>.????? files ('.' forbidden in event names).
The contact is currently lkml, it would be very useful to have a perf
development list to put here instead (acme, feel like making one?).
--
Cody P Schafer (2):
perf Documentation: sysfs events/ interfaces
perf Documentation: remove duplicated docs for powerpc cpu specific
events
.../testing/sysfs-bus-event_source-devices-events | 92 +++++++++++-----------
1 file changed, 47 insertions(+), 45 deletions(-)
--
1.9.0
^ permalink raw reply
* [PATCH 1/2] perf Documentation: sysfs events/ interfaces
From: Cody P Schafer @ 2014-03-06 0:44 UTC (permalink / raw)
To: linux-doc, Arnaldo Carvalho de Melo, Cody P Schafer,
Michael Ellerman, Runzhen Wang, Sukadev Bhattiprolu
Cc: rob, Linux PPC, LKML, Arnaldo Carvalho de Melo
In-Reply-To: <1394066658-16766-1-git-send-email-cody@linux.vnet.ibm.com>
Add documentation for the <event>, <event>.scale, and <event>.unit
files in sysfs.
<event>.scale and <event>.unit were undocumented.
<event> was previously documented only for specific powerpc pmu events.
I've added a restriction that event names cannot contain '.' characters
so we can avoid breaking the API when we (inevitably) add more
'event.????' files.
Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
---
.../testing/sysfs-bus-event_source-devices-events | 59 ++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
index 3c1cc24..5393e1ed6 100644
--- a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
+++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
@@ -82,3 +82,62 @@ Description: POWER-systems specific performance monitoring events
Further, multiple terms like 'event=0xNNNN' can be specified
and separated with comma. All available terms are defined in
the /sys/bus/event_source/devices/<dev>/format file.
+
+What: /sys/bus/event_source/devices/<pmu>/events/<event>
+Date: 2014/02/24
+Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description: Per-pmu performance monitoring events specific to the running system
+
+ Each file (with a name not containing a '.') in the 'events'
+ directory describes a single performance monitoring event
+ supported by the <pmu>. The name of the file is the name of the event.
+
+ File contents:
+
+ <term>[=<value>][,<term>[=<value>]]...
+
+ Where <term> is one of the terms listed under
+ /sys/bus/event_source/devices/<pmu>/format/ and <value> is
+ a number is base-16 format with a '0x' prefix (lowercase only).
+ If a <term> is specified alone (without an assigned value), it
+ is implied that 0x1 is assigned to that <term>.
+
+ Examples (each of these lines would be in a seperate file):
+
+ event=0x2abc
+ event=0x423,inv,cmask=0x3
+ domain=0x1,offset=0x8,starting_index=0xffff
+
+ Each of the assignments indicates a value to be assigned to a
+ particular set of bits (as defined by the format file
+ corresponding to the <term>) in the perf_event structure passed
+ to the perf_open syscall.
+
+What: /sys/bus/event_source/devices/<pmu>/events/<event>.unit
+Date: 2014/02/24
+Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description: Perf event units
+
+ A string specifying the English plural numerical unit that <event>
+ (once multiplied by <event>.scale) represents.
+
+ Example:
+
+ Joules
+
+What: /sys/bus/event_source/devices/<pmu>/events/<event>.scale
+Date: 2014/02/24
+Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description: Perf event scaling factors
+
+ A string representing a floating point value expressed in
+ scientific notation to be multiplied by the event count
+ recieved from the kernel to match the unit specified in the
+ <event>.unit file.
+
+ Example:
+
+ 2.3283064365386962890625e-10
+
+ This is provided to avoid performing floating point arithmetic
+ in the kernel.
--
1.9.0
^ permalink raw reply related
* [PATCH 2/2] perf Documentation: remove duplicated docs for powerpc cpu specific events
From: Cody P Schafer @ 2014-03-06 0:44 UTC (permalink / raw)
To: linux-doc, Arnaldo Carvalho de Melo, Cody P Schafer,
Michael Ellerman, Runzhen Wang, Sukadev Bhattiprolu
Cc: rob, Linux PPC, LKML, Arnaldo Carvalho de Melo
In-Reply-To: <1394066658-16766-1-git-send-email-cody@linux.vnet.ibm.com>
Listing specific events doesn't actually help us at all here because:
- these events actually vary between different ppc processors, they
aren't garunteed to be present.
- the documentation of the file contents is now duplicated by the
docs for arbitrary event file contents.
Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
---
.../testing/sysfs-bus-event_source-devices-events | 57 ----------------------
1 file changed, 57 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
index 5393e1ed6..50c30a6 100644
--- a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
+++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
@@ -26,63 +26,6 @@ Description: Generic performance monitoring events
"raw code" for the perf event identified by the file's
"basename".
-
-What: /sys/devices/cpu/events/PM_1PLUS_PPC_CMPL
- /sys/devices/cpu/events/PM_BRU_FIN
- /sys/devices/cpu/events/PM_BR_MPRED
- /sys/devices/cpu/events/PM_CMPLU_STALL
- /sys/devices/cpu/events/PM_CMPLU_STALL_BRU
- /sys/devices/cpu/events/PM_CMPLU_STALL_DCACHE_MISS
- /sys/devices/cpu/events/PM_CMPLU_STALL_DFU
- /sys/devices/cpu/events/PM_CMPLU_STALL_DIV
- /sys/devices/cpu/events/PM_CMPLU_STALL_ERAT_MISS
- /sys/devices/cpu/events/PM_CMPLU_STALL_FXU
- /sys/devices/cpu/events/PM_CMPLU_STALL_IFU
- /sys/devices/cpu/events/PM_CMPLU_STALL_LSU
- /sys/devices/cpu/events/PM_CMPLU_STALL_REJECT
- /sys/devices/cpu/events/PM_CMPLU_STALL_SCALAR
- /sys/devices/cpu/events/PM_CMPLU_STALL_SCALAR_LONG
- /sys/devices/cpu/events/PM_CMPLU_STALL_STORE
- /sys/devices/cpu/events/PM_CMPLU_STALL_THRD
- /sys/devices/cpu/events/PM_CMPLU_STALL_VECTOR
- /sys/devices/cpu/events/PM_CMPLU_STALL_VECTOR_LONG
- /sys/devices/cpu/events/PM_CYC
- /sys/devices/cpu/events/PM_GCT_NOSLOT_BR_MPRED
- /sys/devices/cpu/events/PM_GCT_NOSLOT_BR_MPRED_IC_MISS
- /sys/devices/cpu/events/PM_GCT_NOSLOT_CYC
- /sys/devices/cpu/events/PM_GCT_NOSLOT_IC_MISS
- /sys/devices/cpu/events/PM_GRP_CMPL
- /sys/devices/cpu/events/PM_INST_CMPL
- /sys/devices/cpu/events/PM_LD_MISS_L1
- /sys/devices/cpu/events/PM_LD_REF_L1
- /sys/devices/cpu/events/PM_RUN_CYC
- /sys/devices/cpu/events/PM_RUN_INST_CMPL
-
-Date: 2013/01/08
-
-Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
- Linux Powerpc mailing list <linuxppc-dev@ozlabs.org>
-
-Description: POWER-systems specific performance monitoring events
-
- A collection of performance monitoring events that may be
- supported by the POWER CPU. These events can be monitored
- using the 'perf(1)' tool.
-
- These events may not be supported by other CPUs.
-
- The contents of each file would look like:
-
- event=0xNNNN
-
- where 'N' is a hex digit and the number '0xNNNN' shows the
- "raw code" for the perf event identified by the file's
- "basename".
-
- Further, multiple terms like 'event=0xNNNN' can be specified
- and separated with comma. All available terms are defined in
- the /sys/bus/event_source/devices/<dev>/format file.
-
What: /sys/bus/event_source/devices/<pmu>/events/<event>
Date: 2014/02/24
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
--
1.9.0
^ permalink raw reply related
* [PATCH v3 1/2] QE: split function mpc85xx_qe_init() into two functions.
From: Zhao Qiang @ 2014-03-06 1:38 UTC (permalink / raw)
To: linuxppc-dev, B07421, galak; +Cc: Zhao Qiang, R63061
New QE doesn't have par_io, it doesn't need to init par_io
for new QE.
Split function mpc85xx_qe_init() into mpc85xx_qe_init()
and mpc85xx_qe_par_io_init().
Call mpc85xx_qe_init() for both new and old while
mpc85xx_qe_par_io_init() after mpc85xx_qe_init() for old.
Signed-off-by: Zhao Qiang <B45475@freescale.com>
---
Changes for v2:
- no
Changes for v3:
- no
arch/powerpc/platforms/85xx/common.c | 6 ++++++
arch/powerpc/platforms/85xx/mpc85xx.h | 2 ++
arch/powerpc/platforms/85xx/mpc85xx_mds.c | 1 +
arch/powerpc/platforms/85xx/mpc85xx_rdb.c | 1 +
arch/powerpc/platforms/85xx/twr_p102x.c | 1 +
5 files changed, 11 insertions(+)
diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c
index 3b085c7..b564b5e 100644
--- a/arch/powerpc/platforms/85xx/common.c
+++ b/arch/powerpc/platforms/85xx/common.c
@@ -107,6 +107,12 @@ void __init mpc85xx_qe_init(void)
qe_reset();
of_node_put(np);
+}
+
+void __init mpc85xx_qe_par_io_init(void)
+{
+ struct device_node *np;
+
np = of_find_node_by_name(NULL, "par_io");
if (np) {
struct device_node *ucc;
diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h
index fc51dd4..39056f6 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx.h
+++ b/arch/powerpc/platforms/85xx/mpc85xx.h
@@ -10,8 +10,10 @@ static inline void __init mpc85xx_cpm2_pic_init(void) {}
#ifdef CONFIG_QUICC_ENGINE
extern void mpc85xx_qe_init(void);
+extern void mpc85xx_qe_par_io_init(void);
#else
static inline void __init mpc85xx_qe_init(void) {}
+static inline void __init mpc85xx_qe_par_io_init(void) {}
#endif
#endif
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 34f3c5e..3c190b4 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -239,6 +239,7 @@ static void __init mpc85xx_mds_qe_init(void)
struct device_node *np;
mpc85xx_qe_init();
+ mpc85xx_qe_par_io_init();
mpc85xx_mds_reset_ucc_phys();
if (machine_is(p1021_mds)) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index e15bdd1..f9668ed 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -99,6 +99,7 @@ static void __init mpc85xx_rdb_setup_arch(void)
#ifdef CONFIG_QUICC_ENGINE
mpc85xx_qe_init();
+ mpc85xx_qe_par_io_init();
#if defined(CONFIG_UCC_GETH) || defined(CONFIG_SERIAL_QE)
if (machine_is(p1025_rdb)) {
diff --git a/arch/powerpc/platforms/85xx/twr_p102x.c b/arch/powerpc/platforms/85xx/twr_p102x.c
index c25ff10..1eadb6d 100644
--- a/arch/powerpc/platforms/85xx/twr_p102x.c
+++ b/arch/powerpc/platforms/85xx/twr_p102x.c
@@ -77,6 +77,7 @@ static void __init twr_p1025_setup_arch(void)
#ifdef CONFIG_QUICC_ENGINE
mpc85xx_qe_init();
+ mpc85xx_qe_par_io_init();
#if defined(CONFIG_UCC_GETH) || defined(CONFIG_SERIAL_QE)
if (machine_is(twr_p1025)) {
--
1.8.5
^ permalink raw reply related
* [PATCH v3 2/2] Corenet: Add QE platform support for Corenet
From: Zhao Qiang @ 2014-03-06 1:39 UTC (permalink / raw)
To: linuxppc-dev, B07421, galak; +Cc: Zhao Qiang, R63061
There is QE on platform T104x, add support.
Call funcs qe_ic_init and qe_init if CONFIG_QUICC_ENGINE is defined.
Signed-off-by: Zhao Qiang <B45475@freescale.com>
---
Changes for v2:
- use mpc85xx_qe_init() instead
Changes for v3:
- remove #ifdef which aren't really needed
arch/powerpc/platforms/85xx/corenet_generic.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c
index fbd871e..19420ef 100644
--- a/arch/powerpc/platforms/85xx/corenet_generic.c
+++ b/arch/powerpc/platforms/85xx/corenet_generic.c
@@ -26,11 +26,13 @@
#include <asm/udbg.h>
#include <asm/mpic.h>
#include <asm/ehv_pic.h>
+#include <asm/qe_ic.h>
#include <linux/of_platform.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
#include "smp.h"
+#include "mpc85xx.h"
void __init corenet_gen_pic_init(void)
{
@@ -38,6 +40,8 @@ void __init corenet_gen_pic_init(void)
unsigned int flags = MPIC_BIG_ENDIAN | MPIC_SINGLE_DEST_CPU |
MPIC_NO_RESET;
+ struct device_node *np;
+
if (ppc_md.get_irq == mpic_get_coreint_irq)
flags |= MPIC_ENABLE_COREINT;
@@ -45,6 +49,14 @@ void __init corenet_gen_pic_init(void)
BUG_ON(mpic == NULL);
mpic_init(mpic);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
+ if (np) {
+ qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
+ qe_ic_cascade_high_mpic);
+ of_node_put(np);
+ }
+
}
/*
@@ -57,6 +69,8 @@ void __init corenet_gen_setup_arch(void)
swiotlb_detect_4g();
pr_info("%s board from Freescale Semiconductor\n", ppc_md.name);
+
+ mpc85xx_qe_init();
}
static const struct of_device_id of_device_ids[] = {
@@ -81,6 +95,9 @@ static const struct of_device_id of_device_ids[] = {
{
.compatible = "fsl,qoriq-pcie-v3.0",
},
+ {
+ .compatible = "fsl,qe",
+ },
/* The following two are for the Freescale hypervisor */
{
.name = "hypervisor",
--
1.8.5
^ permalink raw reply related
* Re: [PATCH] net/mlx4: Support shutdown() interface
From: David Miller @ 2014-03-06 1:45 UTC (permalink / raw)
To: shangw; +Cc: netdev, weiyang, amirv, linuxppc-dev
In-Reply-To: <1393918520-3268-1-git-send-email-shangw@linux.vnet.ibm.com>
From: Gavin Shan <shangw@linux.vnet.ibm.com>
Date: Tue, 4 Mar 2014 15:35:20 +0800
> In kexec scenario, we failed to load the mlx4 driver in the
> second kernel because the ownership bit was hold by the first
> kernel without release correctly.
>
> The patch adds shutdown() interface so that the ownership can
> be released correctly in the first kernel. It also helps avoiding
> EEH error happened during boot stage of the second kernel because
> of undesired traffic, which can't be handled by hardware during
> that stage on Power platform.
>
> Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
> Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Applied.
^ permalink raw reply
* Re: [PATCH 1/2] sched: Remove unused mc_capable() and smt_capable()
From: Preeti U Murthy @ 2014-03-06 2:20 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: linux-mips, linux-ia64, Peter Zijlstra, x86, linux-kernel,
Ingo Molnar, sparclinux, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20140304210737.16893.54289.stgit@bhelgaas-glaptop.roam.corp.google.com>
On 03/05/2014 02:37 AM, Bjorn Helgaas wrote:
> Remove mc_capable() and smt_capable(). Neither is used.
>
> Both were added by 5c45bf279d37 ("sched: mc/smt power savings sched
> policy"). Uses of both were removed by 8e7fbcbc22c1 ("sched: Remove stale
> power aware scheduling remnants and dysfunctional knobs").
>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
> arch/arm/include/asm/topology.h | 3 ---
> arch/ia64/include/asm/topology.h | 1 -
> arch/mips/include/asm/topology.h | 4 ----
> arch/powerpc/include/asm/topology.h | 1 -
> arch/sparc/include/asm/topology_64.h | 2 --
> arch/x86/include/asm/topology.h | 6 ------
> 6 files changed, 17 deletions(-)
>
> diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h
> index 58b8b84adcd2..2fe85fff5cca 100644
> --- a/arch/arm/include/asm/topology.h
> +++ b/arch/arm/include/asm/topology.h
> @@ -20,9 +20,6 @@ extern struct cputopo_arm cpu_topology[NR_CPUS];
> #define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling)
> #define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_sibling)
>
> -#define mc_capable() (cpu_topology[0].socket_id != -1)
> -#define smt_capable() (cpu_topology[0].thread_id != -1)
> -
> void init_cpu_topology(void);
> void store_cpu_topology(unsigned int cpuid);
> const struct cpumask *cpu_coregroup_mask(int cpu);
> diff --git a/arch/ia64/include/asm/topology.h b/arch/ia64/include/asm/topology.h
> index a2496e449b75..5cb55a1e606b 100644
> --- a/arch/ia64/include/asm/topology.h
> +++ b/arch/ia64/include/asm/topology.h
> @@ -77,7 +77,6 @@ void build_cpu_to_node_map(void);
> #define topology_core_id(cpu) (cpu_data(cpu)->core_id)
> #define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
> #define topology_thread_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
> -#define smt_capable() (smp_num_siblings > 1)
> #endif
>
> extern void arch_fix_phys_package_id(int num, u32 slot);
> diff --git a/arch/mips/include/asm/topology.h b/arch/mips/include/asm/topology.h
> index 12609a17dc8b..20ea4859c822 100644
> --- a/arch/mips/include/asm/topology.h
> +++ b/arch/mips/include/asm/topology.h
> @@ -10,8 +10,4 @@
>
> #include <topology.h>
>
> -#ifdef CONFIG_SMP
> -#define smt_capable() (smp_num_siblings > 1)
> -#endif
> -
> #endif /* __ASM_TOPOLOGY_H */
> diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
> index d0b5fca6b077..c9202151079f 100644
> --- a/arch/powerpc/include/asm/topology.h
> +++ b/arch/powerpc/include/asm/topology.h
> @@ -99,7 +99,6 @@ static inline int prrn_is_enabled(void)
>
> #ifdef CONFIG_SMP
> #include <asm/cputable.h>
> -#define smt_capable() (cpu_has_feature(CPU_FTR_SMT))
>
> #ifdef CONFIG_PPC64
> #include <asm/smp.h>
> diff --git a/arch/sparc/include/asm/topology_64.h b/arch/sparc/include/asm/topology_64.h
> index 1754390a426f..a2d10fc64faf 100644
> --- a/arch/sparc/include/asm/topology_64.h
> +++ b/arch/sparc/include/asm/topology_64.h
> @@ -42,8 +42,6 @@ static inline int pcibus_to_node(struct pci_bus *pbus)
> #define topology_core_id(cpu) (cpu_data(cpu).core_id)
> #define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
> #define topology_thread_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
> -#define mc_capable() (sparc64_multi_core)
> -#define smt_capable() (sparc64_multi_core)
> #endif /* CONFIG_SMP */
>
> extern cpumask_t cpu_core_map[NR_CPUS];
> diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
> index d35f24e231cd..9bcc724cafdd 100644
> --- a/arch/x86/include/asm/topology.h
> +++ b/arch/x86/include/asm/topology.h
> @@ -133,12 +133,6 @@ static inline void arch_fix_phys_package_id(int num, u32 slot)
> struct pci_bus;
> void x86_pci_root_bus_resources(int bus, struct list_head *resources);
>
> -#ifdef CONFIG_SMP
> -#define mc_capable() ((boot_cpu_data.x86_max_cores > 1) && \
> - (cpumask_weight(cpu_core_mask(0)) != nr_cpu_ids))
> -#define smt_capable() (smp_num_siblings > 1)
> -#endif
> -
> #ifdef CONFIG_NUMA
> extern int get_mp_bus_to_node(int busnum);
> extern void set_mp_bus_to_node(int busnum, int node);
>
Reviewed-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
^ permalink raw reply
* [PATCH 0/5] V2 IBM Akebono/PPC46GTR Support
From: Alistair Popple @ 2014-03-06 3:52 UTC (permalink / raw)
To: benh, netdev, linux-mmc, chris, linuxppc-dev, davem
Cc: Alistair Popple, linux-kernel, devicetree
The IBM Akebono board is a development board for the new PPC476GTR
system on chip (SoC).
This version of the series updates the device tree and drops the USB
patches as the equivalent functionality is already in linux-next. It
also addresses feedback from the previous submission.
Alistair Popple (5):
SDHCI: Add a generic registration to the SDHCI platform driver
IBM Akebono: Add support for a new PHY interface to the IBM emac
driver
IBM Currituck: Clean up board specific code before adding Akebono code
IBM Akebono: Add the Akebono platform
powerpc: Added PCI MSI support using the HSTA module
.../devicetree/bindings/mmc/sdhci-pltfm.txt | 16 +
.../devicetree/bindings/powerpc/4xx/akebono.txt | 54 +++
.../devicetree/bindings/powerpc/4xx/emac.txt | 9 +
.../devicetree/bindings/powerpc/4xx/hsta.txt | 19 +
arch/powerpc/boot/Makefile | 3 +
arch/powerpc/boot/dcr.h | 4 +
arch/powerpc/boot/dts/akebono.dts | 415 +++++++++++++++++++++
arch/powerpc/boot/treeboot-akebono.c | 163 ++++++++
arch/powerpc/boot/wrapper | 3 +
arch/powerpc/configs/44x/akebono_defconfig | 148 ++++++++
arch/powerpc/platforms/44x/Kconfig | 28 ++
arch/powerpc/platforms/44x/Makefile | 3 +-
arch/powerpc/platforms/44x/currituck.c | 233 ------------
arch/powerpc/platforms/44x/ppc476.c | 299 +++++++++++++++
arch/powerpc/sysdev/Kconfig | 6 +
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/ppc4xx_hsta_msi.c | 215 +++++++++++
arch/powerpc/sysdev/ppc4xx_pci.c | 21 +-
drivers/mmc/host/sdhci-pltfm.c | 28 ++
drivers/net/ethernet/ibm/emac/Kconfig | 4 +
drivers/net/ethernet/ibm/emac/Makefile | 1 +
drivers/net/ethernet/ibm/emac/core.c | 50 ++-
drivers/net/ethernet/ibm/emac/core.h | 12 +
drivers/net/ethernet/ibm/emac/rgmii_wol.c | 244 ++++++++++++
drivers/net/ethernet/ibm/emac/rgmii_wol.h | 62 +++
25 files changed, 1796 insertions(+), 245 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-pltfm.txt
create mode 100644 Documentation/devicetree/bindings/powerpc/4xx/akebono.txt
create mode 100644 Documentation/devicetree/bindings/powerpc/4xx/hsta.txt
create mode 100644 arch/powerpc/boot/dts/akebono.dts
create mode 100644 arch/powerpc/boot/treeboot-akebono.c
create mode 100644 arch/powerpc/configs/44x/akebono_defconfig
delete mode 100644 arch/powerpc/platforms/44x/currituck.c
create mode 100644 arch/powerpc/platforms/44x/ppc476.c
create mode 100644 arch/powerpc/sysdev/ppc4xx_hsta_msi.c
create mode 100644 drivers/net/ethernet/ibm/emac/rgmii_wol.c
create mode 100644 drivers/net/ethernet/ibm/emac/rgmii_wol.h
--
1.8.3.2
^ permalink raw reply
* [PATCH 1/5] SDHCI: Add a generic registration to the SDHCI platform driver
From: Alistair Popple @ 2014-03-06 3:52 UTC (permalink / raw)
To: linux-mmc, chris; +Cc: Alistair Popple, linuxppc-dev, linux-kernel, devicetree
In-Reply-To: <1394077948-8395-1-git-send-email-alistair@popple.id.au>
This patch adds a generic platform driver registration to the exiting SDHCI
platform driver using the devicetree compatibility string "generic-sdhci".
Signed-off-by: Alistair Popple <alistair@popple.id.au>
---
.../devicetree/bindings/mmc/sdhci-pltfm.txt | 16 +++++++++++++
drivers/mmc/host/sdhci-pltfm.c | 28 ++++++++++++++++++++++
2 files changed, 44 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-pltfm.txt
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-pltfm.txt b/Documentation/devicetree/bindings/mmc/sdhci-pltfm.txt
new file mode 100644
index 0000000..3940659
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/sdhci-pltfm.txt
@@ -0,0 +1,16 @@
+Generic SHDCI platform driver
+
+The generic SDHCI platform driver should support most SDHCI host
+controllers. It uses the compatible="generic-sdhci" property and
+supports the following device tree properties as described in mmc.txt.
+
+Supported properties (described in mmc.txt):
+- reg
+- interrupts
+- wp-inverted
+- broken-cd
+- no-1-8-v
+- keep-power-in-suspend
+- enable-sdio-wakeup
+- bus-width
+- clock-frequency
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index bef250e..696d1f6 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -260,6 +260,34 @@ const struct dev_pm_ops sdhci_pltfm_pmops = {
EXPORT_SYMBOL_GPL(sdhci_pltfm_pmops);
#endif /* CONFIG_PM */
+static int sdhci_generic_probe(struct platform_device *pdev)
+{
+ return sdhci_pltfm_register(pdev, NULL, 0);
+}
+
+static int sdhci_generic_remove(struct platform_device *pdev)
+{
+ return sdhci_pltfm_unregister(pdev);
+}
+
+static const struct of_device_id sdhci_generic_of_match[] = {
+ { .compatible = "generic-sdhci" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sdhci_generic_of_match);
+
+static struct platform_driver sdhci_generic_driver = {
+ .driver = {
+ .name = "sdhci-generic",
+ .owner = THIS_MODULE,
+ .of_match_table = sdhci_generic_of_match,
+ .pm = SDHCI_PLTFM_PMOPS,
+ },
+ .probe = sdhci_generic_probe,
+ .remove = sdhci_generic_remove,
+};
+module_platform_driver(sdhci_generic_driver);
+
static int __init sdhci_pltfm_drv_init(void)
{
pr_info("sdhci-pltfm: SDHCI platform and OF driver helper\n");
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/5] IBM Akebono: Add support for a new PHY interface to the IBM emac driver
From: Alistair Popple @ 2014-03-06 3:52 UTC (permalink / raw)
To: netdev, davem; +Cc: Alistair Popple, linuxppc-dev, linux-kernel, devicetree
In-Reply-To: <1394077948-8395-1-git-send-email-alistair@popple.id.au>
The IBM PPC476GTR SoC that is used on the Akebono board uses a
different ethernet PHY interface that has wake on lan (WOL) support
with the IBM emac. This patch adds support to the IBM emac driver for
this new PHY interface.
At this stage the wake on lan functionality has not been implemented.
Signed-off-by: Alistair Popple <alistair@popple.id.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
.../devicetree/bindings/powerpc/4xx/emac.txt | 9 +
drivers/net/ethernet/ibm/emac/Kconfig | 4 +
drivers/net/ethernet/ibm/emac/Makefile | 1 +
drivers/net/ethernet/ibm/emac/core.c | 50 ++++-
drivers/net/ethernet/ibm/emac/core.h | 12 +
drivers/net/ethernet/ibm/emac/rgmii_wol.c | 244 +++++++++++++++++++++
drivers/net/ethernet/ibm/emac/rgmii_wol.h | 62 ++++++
7 files changed, 376 insertions(+), 6 deletions(-)
create mode 100644 drivers/net/ethernet/ibm/emac/rgmii_wol.c
create mode 100644 drivers/net/ethernet/ibm/emac/rgmii_wol.h
diff --git a/Documentation/devicetree/bindings/powerpc/4xx/emac.txt b/Documentation/devicetree/bindings/powerpc/4xx/emac.txt
index 712baf6..0c20529 100644
--- a/Documentation/devicetree/bindings/powerpc/4xx/emac.txt
+++ b/Documentation/devicetree/bindings/powerpc/4xx/emac.txt
@@ -61,6 +61,8 @@
Fox Axon: present, whatever value is appropriate for each
EMAC, that is the content of the current (bogus) "phy-port"
property.
+ - rgmii-wol-device : 1 cell, required iff connected to a RGMII in the WKUP
+ power domain. phandle of the RGMII-WOL device node.
Optional properties:
- phy-address : 1 cell, optional, MDIO address of the PHY. If absent,
@@ -146,3 +148,10 @@
available.
For Axon: 0x0000012a
+ iv) RGMII-WOL node
+
+ Required properties:
+ - compatible : compatible list, containing 2 entries, first is
+ "ibm,rgmii-wol-CHIP" where CHIP is the host ASIC (like
+ EMAC) and the second is "ibm,rgmii-wol".
+ - reg : <registers mapping>
diff --git a/drivers/net/ethernet/ibm/emac/Kconfig b/drivers/net/ethernet/ibm/emac/Kconfig
index 3f44a30..56ea346 100644
--- a/drivers/net/ethernet/ibm/emac/Kconfig
+++ b/drivers/net/ethernet/ibm/emac/Kconfig
@@ -55,6 +55,10 @@ config IBM_EMAC_RGMII
bool
default n
+config IBM_EMAC_RGMII_WOL
+ bool "IBM EMAC RGMII wake-on-LAN support" if COMPILE_TEST
+ default n
+
config IBM_EMAC_TAH
bool
default n
diff --git a/drivers/net/ethernet/ibm/emac/Makefile b/drivers/net/ethernet/ibm/emac/Makefile
index eba2183..8843803 100644
--- a/drivers/net/ethernet/ibm/emac/Makefile
+++ b/drivers/net/ethernet/ibm/emac/Makefile
@@ -7,5 +7,6 @@ obj-$(CONFIG_IBM_EMAC) += ibm_emac.o
ibm_emac-y := mal.o core.o phy.o
ibm_emac-$(CONFIG_IBM_EMAC_ZMII) += zmii.o
ibm_emac-$(CONFIG_IBM_EMAC_RGMII) += rgmii.o
+ibm_emac-$(CONFIG_IBM_EMAC_RGMII_WOL) += rgmii_wol.o
ibm_emac-$(CONFIG_IBM_EMAC_TAH) += tah.o
ibm_emac-$(CONFIG_IBM_EMAC_DEBUG) += debug.o
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index ae342fd..ff58474 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -632,6 +632,8 @@ static int emac_configure(struct emac_instance *dev)
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
rgmii_set_speed(dev->rgmii_dev, dev->rgmii_port,
dev->phy.speed);
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL))
+ rgmii_wol_set_speed(dev->rgmii_wol_dev, dev->phy.speed);
if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII))
zmii_set_speed(dev->zmii_dev, dev->zmii_port, dev->phy.speed);
@@ -799,6 +801,8 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg)
zmii_get_mdio(dev->zmii_dev, dev->zmii_port);
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port);
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL))
+ rgmii_wol_get_mdio(dev->rgmii_wol_dev);
/* Wait for management interface to become idle */
n = 20;
@@ -846,6 +850,8 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg)
DBG2(dev, "mdio_read -> %04x" NL, r);
err = 0;
bail:
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL))
+ rgmii_wol_put_mdio(dev->rgmii_wol_dev);
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
rgmii_put_mdio(dev->rgmii_dev, dev->rgmii_port);
if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII))
@@ -871,6 +877,8 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg,
zmii_get_mdio(dev->zmii_dev, dev->zmii_port);
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port);
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL))
+ rgmii_wol_get_mdio(dev->rgmii_wol_dev);
/* Wait for management interface to be idle */
n = 20;
@@ -909,6 +917,8 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg,
}
err = 0;
bail:
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL))
+ rgmii_wol_put_mdio(dev->rgmii_wol_dev);
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
rgmii_put_mdio(dev->rgmii_dev, dev->rgmii_port);
if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII))
@@ -2277,10 +2287,11 @@ struct emac_depentry {
#define EMAC_DEP_MAL_IDX 0
#define EMAC_DEP_ZMII_IDX 1
#define EMAC_DEP_RGMII_IDX 2
-#define EMAC_DEP_TAH_IDX 3
-#define EMAC_DEP_MDIO_IDX 4
-#define EMAC_DEP_PREV_IDX 5
-#define EMAC_DEP_COUNT 6
+#define EMAC_DEP_RGMII_WOL_IDX 3
+#define EMAC_DEP_TAH_IDX 4
+#define EMAC_DEP_MDIO_IDX 5
+#define EMAC_DEP_PREV_IDX 6
+#define EMAC_DEP_COUNT 7
static int emac_check_deps(struct emac_instance *dev,
struct emac_depentry *deps)
@@ -2358,6 +2369,7 @@ static int emac_wait_deps(struct emac_instance *dev)
deps[EMAC_DEP_MAL_IDX].phandle = dev->mal_ph;
deps[EMAC_DEP_ZMII_IDX].phandle = dev->zmii_ph;
deps[EMAC_DEP_RGMII_IDX].phandle = dev->rgmii_ph;
+ deps[EMAC_DEP_RGMII_WOL_IDX].phandle = dev->rgmii_wol_ph;
if (dev->tah_ph)
deps[EMAC_DEP_TAH_IDX].phandle = dev->tah_ph;
if (dev->mdio_ph)
@@ -2380,6 +2392,7 @@ static int emac_wait_deps(struct emac_instance *dev)
dev->mal_dev = deps[EMAC_DEP_MAL_IDX].ofdev;
dev->zmii_dev = deps[EMAC_DEP_ZMII_IDX].ofdev;
dev->rgmii_dev = deps[EMAC_DEP_RGMII_IDX].ofdev;
+ dev->rgmii_wol_dev = deps[EMAC_DEP_RGMII_WOL_IDX].ofdev;
dev->tah_dev = deps[EMAC_DEP_TAH_IDX].ofdev;
dev->mdio_dev = deps[EMAC_DEP_MDIO_IDX].ofdev;
}
@@ -2585,6 +2598,8 @@ static int emac_init_config(struct emac_instance *dev)
dev->rgmii_ph = 0;
if (emac_read_uint_prop(np, "rgmii-channel", &dev->rgmii_port, 0))
dev->rgmii_port = 0xffffffff;
+ if (emac_read_uint_prop(np, "rgmii-wol-device", &dev->rgmii_wol_ph, 0))
+ dev->rgmii_wol_ph = 0;
if (emac_read_uint_prop(np, "fifo-entry-size", &dev->fifo_entry_size, 0))
dev->fifo_entry_size = 16;
if (emac_read_uint_prop(np, "mal-burst-size", &dev->mal_burst_size, 0))
@@ -2671,6 +2686,16 @@ static int emac_init_config(struct emac_instance *dev)
#endif
}
+ if (dev->rgmii_wol_ph != 0) {
+#ifdef CONFIG_IBM_EMAC_RGMII_WOL
+ dev->features |= EMAC_FTR_HAS_RGMII_WOL;
+#else
+ printk(KERN_ERR "%s: RGMII WOL support not enabled !\n",
+ np->full_name);
+ return -ENXIO;
+#endif
+ }
+
/* Read MAC-address */
p = of_get_property(np, "local-mac-address", NULL);
if (p == NULL) {
@@ -2844,10 +2869,15 @@ static int emac_probe(struct platform_device *ofdev)
(err = rgmii_attach(dev->rgmii_dev, dev->rgmii_port, dev->phy_mode)) != 0)
goto err_detach_zmii;
+ /* Attach to RGMII_WOL, if needed */
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL) &&
+ (err = rgmii_wol_attach(dev->rgmii_wol_dev, dev->phy_mode)) != 0)
+ goto err_detach_rgmii;
+
/* Attach to TAH, if needed */
if (emac_has_feature(dev, EMAC_FTR_HAS_TAH) &&
(err = tah_attach(dev->tah_dev, dev->tah_port)) != 0)
- goto err_detach_rgmii;
+ goto err_detach_rgmii_wol;
/* Set some link defaults before we can find out real parameters */
dev->phy.speed = SPEED_100;
@@ -2920,6 +2950,9 @@ static int emac_probe(struct platform_device *ofdev)
err_detach_tah:
if (emac_has_feature(dev, EMAC_FTR_HAS_TAH))
tah_detach(dev->tah_dev, dev->tah_port);
+ err_detach_rgmii_wol:
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL))
+ rgmii_wol_detach(dev->rgmii_wol_dev);
err_detach_rgmii:
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
rgmii_detach(dev->rgmii_dev, dev->rgmii_port);
@@ -3081,12 +3114,17 @@ static int __init emac_init(void)
rc = tah_init();
if (rc)
goto err_rgmii;
- rc = platform_driver_register(&emac_driver);
+ rc = rgmii_wol_init();
if (rc)
goto err_tah;
+ rc = platform_driver_register(&emac_driver);
+ if (rc)
+ goto err_rgmii_wol;
return 0;
+ err_rgmii_wol:
+ rgmii_wol_exit();
err_tah:
tah_exit();
err_rgmii:
diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h
index 67f342a..7e1a70d 100644
--- a/drivers/net/ethernet/ibm/emac/core.h
+++ b/drivers/net/ethernet/ibm/emac/core.h
@@ -42,6 +42,7 @@
#include "phy.h"
#include "zmii.h"
#include "rgmii.h"
+#include "rgmii_wol.h"
#include "mal.h"
#include "tah.h"
#include "debug.h"
@@ -209,6 +210,10 @@ struct emac_instance {
u32 rgmii_port;
struct platform_device *rgmii_dev;
+ /* RGMII WOL infos if any */
+ u32 rgmii_wol_ph;
+ struct platform_device *rgmii_wol_dev;
+
/* TAH infos if any */
u32 tah_ph;
u32 tah_port;
@@ -332,6 +337,10 @@ struct emac_instance {
* APM821xx does not support Half Duplex mode
*/
#define EMAC_FTR_APM821XX_NO_HALF_DUPLEX 0x00001000
+/*
+ * Set if we have a RGMII with wake on LAN.
+ */
+#define EMAC_FTR_HAS_RGMII_WOL 0x00020000
/* Right now, we don't quite handle the always/possible masks on the
* most optimal way as we don't have a way to say something like
@@ -355,6 +364,9 @@ enum {
#ifdef CONFIG_IBM_EMAC_RGMII
EMAC_FTR_HAS_RGMII |
#endif
+#ifdef CONFIG_IBM_EMAC_RGMII_WOL
+ EMAC_FTR_HAS_RGMII_WOL |
+#endif
#ifdef CONFIG_IBM_EMAC_NO_FLOW_CTRL
EMAC_FTR_NO_FLOW_CONTROL_40x |
#endif
diff --git a/drivers/net/ethernet/ibm/emac/rgmii_wol.c b/drivers/net/ethernet/ibm/emac/rgmii_wol.c
new file mode 100644
index 0000000..5006336
--- /dev/null
+++ b/drivers/net/ethernet/ibm/emac/rgmii_wol.c
@@ -0,0 +1,244 @@
+/* drivers/net/ethernet/ibm/emac/rgmii_wol.c
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge with
+ * wake on LAN support.
+ *
+ * Copyright 2013 Alistair Popple, IBM Corp.
+ * <alistair@popple.id.au>
+ *
+ * Based on rgmii.h:
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * 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/slab.h>
+#include <linux/kernel.h>
+#include <linux/ethtool.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+
+#include "emac.h"
+#include "debug.h"
+
+/* RGMII_WOL_REG */
+
+#define WKUP_ETH_RGSPD 0xC0000000
+#define WKUP_ETH_FCSEN 0x20000000
+#define WKUP_ETH_CRSEN 0x02000000
+#define WKUP_ETH_COLEN 0x01000000
+#define WKUP_ETH_TX_OE 0x00040000
+#define WKUP_ETH_RX_IE 0x00020000
+#define WKUP_ETH_RGMIIEN 0x00010000
+
+#define WKUP_ETH_RGSPD_10 0x00000000
+#define WKUP_ETH_RGSPD_100 0x40000000
+#define WKUP_ETH_RGSPD_1000 0x80000000
+
+/* RGMII bridge supports only GMII/TBI and RGMII/RTBI PHYs */
+static inline int rgmii_valid_mode(int phy_mode)
+{
+ return phy_mode == PHY_MODE_GMII ||
+ phy_mode == PHY_MODE_MII ||
+ phy_mode == PHY_MODE_RGMII ||
+ phy_mode == PHY_MODE_TBI ||
+ phy_mode == PHY_MODE_RTBI;
+}
+
+int rgmii_wol_attach(struct platform_device *ofdev, int mode)
+{
+ struct rgmii_wol_instance *dev = platform_get_drvdata(ofdev);
+
+ dev_dbg(&ofdev->dev, "attach\n");
+
+ /* Check if we need to attach to a RGMII */
+ if (!rgmii_valid_mode(mode)) {
+ dev_err(&ofdev->dev, "unsupported settings !\n");
+ return -ENODEV;
+ }
+
+ mutex_lock(&dev->lock);
+
+ /* Enable this input */
+ out_be32(dev->reg, in_be32(dev->reg) | WKUP_ETH_RGMIIEN
+ | WKUP_ETH_TX_OE | WKUP_ETH_RX_IE);
+
+ ++dev->users;
+
+ mutex_unlock(&dev->lock);
+
+ return 0;
+}
+
+void rgmii_wol_set_speed(struct platform_device *ofdev, int speed)
+{
+ struct rgmii_wol_instance *dev = platform_get_drvdata(ofdev);
+ u32 reg;
+
+ mutex_lock(&dev->lock);
+
+ reg = in_be32(dev->reg) & ~WKUP_ETH_RGSPD;
+
+ dev_dbg(&ofdev->dev, "speed(%d)\n", speed);
+
+ switch (speed) {
+ case SPEED_1000:
+ reg |= WKUP_ETH_RGSPD_1000;
+ break;
+ case SPEED_100:
+ reg |= WKUP_ETH_RGSPD_100;
+ break;
+ case SPEED_10:
+ reg |= WKUP_ETH_RGSPD_10;
+ break;
+ default:
+ dev_err(&ofdev->dev, "invalid speed set!\n");
+ }
+
+ out_be32(dev->reg, reg);
+
+ mutex_unlock(&dev->lock);
+}
+
+void rgmii_wol_get_mdio(struct platform_device *ofdev)
+{
+ /* MDIO is always enabled when RGMII_WOL is enabled, so we
+ * don't have to do anything here.
+ */
+ dev_dbg(&ofdev->dev, "get_mdio\n");
+}
+
+void rgmii_wol_put_mdio(struct platform_device *ofdev)
+{
+ dev_dbg(&ofdev->dev, "put_mdio\n");
+}
+
+void rgmii_wol_detach(struct platform_device *ofdev)
+{
+ struct rgmii_wol_instance *dev = platform_get_drvdata(ofdev);
+
+ BUG_ON(!dev || dev->users == 0);
+
+ mutex_lock(&dev->lock);
+
+ dev_dbg(&ofdev->dev, "detach\n");
+
+ /* Disable this input */
+ out_be32(dev->reg, 0);
+
+ --dev->users;
+
+ mutex_unlock(&dev->lock);
+}
+
+int rgmii_wol_get_regs_len(struct platform_device *ofdev)
+{
+ return sizeof(struct emac_ethtool_regs_subhdr) +
+ sizeof(u32);
+}
+
+void *rgmii_wol_dump_regs(struct platform_device *ofdev, void *buf)
+{
+ struct rgmii_wol_instance *dev = platform_get_drvdata(ofdev);
+ struct emac_ethtool_regs_subhdr *hdr = buf;
+ u32 *regs = (u32 *)(hdr + 1);
+
+ hdr->version = 0;
+ hdr->index = 0; /* for now, are there chips with more than one
+ * rgmii ? if yes, then we'll add a cell_index
+ * like we do for emac
+ */
+ memcpy_fromio(regs, dev->reg, sizeof(u32));
+ return regs + 1;
+}
+
+
+static int rgmii_wol_probe(struct platform_device *ofdev)
+{
+ struct device_node *np = ofdev->dev.of_node;
+ struct rgmii_wol_instance *dev;
+ int rc;
+
+ rc = -ENOMEM;
+ dev = kzalloc(sizeof(struct rgmii_wol_instance), GFP_KERNEL);
+ if (dev == NULL)
+ goto err_gone;
+
+ mutex_init(&dev->lock);
+
+ dev->reg = of_iomap(np, 0);
+ if (!dev->reg) {
+ dev_err(&ofdev->dev, "Can't map registers\n");
+ rc = -ENXIO;
+ goto err_free;
+ }
+
+ /* Check for RGMII flags */
+ if (of_property_read_bool(np, "has-mdio"))
+ dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO;
+
+ dev_dbg(&ofdev->dev, " Boot REG = 0x%08x\n", in_be32(dev->reg));
+
+ /* Disable all inputs by default */
+ out_be32(dev->reg, 0);
+
+ dev_info(&ofdev->dev,
+ "RGMII %s initialized with%s MDIO support\n",
+ ofdev->dev.of_node->full_name,
+ (dev->flags & EMAC_RGMII_FLAG_HAS_MDIO) ? "" : "out");
+
+ wmb();
+ platform_set_drvdata(ofdev, dev);
+
+ return 0;
+
+ err_free:
+ kfree(dev);
+ err_gone:
+ return rc;
+}
+
+static int rgmii_wol_remove(struct platform_device *ofdev)
+{
+ struct rgmii_wol_instance *dev = platform_get_drvdata(ofdev);
+
+ WARN_ON(dev->users != 0);
+
+ iounmap(dev->reg);
+ kfree(dev);
+
+ return 0;
+}
+
+static struct of_device_id rgmii_wol_match[] = {
+ {
+ .compatible = "ibm,rgmii-wol",
+ },
+ {
+ .type = "emac-rgmii-wol",
+ },
+ {},
+};
+
+static struct platform_driver rgmii_wol_driver = {
+ .driver = {
+ .name = "emac-rgmii-wol",
+ .owner = THIS_MODULE,
+ .of_match_table = rgmii_wol_match,
+ },
+ .probe = rgmii_wol_probe,
+ .remove = rgmii_wol_remove,
+};
+
+int __init rgmii_wol_init(void)
+{
+ return platform_driver_register(&rgmii_wol_driver);
+}
+
+void rgmii_wol_exit(void)
+{
+ platform_driver_unregister(&rgmii_wol_driver);
+}
diff --git a/drivers/net/ethernet/ibm/emac/rgmii_wol.h b/drivers/net/ethernet/ibm/emac/rgmii_wol.h
new file mode 100644
index 0000000..9f0b589
--- /dev/null
+++ b/drivers/net/ethernet/ibm/emac/rgmii_wol.h
@@ -0,0 +1,62 @@
+/* drivers/net/ethernet/ibm/emac/rgmii_wol.h
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge with
+ * wake on LAN support.
+ *
+ * Copyright 2013 Alistair Popple, IBM Corp.
+ * <alistair@popple.id.au>
+ *
+ * Based on rgmii.h:
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * 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.
+ */
+
+#ifndef __IBM_NEWEMAC_RGMII_WOL_H
+#define __IBM_NEWEMAC_RGMII_WOL_H
+
+/* RGMII device */
+struct rgmii_wol_instance {
+ u32 __iomem *reg;
+
+ /* RGMII bridge flags */
+ int flags;
+#define EMAC_RGMII_FLAG_HAS_MDIO 0x00000001
+
+ /* Only one EMAC whacks us at a time */
+ struct mutex lock;
+
+ /* number of EMACs using this RGMII bridge */
+ int users;
+};
+
+#ifdef CONFIG_IBM_EMAC_RGMII_WOL
+
+extern int rgmii_wol_init(void);
+extern void rgmii_wol_exit(void);
+extern int rgmii_wol_attach(struct platform_device *ofdev, int mode);
+extern void rgmii_wol_detach(struct platform_device *ofdev);
+extern void rgmii_wol_get_mdio(struct platform_device *ofdev);
+extern void rgmii_wol_put_mdio(struct platform_device *ofdev);
+extern void rgmii_wol_set_speed(struct platform_device *ofdev, int speed);
+extern int rgmii_wol_get_regs_len(struct platform_device *ofdev);
+extern void *rgmii_wol_dump_regs(struct platform_device *ofdev, void *buf);
+
+#else
+
+# define rgmii_wol_init() 0
+# define rgmii_wol_exit() do { } while (0)
+# define rgmii_wol_attach(x, y) (-ENXIO)
+# define rgmii_wol_detach(x) do { } while (0)
+# define rgmii_wol_get_mdio(o) do { } while (0)
+# define rgmii_wol_put_mdio(o) do { } while (0)
+# define rgmii_wol_set_speed(x, y) do { } while (0)
+# define rgmii_wol_get_regs_len(x) 0
+# define rgmii_wol_dump_regs(x, buf) (buf)
+#endif /* !CONFIG_IBM_EMAC_RGMII_WOL */
+
+#endif /* __IBM_NEWEMAC_RGMII_WOL_H */
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/5] IBM Currituck: Clean up board specific code before adding Akebono code
From: Alistair Popple @ 2014-03-06 3:52 UTC (permalink / raw)
To: benh; +Cc: Alistair Popple, linuxppc-dev, linux-kernel, devicetree
In-Reply-To: <1394077948-8395-1-git-send-email-alistair@popple.id.au>
The IBM Akebono code uses the same initialisation functions as the
earlier Currituck board. Rather than create a copy of this code for
Akebono we will instead integrate support for it into the same file as
the Currituck code.
This patch just renames the board support file and updates the Makefile.
Signed-off-by: Alistair Popple <alistair@popple.id.au>
---
arch/powerpc/platforms/44x/Makefile | 2 +-
arch/powerpc/platforms/44x/currituck.c | 233 ---------------------------------
arch/powerpc/platforms/44x/ppc476.c | 233 +++++++++++++++++++++++++++++++++
3 files changed, 234 insertions(+), 234 deletions(-)
delete mode 100644 arch/powerpc/platforms/44x/currituck.c
create mode 100644 arch/powerpc/platforms/44x/ppc476.c
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
index d03833a..f896b89 100644
--- a/arch/powerpc/platforms/44x/Makefile
+++ b/arch/powerpc/platforms/44x/Makefile
@@ -10,4 +10,4 @@ obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o
obj-$(CONFIG_XILINX_ML510) += virtex_ml510.o
obj-$(CONFIG_ISS4xx) += iss4xx.o
obj-$(CONFIG_CANYONLANDS)+= canyonlands.o
-obj-$(CONFIG_CURRITUCK) += currituck.o
+obj-$(CONFIG_CURRITUCK) += ppc476.o
diff --git a/arch/powerpc/platforms/44x/currituck.c b/arch/powerpc/platforms/44x/currituck.c
deleted file mode 100644
index 7f1b71a..0000000
--- a/arch/powerpc/platforms/44x/currituck.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Currituck board specific routines
- *
- * Copyright © 2011 Tony Breeds IBM Corporation
- *
- * Based on earlier code:
- * Matt Porter <mporter@kernel.crashing.org>
- * Copyright 2002-2005 MontaVista Software Inc.
- *
- * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
- * Copyright (c) 2003-2005 Zultys Technologies
- *
- * Rewritten and ported to the merged powerpc tree:
- * Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
- * Copyright © 2011 David Kliekamp 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/init.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/rtc.h>
-
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/ppc4xx.h>
-#include <asm/mpic.h>
-#include <asm/mmu.h>
-
-#include <linux/pci.h>
-
-static __initdata struct of_device_id ppc47x_of_bus[] = {
- { .compatible = "ibm,plb4", },
- { .compatible = "ibm,plb6", },
- { .compatible = "ibm,opb", },
- { .compatible = "ibm,ebc", },
- {},
-};
-
-/* The EEPROM is missing and the default values are bogus. This forces USB in
- * to EHCI mode */
-static void quirk_ppc_currituck_usb_fixup(struct pci_dev *dev)
-{
- if (of_machine_is_compatible("ibm,currituck")) {
- pci_write_config_dword(dev, 0xe0, 0x0114231f);
- pci_write_config_dword(dev, 0xe4, 0x00006c40);
- }
-}
-DECLARE_PCI_FIXUP_HEADER(0x1033, 0x0035, quirk_ppc_currituck_usb_fixup);
-
-static int __init ppc47x_device_probe(void)
-{
- of_platform_bus_probe(NULL, ppc47x_of_bus, NULL);
-
- return 0;
-}
-machine_device_initcall(ppc47x, ppc47x_device_probe);
-
-/* We can have either UICs or MPICs */
-static void __init ppc47x_init_irq(void)
-{
- struct device_node *np;
-
- /* Find top level interrupt controller */
- for_each_node_with_property(np, "interrupt-controller") {
- if (of_get_property(np, "interrupts", NULL) == NULL)
- break;
- }
- if (np == NULL)
- panic("Can't find top level interrupt controller");
-
- /* Check type and do appropriate initialization */
- if (of_device_is_compatible(np, "chrp,open-pic")) {
- /* The MPIC driver will get everything it needs from the
- * device-tree, just pass 0 to all arguments
- */
- struct mpic *mpic =
- mpic_alloc(np, 0, MPIC_NO_RESET, 0, 0, " MPIC ");
- BUG_ON(mpic == NULL);
- mpic_init(mpic);
- ppc_md.get_irq = mpic_get_irq;
- } else
- panic("Unrecognized top level interrupt controller");
-}
-
-#ifdef CONFIG_SMP
-static void smp_ppc47x_setup_cpu(int cpu)
-{
- mpic_setup_this_cpu();
-}
-
-static int smp_ppc47x_kick_cpu(int cpu)
-{
- struct device_node *cpunode = of_get_cpu_node(cpu, NULL);
- const u64 *spin_table_addr_prop;
- u32 *spin_table;
- extern void start_secondary_47x(void);
-
- BUG_ON(cpunode == NULL);
-
- /* Assume spin table. We could test for the enable-method in
- * the device-tree but currently there's little point as it's
- * our only supported method
- */
- spin_table_addr_prop =
- of_get_property(cpunode, "cpu-release-addr", NULL);
-
- if (spin_table_addr_prop == NULL) {
- pr_err("CPU%d: Can't start, missing cpu-release-addr !\n",
- cpu);
- return 1;
- }
-
- /* Assume it's mapped as part of the linear mapping. This is a bit
- * fishy but will work fine for now
- *
- * XXX: Is there any reason to assume differently?
- */
- spin_table = (u32 *)__va(*spin_table_addr_prop);
- pr_debug("CPU%d: Spin table mapped at %p\n", cpu, spin_table);
-
- spin_table[3] = cpu;
- smp_wmb();
- spin_table[1] = __pa(start_secondary_47x);
- mb();
-
- return 0;
-}
-
-static struct smp_ops_t ppc47x_smp_ops = {
- .probe = smp_mpic_probe,
- .message_pass = smp_mpic_message_pass,
- .setup_cpu = smp_ppc47x_setup_cpu,
- .kick_cpu = smp_ppc47x_kick_cpu,
- .give_timebase = smp_generic_give_timebase,
- .take_timebase = smp_generic_take_timebase,
-};
-
-static void __init ppc47x_smp_init(void)
-{
- if (mmu_has_feature(MMU_FTR_TYPE_47x))
- smp_ops = &ppc47x_smp_ops;
-}
-
-#else /* CONFIG_SMP */
-static void __init ppc47x_smp_init(void) { }
-#endif /* CONFIG_SMP */
-
-static void __init ppc47x_setup_arch(void)
-{
-
- /* No need to check the DMA config as we /know/ our windows are all of
- * RAM. Lets hope that doesn't change */
- swiotlb_detect_4g();
-
- ppc47x_smp_init();
-}
-
-/*
- * Called very early, MMU is off, device-tree isn't unflattened
- */
-static int __init ppc47x_probe(void)
-{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "ibm,currituck"))
- return 0;
-
- return 1;
-}
-
-static int board_rev = -1;
-static int __init ppc47x_get_board_rev(void)
-{
- u8 fpga_reg0;
- void *fpga;
- struct device_node *np;
-
- np = of_find_compatible_node(NULL, NULL, "ibm,currituck-fpga");
- if (!np)
- goto fail;
-
- fpga = of_iomap(np, 0);
- of_node_put(np);
- if (!fpga)
- goto fail;
-
- fpga_reg0 = ioread8(fpga);
- board_rev = fpga_reg0 & 0x03;
- pr_info("%s: Found board revision %d\n", __func__, board_rev);
- iounmap(fpga);
- return 0;
-
-fail:
- pr_info("%s: Unable to find board revision\n", __func__);
- return 0;
-}
-machine_arch_initcall(ppc47x, ppc47x_get_board_rev);
-
-/* Use USB controller should have been hardware swizzled but it wasn't :( */
-static void ppc47x_pci_irq_fixup(struct pci_dev *dev)
-{
- if (dev->vendor == 0x1033 && (dev->device == 0x0035 ||
- dev->device == 0x00e0)) {
- if (board_rev == 0) {
- dev->irq = irq_create_mapping(NULL, 47);
- pr_info("%s: Mapping irq %d\n", __func__, dev->irq);
- } else if (board_rev == 2) {
- dev->irq = irq_create_mapping(NULL, 49);
- pr_info("%s: Mapping irq %d\n", __func__, dev->irq);
- } else {
- pr_alert("%s: Unknown board revision\n", __func__);
- }
- }
-}
-
-define_machine(ppc47x) {
- .name = "PowerPC 47x",
- .probe = ppc47x_probe,
- .progress = udbg_progress,
- .init_IRQ = ppc47x_init_irq,
- .setup_arch = ppc47x_setup_arch,
- .pci_irq_fixup = ppc47x_pci_irq_fixup,
- .restart = ppc4xx_reset_system,
- .calibrate_decr = generic_calibrate_decr,
-};
diff --git a/arch/powerpc/platforms/44x/ppc476.c b/arch/powerpc/platforms/44x/ppc476.c
new file mode 100644
index 0000000..c6c5a6f
--- /dev/null
+++ b/arch/powerpc/platforms/44x/ppc476.c
@@ -0,0 +1,233 @@
+/*
+ * PowerPC 476FPE board specific routines
+ *
+ * Copyright © 2011 Tony Breeds IBM Corporation
+ *
+ * Based on earlier code:
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003-2005 Zultys Technologies
+ *
+ * Rewritten and ported to the merged powerpc tree:
+ * Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
+ * Copyright © 2011 David Kliekamp 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/init.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/rtc.h>
+
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/time.h>
+#include <asm/uic.h>
+#include <asm/ppc4xx.h>
+#include <asm/mpic.h>
+#include <asm/mmu.h>
+
+#include <linux/pci.h>
+
+static struct of_device_id ppc47x_of_bus[] __initdata = {
+ { .compatible = "ibm,plb4", },
+ { .compatible = "ibm,plb6", },
+ { .compatible = "ibm,opb", },
+ { .compatible = "ibm,ebc", },
+ {},
+};
+
+/* The EEPROM is missing and the default values are bogus. This forces USB in
+ * to EHCI mode */
+static void quirk_ppc_currituck_usb_fixup(struct pci_dev *dev)
+{
+ if (of_machine_is_compatible("ibm,currituck")) {
+ pci_write_config_dword(dev, 0xe0, 0x0114231f);
+ pci_write_config_dword(dev, 0xe4, 0x00006c40);
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(0x1033, 0x0035, quirk_ppc_currituck_usb_fixup);
+
+static int __init ppc47x_device_probe(void)
+{
+ of_platform_bus_probe(NULL, ppc47x_of_bus, NULL);
+
+ return 0;
+}
+machine_device_initcall(ppc47x, ppc47x_device_probe);
+
+/* We can have either UICs or MPICs */
+static void __init ppc47x_init_irq(void)
+{
+ struct device_node *np;
+
+ /* Find top level interrupt controller */
+ for_each_node_with_property(np, "interrupt-controller") {
+ if (of_get_property(np, "interrupts", NULL) == NULL)
+ break;
+ }
+ if (np == NULL)
+ panic("Can't find top level interrupt controller");
+
+ /* Check type and do appropriate initialization */
+ if (of_device_is_compatible(np, "chrp,open-pic")) {
+ /* The MPIC driver will get everything it needs from the
+ * device-tree, just pass 0 to all arguments
+ */
+ struct mpic *mpic =
+ mpic_alloc(np, 0, MPIC_NO_RESET, 0, 0, " MPIC ");
+ BUG_ON(mpic == NULL);
+ mpic_init(mpic);
+ ppc_md.get_irq = mpic_get_irq;
+ } else
+ panic("Unrecognized top level interrupt controller");
+}
+
+#ifdef CONFIG_SMP
+static void smp_ppc47x_setup_cpu(int cpu)
+{
+ mpic_setup_this_cpu();
+}
+
+static int smp_ppc47x_kick_cpu(int cpu)
+{
+ struct device_node *cpunode = of_get_cpu_node(cpu, NULL);
+ const u64 *spin_table_addr_prop;
+ u32 *spin_table;
+ extern void start_secondary_47x(void);
+
+ BUG_ON(cpunode == NULL);
+
+ /* Assume spin table. We could test for the enable-method in
+ * the device-tree but currently there's little point as it's
+ * our only supported method
+ */
+ spin_table_addr_prop =
+ of_get_property(cpunode, "cpu-release-addr", NULL);
+
+ if (spin_table_addr_prop == NULL) {
+ pr_err("CPU%d: Can't start, missing cpu-release-addr !\n",
+ cpu);
+ return 1;
+ }
+
+ /* Assume it's mapped as part of the linear mapping. This is a bit
+ * fishy but will work fine for now
+ *
+ * XXX: Is there any reason to assume differently?
+ */
+ spin_table = (u32 *)__va(*spin_table_addr_prop);
+ pr_debug("CPU%d: Spin table mapped at %p\n", cpu, spin_table);
+
+ spin_table[3] = cpu;
+ smp_wmb();
+ spin_table[1] = __pa(start_secondary_47x);
+ mb();
+
+ return 0;
+}
+
+static struct smp_ops_t ppc47x_smp_ops = {
+ .probe = smp_mpic_probe,
+ .message_pass = smp_mpic_message_pass,
+ .setup_cpu = smp_ppc47x_setup_cpu,
+ .kick_cpu = smp_ppc47x_kick_cpu,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
+};
+
+static void __init ppc47x_smp_init(void)
+{
+ if (mmu_has_feature(MMU_FTR_TYPE_47x))
+ smp_ops = &ppc47x_smp_ops;
+}
+
+#else /* CONFIG_SMP */
+static void __init ppc47x_smp_init(void) { }
+#endif /* CONFIG_SMP */
+
+static void __init ppc47x_setup_arch(void)
+{
+
+ /* No need to check the DMA config as we /know/ our windows are all of
+ * RAM. Lets hope that doesn't change */
+ swiotlb_detect_4g();
+
+ ppc47x_smp_init();
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init ppc47x_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (!of_flat_dt_is_compatible(root, "ibm,currituck"))
+ return 0;
+
+ return 1;
+}
+
+static int board_rev = -1;
+static int __init ppc47x_get_board_rev(void)
+{
+ u8 fpga_reg0;
+ void *fpga;
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "ibm,currituck-fpga");
+ if (!np)
+ goto fail;
+
+ fpga = of_iomap(np, 0);
+ of_node_put(np);
+ if (!fpga)
+ goto fail;
+
+ fpga_reg0 = ioread8(fpga);
+ board_rev = fpga_reg0 & 0x03;
+ pr_info("%s: Found board revision %d\n", __func__, board_rev);
+ iounmap(fpga);
+ return 0;
+
+fail:
+ pr_info("%s: Unable to find board revision\n", __func__);
+ return 0;
+}
+machine_arch_initcall(ppc47x, ppc47x_get_board_rev);
+
+/* Use USB controller should have been hardware swizzled but it wasn't :( */
+static void ppc47x_pci_irq_fixup(struct pci_dev *dev)
+{
+ if (dev->vendor == 0x1033 && (dev->device == 0x0035 ||
+ dev->device == 0x00e0)) {
+ if (board_rev == 0) {
+ dev->irq = irq_create_mapping(NULL, 47);
+ pr_info("%s: Mapping irq %d\n", __func__, dev->irq);
+ } else if (board_rev == 2) {
+ dev->irq = irq_create_mapping(NULL, 49);
+ pr_info("%s: Mapping irq %d\n", __func__, dev->irq);
+ } else {
+ pr_alert("%s: Unknown board revision\n", __func__);
+ }
+ }
+}
+
+define_machine(ppc47x) {
+ .name = "PowerPC 47x",
+ .probe = ppc47x_probe,
+ .progress = udbg_progress,
+ .init_IRQ = ppc47x_init_irq,
+ .setup_arch = ppc47x_setup_arch,
+ .pci_irq_fixup = ppc47x_pci_irq_fixup,
+ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+};
--
1.8.3.2
^ permalink raw reply related
* [PATCH 4/5] IBM Akebono: Add the Akebono platform
From: Alistair Popple @ 2014-03-06 3:52 UTC (permalink / raw)
To: benh; +Cc: Alistair Popple, linuxppc-dev, linux-kernel, devicetree
In-Reply-To: <1394077948-8395-1-git-send-email-alistair@popple.id.au>
This patch adds support for the IBM Akebono board.
Signed-off-by: Alistair Popple <alistair@popple.id.au>
---
.../devicetree/bindings/powerpc/4xx/akebono.txt | 54 +++
arch/powerpc/boot/Makefile | 3 +
arch/powerpc/boot/dcr.h | 4 +
arch/powerpc/boot/dts/akebono.dts | 385 +++++++++++++++++++++
arch/powerpc/boot/treeboot-akebono.c | 178 ++++++++++
arch/powerpc/boot/wrapper | 3 +
arch/powerpc/configs/44x/akebono_defconfig | 148 ++++++++
arch/powerpc/platforms/44x/Kconfig | 26 ++
arch/powerpc/platforms/44x/Makefile | 1 +
arch/powerpc/platforms/44x/ppc476.c | 112 ++++--
arch/powerpc/sysdev/ppc4xx_pci.c | 13 +-
11 files changed, 901 insertions(+), 26 deletions(-)
create mode 100644 Documentation/devicetree/bindings/powerpc/4xx/akebono.txt
create mode 100644 arch/powerpc/boot/dts/akebono.dts
create mode 100644 arch/powerpc/boot/treeboot-akebono.c
create mode 100644 arch/powerpc/configs/44x/akebono_defconfig
diff --git a/Documentation/devicetree/bindings/powerpc/4xx/akebono.txt b/Documentation/devicetree/bindings/powerpc/4xx/akebono.txt
new file mode 100644
index 0000000..db93921
--- /dev/null
+++ b/Documentation/devicetree/bindings/powerpc/4xx/akebono.txt
@@ -0,0 +1,54 @@
+
+IBM Akebono board device tree
+=============================
+
+The IBM Akebono board is a development board for the PPC476GTR SoC.
+
+0) The root node
+
+ Required properties:
+
+ - model : "ibm,akebono".
+ - compatible : "ibm,akebono" , "ibm,476gtr".
+
+1.a) The Secure Digital Host Controller Interface (SDHCI) node
+
+ Represent the Secure Digital Host Controller Interfaces.
+
+ Required properties:
+
+ - compatible : should be "ibm,476gtr-sdhci","generic-sdhci".
+ - reg : should contain the SDHCI registers location and length.
+ - interrupt-parent : a phandle for the interrupt controller.
+ - interrupts : should contain the SDHCI interrupt.
+
+1.b) The Advanced Host Controller Interface (AHCI) SATA node
+
+ Represents the advanced host controller SATA interface.
+
+ Required properties:
+
+ - compatible : should be "ibm,476gtr-ahci".
+ - reg : should contain the AHCI registers location and length.
+ - interrupt-parent : a phandle for the interrupt controller.
+ - interrupts : should contain the AHCI interrupt.
+
+1.c) The FPGA node
+
+ The Akebono board stores some board information such as the revision
+ number in an FPGA which is represented by this node.
+
+ Required properties:
+
+ - compatible : should be "ibm,akebono-fpga".
+ - reg : should contain the FPGA registers location and length.
+
+1.d) The AVR node
+
+ The Akebono board has an Atmel AVR microprocessor attached to the I2C
+ bus as a power controller for the board.
+
+ Required properties:
+
+ - compatible : should be "ibm,akebono-avr".
+ - reg : should contain the I2C bus address for the AVR.
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 90e9d95..0a079a3 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -47,6 +47,7 @@ $(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405
$(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
$(obj)/treeboot-iss4xx.o: BOOTCFLAGS += -mcpu=405
$(obj)/treeboot-currituck.o: BOOTCFLAGS += -mcpu=405
+$(obj)/treeboot-akebono.o: BOOTCFLAGS += -mcpu=405
$(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405
@@ -86,6 +87,7 @@ src-plat-$(CONFIG_44x) += treeboot-ebony.c cuboot-ebony.c treeboot-bamboo.c \
cuboot-taishan.c cuboot-katmai.c \
cuboot-warp.c cuboot-yosemite.c \
treeboot-iss4xx.c treeboot-currituck.c \
+ treeboot-akebono.c \
simpleboot.c fixed-head.S virtex.c
src-plat-$(CONFIG_8xx) += cuboot-8xx.c fixed-head.S ep88xc.c redboot-8xx.c
src-plat-$(CONFIG_PPC_MPC52xx) += cuboot-52xx.c
@@ -236,6 +238,7 @@ image-$(CONFIG_YOSEMITE) += cuImage.yosemite
image-$(CONFIG_ISS4xx) += treeImage.iss4xx \
treeImage.iss4xx-mpic
image-$(CONFIG_CURRITUCK) += treeImage.currituck
+image-$(CONFIG_AKEBONO) += treeImage.akebono
# Board ports in arch/powerpc/platform/8xx/Kconfig
image-$(CONFIG_MPC86XADS) += cuImage.mpc866ads
diff --git a/arch/powerpc/boot/dcr.h b/arch/powerpc/boot/dcr.h
index cc73f7a..bf8f4ed 100644
--- a/arch/powerpc/boot/dcr.h
+++ b/arch/powerpc/boot/dcr.h
@@ -15,6 +15,10 @@
asm volatile("mfdcrx %0,%1" : "=r"(rval) : "r"(rn)); \
rval; \
})
+#define mtdcrx(rn, val) \
+ ({ \
+ asm volatile("mtdcrx %0,%1" : : "r"(rn), "r" (val)); \
+ })
/* 440GP/440GX SDRAM controller DCRs */
#define DCRN_SDRAM0_CFGADDR 0x010
diff --git a/arch/powerpc/boot/dts/akebono.dts b/arch/powerpc/boot/dts/akebono.dts
new file mode 100644
index 0000000..96ac13b
--- /dev/null
+++ b/arch/powerpc/boot/dts/akebono.dts
@@ -0,0 +1,385 @@
+/*
+ * Device Tree Source for IBM Embedded PPC 476 Platform
+ *
+ * Copyright © 2013 Tony Breeds IBM Corporation
+ * Copyright © 2013 Alistair Popple IBM Corporation
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without
+ * any warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x01f00000 0x00100000; // spin table
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "ibm,akebono";
+ compatible = "ibm,akebono", "ibm,476gtr";
+ dcr-parent = <&{/cpus/cpu@0}>;
+
+ aliases {
+ serial0 = &UART0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ model = "PowerPC,476";
+ reg = <0>;
+ clock-frequency = <1600000000>; // 1.6 GHz
+ timebase-frequency = <100000000>; // 100Mhz
+ i-cache-line-size = <32>;
+ d-cache-line-size = <32>;
+ i-cache-size = <32768>;
+ d-cache-size = <32768>;
+ dcr-controller;
+ dcr-access-method = "native";
+ status = "ok";
+ };
+ cpu@1 {
+ device_type = "cpu";
+ model = "PowerPC,476";
+ reg = <1>;
+ clock-frequency = <1600000000>; // 1.6 GHz
+ timebase-frequency = <100000000>; // 100Mhz
+ i-cache-line-size = <32>;
+ d-cache-line-size = <32>;
+ i-cache-size = <32768>;
+ d-cache-size = <32768>;
+ dcr-controller;
+ dcr-access-method = "native";
+ status = "disabled";
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x01f00000>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x0>; // filled in by zImage
+ };
+
+ MPIC: interrupt-controller {
+ compatible = "chrp,open-pic";
+ interrupt-controller;
+ dcr-reg = <0xffc00000 0x00040000>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ #interrupt-cells = <2>;
+ single-cpu-affinity;
+ };
+
+ plb {
+ compatible = "ibm,plb6";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ clock-frequency = <200000000>; // 200Mhz
+
+ MAL0: mcmal {
+ compatible = "ibm,mcmal-476gtr", "ibm,mcmal2";
+ dcr-reg = <0xc0000000 0x062>;
+ num-tx-chans = <1>;
+ num-rx-chans = <1>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ interrupt-parent = <&MPIC>;
+ interrupts = < /*TXEOB*/ 77 0x4
+ /*RXEOB*/ 78 0x4
+ /*SERR*/ 76 0x4
+ /*TXDE*/ 79 0x4
+ /*RXDE*/ 80 0x4>;
+ };
+
+ SATA0: sata@30000010000 {
+ compatible = "ibm,476gtr-ahci";
+ reg = <0x300 0x00010000 0x0 0x10000>;
+ interrupt-parent = <&MPIC>;
+ interrupts = <93 2>;
+ };
+
+ EHCI0: ehci@30010000000 {
+ compatible = "ibm,476gtr-ehci", "generic-ehci";
+ reg = <0x300 0x10000000 0x0 0x10000>;
+ interrupt-parent = <&MPIC>;
+ interrupts = <85 2>;
+ };
+
+ SD0: sd@30000000000 {
+ compatible = "ibm,476gtr-sdhci", "generic-sdhci";
+ reg = <0x300 0x00000000 0x0 0x10000>;
+ interrupts = <91 2>;
+ interrupt-parent = <&MPIC>;
+ };
+
+ OHCI0: ohci@30010010000 {
+ compatible = "ibm,476gtr-ohci", "generic-ohci";
+ reg = <0x300 0x10010000 0x0 0x10000>;
+ interrupt-parent = <&MPIC>;
+ interrupts = <89 1>;
+ };
+
+ OHCI1: ohci@30010020000 {
+ compatible = "ibm,476gtr-ohci", "generic-ohci";
+ reg = <0x300 0x10020000 0x0 0x10000>;
+ interrupt-parent = <&MPIC>;
+ interrupts = <88 1>;
+ };
+
+ POB0: opb {
+ compatible = "ibm,opb-4xx", "ibm,opb";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ /* Wish there was a nicer way of specifying a full
+ * 32-bit range
+ */
+ ranges = <0x00000000 0x0000033f 0x00000000 0x80000000
+ 0x80000000 0x0000033f 0x80000000 0x80000000>;
+ clock-frequency = <100000000>;
+
+ RGMII0: emac-rgmii-wol@50004 {
+ compatible = "ibm,rgmii-wol-476gtr", "ibm,rgmii-wol";
+ reg = <0x50004 0x00000008>;
+ has-mdio;
+ };
+
+ EMAC0: ethernet@30000 {
+ device_type = "network";
+ compatible = "ibm,emac-476gtr", "ibm,emac4sync";
+ interrupt-parent = <&EMAC0>;
+ interrupts = <0x0 0x1>;
+ #interrupt-cells = <1>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ interrupt-map = </*Status*/ 0x0 &MPIC 81 0x4
+ /*Wake*/ 0x1 &MPIC 82 0x4>;
+ reg = <0x30000 0x78>;
+
+ /* local-mac-address will normally be added by
+ * the wrapper. If your device doesn't support
+ * passing data to the wrapper (in the form
+ * local-mac-addr=<hwaddr>) then you will need
+ * to set it manually here. */
+ //local-mac-address = [000000000000];
+
+ mal-device = <&MAL0>;
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+ max-frame-size = <9000>;
+ rx-fifo-size = <4096>;
+ tx-fifo-size = <2048>;
+ rx-fifo-size-gige = <16384>;
+ phy-mode = "rgmii";
+ phy-map = <0x00000000>;
+ rgmii-wol-device = <&RGMII0>;
+ has-inverted-stacr-oc;
+ has-new-stacr-staopc;
+ };
+
+ UART0: serial@10000 {
+ device_type = "serial";
+ compatible = "ns16750", "ns16550";
+ reg = <0x10000 0x00000008>;
+ virtual-reg = <0xe8010000>;
+ clock-frequency = <1851851>;
+ current-speed = <38400>;
+ interrupt-parent = <&MPIC>;
+ interrupts = <39 2>;
+ };
+
+ IIC0: i2c@00000000 {
+ compatible = "ibm,iic-476gtr", "ibm,iic";
+ reg = <0x0 0x00000020>;
+ interrupt-parent = <&MPIC>;
+ interrupts = <37 2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ rtc@68 {
+ compatible = "stm,m41t80", "m41st85";
+ reg = <0x68>;
+ };
+ };
+
+ IIC1: i2c@00000100 {
+ compatible = "ibm,iic-476gtr", "ibm,iic";
+ reg = <0x100 0x00000020>;
+ interrupt-parent = <&MPIC>;
+ interrupts = <38 2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ avr@58 {
+ compatible = "ibm,akebono-avr";
+ reg = <0x58>;
+ };
+ };
+
+ FPGA0: fpga@ebc00000 {
+ compatible = "ibm,akebono-fpga";
+ reg = <0xebc00000 0x8>;
+ };
+ };
+
+ PCIE0: pciex@10100000000 {
+ device_type = "pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ compatible = "ibm,plb-pciex-476fpe", "ibm,plb-pciex";
+ primary;
+ port = <0x0>; /* port number */
+ reg = <0x00000101 0x00000000 0x0 0x10000000 /* Config space access */
+ 0x00000100 0x00000000 0x0 0x00001000>; /* UTL Registers space access */
+ dcr-reg = <0xc0 0x20>;
+
+// pci_space < pci_addr > < cpu_addr > < size >
+ ranges = <0x02000000 0x00000000 0x80000000 0x00000110 0x80000000 0x0 0x80000000
+ 0x01000000 0x0 0x0 0x00000140 0x0 0x0 0x00010000>;
+
+ /* Inbound starting at 0 to memsize filled in by zImage */
+ dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+
+ /* This drives busses 0 to 0xf */
+ bus-range = <0x0 0xf>;
+
+ /* Legacy interrupts (note the weird polarity, the bridge seems
+ * to invert PCIe legacy interrupts).
+ * We are de-swizzling here because the numbers are actually for
+ * port of the root complex virtual P2P bridge. But I want
+ * to avoid putting a node for it in the tree, so the numbers
+ * below are basically de-swizzled numbers.
+ * The real slot is on idsel 0, so the swizzling is 1:1
+ */
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <
+ 0x0 0x0 0x0 0x1 &MPIC 45 0x2 /* int A */
+ 0x0 0x0 0x0 0x2 &MPIC 46 0x2 /* int B */
+ 0x0 0x0 0x0 0x3 &MPIC 47 0x2 /* int C */
+ 0x0 0x0 0x0 0x4 &MPIC 48 0x2 /* int D */>;
+ };
+
+ PCIE1: pciex@20100000000 {
+ device_type = "pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ compatible = "ibm,plb-pciex-476fpe", "ibm,plb-pciex";
+ primary;
+ port = <0x1>; /* port number */
+ reg = <0x00000201 0x00000000 0x0 0x10000000 /* Config space access */
+ 0x00000200 0x00000000 0x0 0x00001000>; /* UTL Registers space access */
+ dcr-reg = <0x100 0x20>;
+
+// pci_space < pci_addr > < cpu_addr > < size >
+ ranges = <0x02000000 0x00000000 0x80000000 0x00000210 0x80000000 0x0 0x80000000
+ 0x01000000 0x0 0x0 0x00000240 0x0 0x0 0x00010000>;
+
+ /* Inbound starting at 0 to memsize filled in by zImage */
+ dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+
+ /* This drives busses 0 to 0xf */
+ bus-range = <0x0 0xf>;
+
+ /* Legacy interrupts (note the weird polarity, the bridge seems
+ * to invert PCIe legacy interrupts).
+ * We are de-swizzling here because the numbers are actually for
+ * port of the root complex virtual P2P bridge. But I want
+ * to avoid putting a node for it in the tree, so the numbers
+ * below are basically de-swizzled numbers.
+ * The real slot is on idsel 0, so the swizzling is 1:1
+ */
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <
+ 0x0 0x0 0x0 0x1 &MPIC 53 0x2 /* int A */
+ 0x0 0x0 0x0 0x2 &MPIC 54 0x2 /* int B */
+ 0x0 0x0 0x0 0x3 &MPIC 55 0x2 /* int C */
+ 0x0 0x0 0x0 0x4 &MPIC 56 0x2 /* int D */>;
+ };
+
+ PCIE2: pciex@18100000000 {
+ device_type = "pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ compatible = "ibm,plb-pciex-476fpe", "ibm,plb-pciex";
+ primary;
+ port = <0x2>; /* port number */
+ reg = <0x00000181 0x00000000 0x0 0x10000000 /* Config space access */
+ 0x00000180 0x00000000 0x0 0x00001000>; /* UTL Registers space access */
+ dcr-reg = <0xe0 0x20>;
+
+// pci_space < pci_addr > < cpu_addr > < size >
+ ranges = <0x02000000 0x00000000 0x80000000 0x00000190 0x80000000 0x0 0x80000000
+ 0x01000000 0x0 0x0 0x000001c0 0x0 0x0 0x00010000>;
+
+ /* Inbound starting at 0 to memsize filled in by zImage */
+ dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+
+ /* This drives busses 0 to 0xf */
+ bus-range = <0x0 0xf>;
+
+ /* Legacy interrupts (note the weird polarity, the bridge seems
+ * to invert PCIe legacy interrupts).
+ * We are de-swizzling here because the numbers are actually for
+ * port of the root complex virtual P2P bridge. But I want
+ * to avoid putting a node for it in the tree, so the numbers
+ * below are basically de-swizzled numbers.
+ * The real slot is on idsel 0, so the swizzling is 1:1
+ */
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <
+ 0x0 0x0 0x0 0x1 &MPIC 61 0x2 /* int A */
+ 0x0 0x0 0x0 0x2 &MPIC 62 0x2 /* int B */
+ 0x0 0x0 0x0 0x3 &MPIC 63 0x2 /* int C */
+ 0x0 0x0 0x0 0x4 &MPIC 64 0x2 /* int D */>;
+ };
+
+ PCIE3: pciex@28100000000 {
+ device_type = "pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ compatible = "ibm,plb-pciex-476fpe", "ibm,plb-pciex";
+ primary;
+ port = <0x3>; /* port number */
+ reg = <0x00000281 0x00000000 0x0 0x10000000 /* Config space access */
+ 0x00000280 0x00000000 0x0 0x00001000>; /* UTL Registers space access */
+ dcr-reg = <0x120 0x20>;
+
+// pci_space < pci_addr > < cpu_addr > < size >
+ ranges = <0x02000000 0x00000000 0x80000000 0x00000290 0x80000000 0x0 0x80000000
+ 0x01000000 0x0 0x0 0x000002c0 0x0 0x0 0x00010000>;
+
+ /* Inbound starting at 0 to memsize filled in by zImage */
+ dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+
+ /* This drives busses 0 to 0xf */
+ bus-range = <0x0 0xf>;
+
+ /* Legacy interrupts (note the weird polarity, the bridge seems
+ * to invert PCIe legacy interrupts).
+ * We are de-swizzling here because the numbers are actually for
+ * port of the root complex virtual P2P bridge. But I want
+ * to avoid putting a node for it in the tree, so the numbers
+ * below are basically de-swizzled numbers.
+ * The real slot is on idsel 0, so the swizzling is 1:1
+ */
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <
+ 0x0 0x0 0x0 0x1 &MPIC 69 0x2 /* int A */
+ 0x0 0x0 0x0 0x2 &MPIC 70 0x2 /* int B */
+ 0x0 0x0 0x0 0x3 &MPIC 71 0x2 /* int C */
+ 0x0 0x0 0x0 0x4 &MPIC 72 0x2 /* int D */>;
+ };
+ };
+
+ chosen {
+ linux,stdout-path = &UART0;
+ };
+};
diff --git a/arch/powerpc/boot/treeboot-akebono.c b/arch/powerpc/boot/treeboot-akebono.c
new file mode 100644
index 0000000..070a20f
--- /dev/null
+++ b/arch/powerpc/boot/treeboot-akebono.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright © 2013 Tony Breeds IBM Corporation
+ * Copyright © 2013 Alistair Popple IBM Corporation
+ *
+ * Based on earlier code:
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * Copyright 2007 David Gibson, IBM Corporation.
+ * Copyright 2010 Ben. Herrenschmidt, IBM Corporation.
+ * Copyright © 2011 David Kleikamp 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 <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+#include "reg.h"
+#include "io.h"
+#include "dcr.h"
+#include "4xx.h"
+#include "44x.h"
+#include "libfdt.h"
+
+BSS_STACK(4096);
+
+#define SPRN_PIR 0x11E /* Processor Indentification Register */
+#define USERDATA_LEN 256 /* Length of userdata passed in by PIBS */
+#define MAX_RANKS 0x4
+#define DDR3_MR0CF 0x80010011U
+#define CCTL0_MCO2 0x8000080FU
+#define CCTL0_MCO3 0x80000810U
+#define CCTL0_MCO4 0x80000811U
+#define CCTL0_MCO5 0x80000812U
+#define CCTL0_MCO6 0x80000813U
+
+static unsigned long long ibm_akebono_memsize;
+static long long unsigned mac_addr;
+
+static unsigned long long ibm_akebono_detect_memsize(void)
+{
+ u32 reg;
+ unsigned i;
+ unsigned long long memsize = 0;
+
+ for (i = 0; i < MAX_RANKS; i++) {
+ reg = mfdcrx(DDR3_MR0CF + i);
+
+ if (!(reg & 1))
+ continue;
+
+ reg &= 0x0000f000;
+ reg >>= 12;
+ memsize += (0x800000ULL << reg);
+ }
+
+ return memsize;
+}
+
+static void ibm_akebono_fixups(void)
+{
+ void *emac;
+ u32 reg;
+ void *devp = finddevice("/");
+ u32 dma_ranges[7];
+
+ dt_fixup_memory(0x0ULL, ibm_akebono_memsize);
+
+ while ((devp = find_node_by_devtype(devp, "pci"))) {
+ if (getprop(devp, "dma-ranges", dma_ranges,
+ sizeof(dma_ranges)) < 0) {
+ printf("%s: Failed to get dma-ranges\r\n", __func__);
+ continue;
+ }
+
+ dma_ranges[5] = ibm_akebono_memsize >> 32;
+ dma_ranges[6] = ibm_akebono_memsize & 0xffffffffUL;
+
+ setprop(devp, "dma-ranges", dma_ranges, sizeof(dma_ranges));
+ }
+
+ /* Fixup the SD timeout frequency */
+ mtdcrx(CCTL0_MCO4, 0x1);
+
+ /* Disable SD high-speed mode (which seems to be broken) */
+ reg = mfdcrx(CCTL0_MCO2) & ~0x2;
+ mtdcrx(CCTL0_MCO2, reg);
+
+ /* Set the MAC address */
+ emac = finddevice("/plb/opb/ethernet");
+ if (emac > 0) {
+ if (mac_addr)
+ setprop(emac, "local-mac-address",
+ ((u8 *) &mac_addr) + 2 , 6);
+ }
+}
+
+void platform_init(char *userdata)
+{
+ unsigned long end_of_ram, avail_ram;
+ u32 pir_reg;
+ int node, size;
+ const u32 *timebase;
+ int len, i, userdata_len;
+ char *end;
+
+ userdata[USERDATA_LEN - 1] = '\0';
+ userdata_len = strlen(userdata);
+ for (i = 0; i < userdata_len - 15; i++) {
+ if (strncmp(&userdata[i], "local-mac-addr=", 15) == 0) {
+ if (i > 0 && userdata[i - 1] != ' ') {
+ /* We've only found a substring ending
+ * with local-mac-addr so this isn't
+ * our mac address. */
+ continue;
+ }
+
+ mac_addr = strtoull(&userdata[i + 15], &end, 16);
+
+ /* Remove the "local-mac-addr=<...>" from the kernel
+ * command line, including the tailing space if
+ * present. */
+ if (*end == ' ')
+ end++;
+
+ len = ((int) end) - ((int) &userdata[i]);
+ memmove(&userdata[i], end,
+ userdata_len - (len + i) + 1);
+ break;
+ }
+ }
+
+ loader_info.cmdline = userdata;
+ loader_info.cmdline_len = 256;
+
+ ibm_akebono_memsize = ibm_akebono_detect_memsize();
+ if (ibm_akebono_memsize >> 32)
+ end_of_ram = ~0UL;
+ else
+ end_of_ram = ibm_akebono_memsize;
+ avail_ram = end_of_ram - (unsigned long)_end;
+
+ simple_alloc_init(_end, avail_ram, 128, 64);
+ platform_ops.fixups = ibm_akebono_fixups;
+ platform_ops.exit = ibm44x_dbcr_reset;
+ pir_reg = mfspr(SPRN_PIR);
+
+ /* Make sure FDT blob is sane */
+ if (fdt_check_header(_dtb_start) != 0)
+ fatal("Invalid device tree blob\n");
+
+ node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
+ "cpu", sizeof("cpu"));
+ if (!node)
+ fatal("Cannot find cpu node\n");
+ timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
+ if (timebase && (size == 4))
+ timebase_period_ns = 1000000000 / *timebase;
+
+ fdt_set_boot_cpuid_phys(_dtb_start, pir_reg);
+ fdt_init(_dtb_start);
+
+ serial_console_init();
+}
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index d27a255..c783264 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -257,6 +257,9 @@ gamecube|wii)
treeboot-currituck)
link_address='0x1000000'
;;
+treeboot-akebono)
+ link_address='0x1000000'
+ ;;
treeboot-iss4xx-mpic)
platformo="$object/treeboot-iss4xx.o"
;;
diff --git a/arch/powerpc/configs/44x/akebono_defconfig b/arch/powerpc/configs/44x/akebono_defconfig
new file mode 100644
index 0000000..7e2530c
--- /dev/null
+++ b/arch/powerpc/configs/44x/akebono_defconfig
@@ -0,0 +1,148 @@
+CONFIG_44x=y
+CONFIG_SMP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_EXPERT=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_SLUB_CPU_PARTIAL is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_POWERNV_MSI is not set
+CONFIG_PPC_47x=y
+# CONFIG_EBONY is not set
+CONFIG_AKEBONO=y
+CONFIG_HIGHMEM=y
+CONFIG_HZ_100=y
+CONFIG_IRQ_ALL_CPUS=y
+# CONFIG_COMPACTION is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE=""
+# CONFIG_SUSPEND is not set
+CONFIG_PCI_MSI=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=35000
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SATA_PMP is not set
+# CONFIG_ATA_SFF is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+CONFIG_IBM_EMAC=y
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_NET_VENDOR_XILINX is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+# CONFIG_USB_DEFAULT_PERSIST is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PCI is not set
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_M41T80=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_DEFAULT="n"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+CONFIG_PPC_EARLY_DEBUG=y
+CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0x00010000
+CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x33f
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1_PPC=y
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index dc1a264..b0202d8 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -199,6 +199,32 @@ config CURRITUCK
help
This option enables support for the IBM Currituck (476fpe) evaluation board
+config AKEBONO
+ bool "IBM Akebono (476gtr) Support"
+ depends on PPC_47x
+ default n
+ select SWIOTLB
+ select 476FPE
+ select PPC4xx_PCI_EXPRESS
+ select I2C
+ select I2C_IBM_IIC
+ select NETDEVICES
+ select ETHERNET
+ select NET_VENDOR_IBM
+ select IBM_EMAC_EMAC4
+ select IBM_EMAC_RGMII_WOL
+ select USB
+ select USB_OHCI_HCD_PLATFORM
+ select USB_EHCI_HCD_PLATFORM
+ select MMC_SDHCI
+ select MMC_SDHCI_PLTFM
+ select MMC_SDHCI_OF_476GTR
+ select ATA
+ select SATA_AHCI_PLATFORM
+ help
+ This option enables support for the IBM Akebono (476gtr) evaluation board
+
+
config ICON
bool "Icon"
depends on 44x
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
index f896b89..26d35b5 100644
--- a/arch/powerpc/platforms/44x/Makefile
+++ b/arch/powerpc/platforms/44x/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_XILINX_ML510) += virtex_ml510.o
obj-$(CONFIG_ISS4xx) += iss4xx.o
obj-$(CONFIG_CANYONLANDS)+= canyonlands.o
obj-$(CONFIG_CURRITUCK) += ppc476.o
+obj-$(CONFIG_AKEBONO) += ppc476.o
diff --git a/arch/powerpc/platforms/44x/ppc476.c b/arch/powerpc/platforms/44x/ppc476.c
index c6c5a6f..33986c1 100644
--- a/arch/powerpc/platforms/44x/ppc476.c
+++ b/arch/powerpc/platforms/44x/ppc476.c
@@ -1,7 +1,8 @@
/*
* PowerPC 476FPE board specific routines
*
- * Copyright © 2011 Tony Breeds IBM Corporation
+ * Copyright © 2013 Tony Breeds IBM Corporation
+ * Copyright © 2013 Alistair Popple IBM Corporation
*
* Based on earlier code:
* Matt Porter <mporter@kernel.crashing.org>
@@ -35,6 +36,7 @@
#include <asm/mmu.h>
#include <linux/pci.h>
+#include <linux/i2c.h>
static struct of_device_id ppc47x_of_bus[] __initdata = {
{ .compatible = "ibm,plb4", },
@@ -55,15 +57,69 @@ static void quirk_ppc_currituck_usb_fixup(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(0x1033, 0x0035, quirk_ppc_currituck_usb_fixup);
+/* Akebono has an AVR microcontroller attached to the I2C bus
+ * which is used to power off/reset the system. */
+
+/* AVR I2C Commands */
+#define AVR_PWRCTL_CMD (0x26)
+
+/* Flags for the power control I2C commands */
+#define AVR_PWRCTL_PWROFF (0x01)
+#define AVR_PWRCTL_RESET (0x02)
+
+static struct i2c_client *avr_i2c_client;
+static void avr_halt_system(int pwrctl_flags)
+{
+ /* Request the AVR to reset the system */
+ i2c_smbus_write_byte_data(avr_i2c_client,
+ AVR_PWRCTL_CMD, pwrctl_flags);
+
+ /* Wait for system to be reset */
+ while (1)
+ ;
+}
+
+static void avr_power_off_system(void)
+{
+ avr_halt_system(AVR_PWRCTL_PWROFF);
+}
+
+static void avr_reset_system(char *cmd)
+{
+ avr_halt_system(AVR_PWRCTL_RESET);
+}
+
+static int avr_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ avr_i2c_client = client;
+ ppc_md.restart = avr_reset_system;
+ ppc_md.power_off = avr_power_off_system;
+ return 0;
+}
+
+static const struct i2c_device_id avr_id[] = {
+ { "akebono-avr", 0 },
+ { }
+};
+
+static struct i2c_driver avr_driver = {
+ .driver = {
+ .name = "akebono-avr",
+ },
+ .probe = avr_probe,
+ .id_table = avr_id,
+};
+
static int __init ppc47x_device_probe(void)
{
+ i2c_add_driver(&avr_driver);
of_platform_bus_probe(NULL, ppc47x_of_bus, NULL);
return 0;
}
machine_device_initcall(ppc47x, ppc47x_device_probe);
-/* We can have either UICs or MPICs */
static void __init ppc47x_init_irq(void)
{
struct device_node *np;
@@ -163,37 +219,30 @@ static void __init ppc47x_setup_arch(void)
ppc47x_smp_init();
}
-/*
- * Called very early, MMU is off, device-tree isn't unflattened
- */
-static int __init ppc47x_probe(void)
-{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "ibm,currituck"))
- return 0;
-
- return 1;
-}
-
static int board_rev = -1;
static int __init ppc47x_get_board_rev(void)
{
- u8 fpga_reg0;
- void *fpga;
- struct device_node *np;
+ int reg;
+ u8 *fpga;
+ struct device_node *np = NULL;
+
+ if (of_machine_is_compatible("ibm,currituck")) {
+ np = of_find_compatible_node(NULL, NULL, "ibm,currituck-fpga");
+ reg = 0;
+ } else if (of_machine_is_compatible("ibm,akebono")) {
+ np = of_find_compatible_node(NULL, NULL, "ibm,akebono-fpga");
+ reg = 2;
+ }
- np = of_find_compatible_node(NULL, NULL, "ibm,currituck-fpga");
if (!np)
goto fail;
- fpga = of_iomap(np, 0);
+ fpga = (u8 *) of_iomap(np, 0);
of_node_put(np);
if (!fpga)
goto fail;
- fpga_reg0 = ioread8(fpga);
- board_rev = fpga_reg0 & 0x03;
+ board_rev = ioread8(fpga + reg) & 0x03;
pr_info("%s: Found board revision %d\n", __func__, board_rev);
iounmap(fpga);
return 0;
@@ -221,13 +270,30 @@ static void ppc47x_pci_irq_fixup(struct pci_dev *dev)
}
}
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init ppc47x_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (of_flat_dt_is_compatible(root, "ibm,akebono"))
+ return 1;
+
+ if (of_flat_dt_is_compatible(root, "ibm,currituck")) {
+ ppc_md.pci_irq_fixup = ppc47x_pci_irq_fixup;
+ return 1;
+ }
+
+ return 0;
+}
+
define_machine(ppc47x) {
.name = "PowerPC 47x",
.probe = ppc47x_probe,
.progress = udbg_progress,
.init_IRQ = ppc47x_init_irq,
.setup_arch = ppc47x_setup_arch,
- .pci_irq_fixup = ppc47x_pci_irq_fixup,
.restart = ppc4xx_reset_system,
.calibrate_decr = generic_calibrate_decr,
};
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 64603a1..54ec1d5 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -1440,7 +1440,8 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
ppc4xx_pciex_hwops = &ppc405ex_pcie_hwops;
#endif
#ifdef CONFIG_476FPE
- if (of_device_is_compatible(np, "ibm,plb-pciex-476fpe"))
+ if (of_device_is_compatible(np, "ibm,plb-pciex-476fpe")
+ || of_device_is_compatible(np, "ibm,plb-pciex-476gtr"))
ppc4xx_pciex_hwops = &ppc_476fpe_pcie_hwops;
#endif
if (ppc4xx_pciex_hwops == NULL) {
@@ -1751,7 +1752,10 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port,
dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT
| DCRO_PEGPL_OMRxMSKL_VAL);
- else if (of_device_is_compatible(port->node, "ibm,plb-pciex-476fpe"))
+ else if (of_device_is_compatible(
+ port->node, "ibm,plb-pciex-476fpe") ||
+ of_device_is_compatible(
+ port->node, "ibm,plb-pciex-476gtr"))
dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
sa | DCRO_PEGPL_476FPE_OMR1MSKL_UOT
| DCRO_PEGPL_OMRxMSKL_VAL);
@@ -1881,7 +1885,10 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
sa |= PCI_BASE_ADDRESS_MEM_PREFETCH;
if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx") ||
- of_device_is_compatible(port->node, "ibm,plb-pciex-476fpe"))
+ of_device_is_compatible(
+ port->node, "ibm,plb-pciex-476fpe") ||
+ of_device_is_compatible(
+ port->node, "ibm,plb-pciex-476gtr"))
sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;
out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
--
1.8.3.2
^ permalink raw reply related
* [PATCH 5/5] powerpc: Added PCI MSI support using the HSTA module
From: Alistair Popple @ 2014-03-06 3:52 UTC (permalink / raw)
To: benh; +Cc: Alistair Popple, linuxppc-dev, linux-kernel, devicetree
In-Reply-To: <1394077948-8395-1-git-send-email-alistair@popple.id.au>
The PPC476GTR SoC supports message signalled interrupts (MSI) by writing
to special addresses within the High Speed Transfer Assist (HSTA) module.
This patch adds support for PCI MSI with a new system device. The DMA
window is also updated to allow access to the entire 42-bit address range
to allow PCI devices write access to the HSTA module.
Signed-off-by: Alistair Popple <alistair@popple.id.au>
---
.../devicetree/bindings/powerpc/4xx/hsta.txt | 19 ++
arch/powerpc/boot/dts/akebono.dts | 46 ++++-
arch/powerpc/boot/treeboot-akebono.c | 15 --
arch/powerpc/platforms/44x/Kconfig | 2 +
arch/powerpc/sysdev/Kconfig | 6 +
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/ppc4xx_hsta_msi.c | 215 +++++++++++++++++++++
arch/powerpc/sysdev/ppc4xx_pci.c | 8 +-
8 files changed, 287 insertions(+), 25 deletions(-)
create mode 100644 Documentation/devicetree/bindings/powerpc/4xx/hsta.txt
create mode 100644 arch/powerpc/sysdev/ppc4xx_hsta_msi.c
diff --git a/Documentation/devicetree/bindings/powerpc/4xx/hsta.txt b/Documentation/devicetree/bindings/powerpc/4xx/hsta.txt
new file mode 100644
index 0000000..c737c83
--- /dev/null
+++ b/Documentation/devicetree/bindings/powerpc/4xx/hsta.txt
@@ -0,0 +1,19 @@
+
+ppc476gtr High Speed Serial Assist (HSTA) node
+==============================================
+
+The 476gtr SoC contains a high speed serial assist module attached
+between the plb4 and plb6 system buses to provide high speed data
+transfer between memory and system peripherals as well as support for
+PCI message signalled interrupts.
+
+Currently only the MSI support is used by Linux using the following
+device tree entries:
+
+Require properties:
+- compatible : "ibm,476gtr-hsta-msi", "ibm,hsta-msi"
+- reg : register mapping for the HSTA MSI space
+- interrupt-parent : parent controller for mapping interrupts
+- interrupts : ordered interrupt mapping for each MSI in the register
+ space. The first interrupt should be associated with a
+ register offset of 0x00, the second to 0x10, etc.
diff --git a/arch/powerpc/boot/dts/akebono.dts b/arch/powerpc/boot/dts/akebono.dts
index 96ac13b..f92ecfe 100644
--- a/arch/powerpc/boot/dts/akebono.dts
+++ b/arch/powerpc/boot/dts/akebono.dts
@@ -82,6 +82,28 @@
ranges;
clock-frequency = <200000000>; // 200Mhz
+ HSTA0: hsta@310000e0000 {
+ compatible = "ibm,476gtr-hsta-msi", "ibm,hsta-msi";
+ reg = <0x310 0x000e0000 0x0 0xf0>;
+ interrupt-parent = <&MPIC>;
+ interrupts = <108 0
+ 109 0
+ 110 0
+ 111 0
+ 112 0
+ 113 0
+ 114 0
+ 115 0
+ 116 0
+ 117 0
+ 118 0
+ 119 0
+ 120 0
+ 121 0
+ 122 0
+ 123 0>;
+ };
+
MAL0: mcmal {
compatible = "ibm,mcmal-476gtr", "ibm,mcmal2";
dcr-reg = <0xc0000000 0x062>;
@@ -242,8 +264,10 @@
ranges = <0x02000000 0x00000000 0x80000000 0x00000110 0x80000000 0x0 0x80000000
0x01000000 0x0 0x0 0x00000140 0x0 0x0 0x00010000>;
- /* Inbound starting at 0 to memsize filled in by zImage */
- dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+ /* Inbound starting at 0x0 to 0x40000000000. In order to use MSI
+ * PCI devices must be able to write to the HSTA module.
+ */
+ dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x400 0x0>;
/* This drives busses 0 to 0xf */
bus-range = <0x0 0xf>;
@@ -280,8 +304,10 @@
ranges = <0x02000000 0x00000000 0x80000000 0x00000210 0x80000000 0x0 0x80000000
0x01000000 0x0 0x0 0x00000240 0x0 0x0 0x00010000>;
- /* Inbound starting at 0 to memsize filled in by zImage */
- dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+ /* Inbound starting at 0x0 to 0x40000000000. In order to use MSI
+ * PCI devices must be able to write to the HSTA module.
+ */
+ dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x400 0x0>;
/* This drives busses 0 to 0xf */
bus-range = <0x0 0xf>;
@@ -318,8 +344,10 @@
ranges = <0x02000000 0x00000000 0x80000000 0x00000190 0x80000000 0x0 0x80000000
0x01000000 0x0 0x0 0x000001c0 0x0 0x0 0x00010000>;
- /* Inbound starting at 0 to memsize filled in by zImage */
- dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+ /* Inbound starting at 0x0 to 0x40000000000. In order to use MSI
+ * PCI devices must be able to write to the HSTA module.
+ */
+ dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x400 0x0>;
/* This drives busses 0 to 0xf */
bus-range = <0x0 0xf>;
@@ -356,8 +384,10 @@
ranges = <0x02000000 0x00000000 0x80000000 0x00000290 0x80000000 0x0 0x80000000
0x01000000 0x0 0x0 0x000002c0 0x0 0x0 0x00010000>;
- /* Inbound starting at 0 to memsize filled in by zImage */
- dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+ /* Inbound starting at 0x0 to 0x40000000000. In order to use MSI
+ * PCI devices must be able to write to the HSTA module.
+ */
+ dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x400 0x0>;
/* This drives busses 0 to 0xf */
bus-range = <0x0 0xf>;
diff --git a/arch/powerpc/boot/treeboot-akebono.c b/arch/powerpc/boot/treeboot-akebono.c
index 070a20f..b73174c 100644
--- a/arch/powerpc/boot/treeboot-akebono.c
+++ b/arch/powerpc/boot/treeboot-akebono.c
@@ -75,24 +75,9 @@ static void ibm_akebono_fixups(void)
{
void *emac;
u32 reg;
- void *devp = finddevice("/");
- u32 dma_ranges[7];
dt_fixup_memory(0x0ULL, ibm_akebono_memsize);
- while ((devp = find_node_by_devtype(devp, "pci"))) {
- if (getprop(devp, "dma-ranges", dma_ranges,
- sizeof(dma_ranges)) < 0) {
- printf("%s: Failed to get dma-ranges\r\n", __func__);
- continue;
- }
-
- dma_ranges[5] = ibm_akebono_memsize >> 32;
- dma_ranges[6] = ibm_akebono_memsize & 0xffffffffUL;
-
- setprop(devp, "dma-ranges", dma_ranges, sizeof(dma_ranges));
- }
-
/* Fixup the SD timeout frequency */
mtdcrx(CCTL0_MCO4, 0x1);
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index b0202d8..8beec7d 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -206,6 +206,8 @@ config AKEBONO
select SWIOTLB
select 476FPE
select PPC4xx_PCI_EXPRESS
+ select PCI_MSI
+ select PPC4xx_HSTA_MSI
select I2C
select I2C_IBM_IIC
select NETDEVICES
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index 7baa70d..a19332a 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -7,6 +7,12 @@ config PPC4xx_PCI_EXPRESS
depends on PCI && 4xx
default n
+config PPC4xx_HSTA_MSI
+ bool
+ depends on PCI_MSI
+ depends on PCI && 4xx
+ default n
+
config PPC4xx_MSI
bool
depends on PCI_MSI
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index afbcc37..f7cb2a1 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_OF_RTC) += of_rtc.o
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_4xx) += ppc4xx_pci.o
endif
+obj-$(CONFIG_PPC4xx_HSTA_MSI) += ppc4xx_hsta_msi.o
obj-$(CONFIG_PPC4xx_MSI) += ppc4xx_msi.o
obj-$(CONFIG_PPC4xx_CPM) += ppc4xx_cpm.o
obj-$(CONFIG_PPC4xx_GPIO) += ppc4xx_gpio.o
diff --git a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c
new file mode 100644
index 0000000..11c8884
--- /dev/null
+++ b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c
@@ -0,0 +1,215 @@
+/*
+ * MSI support for PPC4xx SoCs using High Speed Transfer Assist (HSTA) for
+ * generation of the interrupt.
+ *
+ * Copyright © 2013 Alistair Popple <alistair@popple.id.au> 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/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/msi.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/semaphore.h>
+#include <asm/msi_bitmap.h>
+
+struct ppc4xx_hsta_msi {
+ struct device *dev;
+
+ /* The ioremapped HSTA MSI IO space */
+ u32 __iomem *data;
+
+ /* Physical address of HSTA MSI IO space */
+ u64 address;
+ struct msi_bitmap bmp;
+
+ /* An array mapping offsets to hardware IRQs */
+ int *irq_map;
+
+ /* Number of hwirqs supported */
+ int irq_count;
+};
+static struct ppc4xx_hsta_msi ppc4xx_hsta_msi;
+
+static int hsta_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+ struct msi_msg msg;
+ struct msi_desc *entry;
+ int irq, hwirq;
+ u64 addr;
+
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ irq = msi_bitmap_alloc_hwirqs(&ppc4xx_hsta_msi.bmp, 1);
+ if (irq < 0) {
+ pr_debug("%s: Failed to allocate msi interrupt\n",
+ __func__);
+ return irq;
+ }
+
+ hwirq = ppc4xx_hsta_msi.irq_map[irq];
+ if (hwirq == NO_IRQ) {
+ pr_err("%s: Failed mapping irq %d\n", __func__, irq);
+ return -EINVAL;
+ }
+
+ /*
+ * HSTA generates interrupts on writes to 128-bit aligned
+ * addresses.
+ */
+ addr = ppc4xx_hsta_msi.address + irq*0x10;
+ msg.address_hi = upper_32_bits(addr);
+ msg.address_lo = lower_32_bits(addr);
+
+ /* Data is not used by the HSTA. */
+ msg.data = 0;
+
+ pr_debug("%s: Setup irq %d (0x%0llx)\n", __func__, hwirq,
+ (((u64) msg.address_hi) << 32) | msg.address_lo);
+
+ if (irq_set_msi_desc(hwirq, entry)) {
+ pr_err(
+ "%s: Invalid hwirq %d specified in device tree\n",
+ __func__, hwirq);
+ msi_bitmap_free_hwirqs(&ppc4xx_hsta_msi.bmp, irq, 1);
+ return -EINVAL;
+ }
+ write_msi_msg(hwirq, &msg);
+ }
+
+ return 0;
+}
+
+static int hsta_find_hwirq_offset(int hwirq)
+{
+ int irq;
+
+ /* Find the offset given the hwirq */
+ for (irq = 0; irq < ppc4xx_hsta_msi.irq_count; irq++)
+ if (ppc4xx_hsta_msi.irq_map[irq] == hwirq)
+ return irq;
+
+ return -EINVAL;
+}
+
+static void hsta_teardown_msi_irqs(struct pci_dev *dev)
+{
+ struct msi_desc *entry;
+ int irq;
+
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ if (entry->irq == NO_IRQ)
+ continue;
+
+ irq = hsta_find_hwirq_offset(entry->irq);
+
+ /* entry->irq should always be in irq_map */
+ BUG_ON(irq < 0);
+ irq_set_msi_desc(entry->irq, NULL);
+ msi_bitmap_free_hwirqs(&ppc4xx_hsta_msi.bmp, irq, 1);
+ pr_debug("%s: Teardown IRQ %u (index %u)\n", __func__,
+ entry->irq, irq);
+ }
+}
+
+static int hsta_msi_check_device(struct pci_dev *pdev, int nvec, int type)
+{
+ /* We don't support MSI-X */
+ if (type == PCI_CAP_ID_MSIX) {
+ pr_debug("%s: MSI-X not supported.\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hsta_msi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *mem;
+ int irq, ret, irq_count;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (IS_ERR(mem)) {
+ dev_err(dev, "Unable to get mmio space\n");
+ return -EINVAL;
+ }
+
+ irq_count = of_irq_count(dev->of_node);
+ if (!irq_count) {
+ dev_err(dev, "Unable to find IRQ range\n");
+ return -EINVAL;
+ }
+
+ ppc4xx_hsta_msi.dev = dev;
+ ppc4xx_hsta_msi.address = mem->start;
+ ppc4xx_hsta_msi.data = ioremap(mem->start, resource_size(mem));
+ ppc4xx_hsta_msi.irq_count = irq_count;
+ if (IS_ERR(ppc4xx_hsta_msi.data)) {
+ dev_err(dev, "Unable to map memory\n");
+ return -ENOMEM;
+ }
+
+ ret = msi_bitmap_alloc(&ppc4xx_hsta_msi.bmp, irq_count, dev->of_node);
+ if (ret)
+ goto out;
+
+ ppc4xx_hsta_msi.irq_map = kmalloc(sizeof(int) * irq_count, GFP_KERNEL);
+ if (IS_ERR(ppc4xx_hsta_msi.irq_map)) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ /* Setup a mapping from irq offsets to hardware irq numbers */
+ for (irq = 0; irq < irq_count; irq++) {
+ ppc4xx_hsta_msi.irq_map[irq] =
+ irq_of_parse_and_map(dev->of_node, irq);
+ if (ppc4xx_hsta_msi.irq_map[irq] == NO_IRQ) {
+ dev_err(dev, "Unable to map IRQ\n");
+ ret = -EINVAL;
+ goto out2;
+ }
+ }
+
+ ppc_md.setup_msi_irqs = hsta_setup_msi_irqs;
+ ppc_md.teardown_msi_irqs = hsta_teardown_msi_irqs;
+ ppc_md.msi_check_device = hsta_msi_check_device;
+ return 0;
+
+out2:
+ kfree(ppc4xx_hsta_msi.irq_map);
+
+out1:
+ msi_bitmap_free(&ppc4xx_hsta_msi.bmp);
+
+out:
+ iounmap(ppc4xx_hsta_msi.data);
+ return ret;
+}
+
+static const struct of_device_id hsta_msi_ids[] = {
+ {
+ .compatible = "ibm,hsta-msi",
+ },
+ {}
+};
+
+static struct platform_driver hsta_msi_driver = {
+ .probe = hsta_msi_probe,
+ .driver = {
+ .name = "hsta-msi",
+ .owner = THIS_MODULE,
+ .of_match_table = hsta_msi_ids,
+ },
+};
+
+static int hsta_msi_init(void)
+{
+ return platform_driver_register(&hsta_msi_driver);
+}
+subsys_initcall(hsta_msi_init);
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 54ec1d5..7cc3acc 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -176,8 +176,12 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
return -ENXIO;
}
- /* Check that we are fully contained within 32 bits space */
- if (res->end > 0xffffffff) {
+ /* Check that we are fully contained within 32 bits space if we are not
+ * running on a 460sx or 476fpe which have 64 bit bus addresses.
+ */
+ if (res->end > 0xffffffff &&
+ !(of_device_is_compatible(hose->dn, "ibm,plb-pciex-460sx")
+ || of_device_is_compatible(hose->dn, "ibm,plb-pciex-476fpe"))) {
printk(KERN_ERR "%s: dma-ranges outside of 32 bits space\n",
hose->dn->full_name);
return -ENXIO;
--
1.8.3.2
^ permalink raw reply related
* [RFC][PATCH 1/3] power: perf: Enable saving the user stack in a sample.
From: Sukadev Bhattiprolu @ 2014-03-06 4:41 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
Paul Mackerras, Jiri Olsa
In-Reply-To: <1394080919-17957-1-git-send-email-sukadev@linux.vnet.ibm.com>
When requested, have the kernel save the user stack in each perf sample
so 'perf report' can use libunwind and produce better backtraces.
The downside of course is that the kernel has to copy the user-stack
on each sample which has both performance and file-size implications
(of the perf.data file).
But we save the user-stack only when user explicitly requests it:
perf record --call-graph=dwarf,8192 <application>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
arch/powerpc/Kconfig | 2 +
arch/powerpc/include/uapi/asm/perf_regs.h | 70 +++++++++++++++++++
arch/powerpc/perf/Makefile | 1 +
arch/powerpc/perf/perf-regs.c | 104 +++++++++++++++++++++++++++++
4 files changed, 177 insertions(+)
create mode 100644 arch/powerpc/include/uapi/asm/perf_regs.h
create mode 100644 arch/powerpc/perf/perf-regs.c
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 957bf34..e79ce6e 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -113,6 +113,8 @@ config PPC
select GENERIC_ATOMIC64 if PPC32
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select HAVE_PERF_EVENTS
+ select HAVE_PERF_REGS
+ select HAVE_PERF_USER_STACK_DUMP
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
select ARCH_WANT_IPC_PARSE_VERSION
diff --git a/arch/powerpc/include/uapi/asm/perf_regs.h b/arch/powerpc/include/uapi/asm/perf_regs.h
new file mode 100644
index 0000000..b6120dc
--- /dev/null
+++ b/arch/powerpc/include/uapi/asm/perf_regs.h
@@ -0,0 +1,70 @@
+#ifndef _ASM_POWERPC_PERF_REGS_H
+#define _ASM_POWERPC_PERF_REGS_H
+
+#ifndef __powerpc64__
+#error Support for 32bit processors is TBD.
+#endif
+
+enum perf_event_powerpc_regs {
+ /*
+ * The order of these values are based on the corresponding
+ * macros in arch/powerpc/include/uapi/asm/ptrace.h .
+ */
+ PERF_REG_POWERPC_GPR0,
+ PERF_REG_POWERPC_GPR1,
+ PERF_REG_POWERPC_GPR2,
+ PERF_REG_POWERPC_GPR3,
+ PERF_REG_POWERPC_GPR4,
+ PERF_REG_POWERPC_GPR5,
+ PERF_REG_POWERPC_GPR6,
+ PERF_REG_POWERPC_GPR7,
+ PERF_REG_POWERPC_GPR8,
+ PERF_REG_POWERPC_GPR9,
+
+ PERF_REG_POWERPC_GPR10,
+ PERF_REG_POWERPC_GPR11,
+ PERF_REG_POWERPC_GPR12,
+ PERF_REG_POWERPC_GPR13,
+ PERF_REG_POWERPC_GPR14,
+ PERF_REG_POWERPC_GPR15,
+ PERF_REG_POWERPC_GPR16,
+ PERF_REG_POWERPC_GPR17,
+ PERF_REG_POWERPC_GPR18,
+ PERF_REG_POWERPC_GPR19,
+
+ PERF_REG_POWERPC_GPR20,
+ PERF_REG_POWERPC_GPR21,
+ PERF_REG_POWERPC_GPR22,
+ PERF_REG_POWERPC_GPR23,
+ PERF_REG_POWERPC_GPR24,
+ PERF_REG_POWERPC_GPR25,
+ PERF_REG_POWERPC_GPR26,
+ PERF_REG_POWERPC_GPR27,
+ PERF_REG_POWERPC_GPR28,
+ PERF_REG_POWERPC_GPR29,
+
+ PERF_REG_POWERPC_GPR30,
+ PERF_REG_POWERPC_GPR31,
+
+ PERF_REG_POWERPC_NIP,
+ PERF_REG_POWERPC_MSR,
+ PERF_REG_POWERPC_ORIG_GPR3,
+ PERF_REG_POWERPC_CTR, /* 35 */
+
+ PERF_REG_POWERPC_LINK,
+ PERF_REG_POWERPC_XER,
+ PERF_REG_POWERPC_CCR,
+#ifdef __powerpc64__
+ PERF_REG_POWERPC_SOFTE,
+#else
+ PERF_REG_POWERPC_MQ,
+#endif
+ PERF_REG_POWERPC_TRAP, /* 40 */
+
+ PERF_REG_POWERPC_DAR,
+ PERF_REG_POWERPC_DSISR,
+ PERF_REG_POWERPC_RESULT,
+ PERF_REG_POWERPC_DSCR,
+ PERF_REG_POWERPC_MAX
+};
+#endif
diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile
index 60d71ee..44fec45 100644
--- a/arch/powerpc/perf/Makefile
+++ b/arch/powerpc/perf/Makefile
@@ -2,6 +2,7 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
obj-$(CONFIG_PERF_EVENTS) += callchain.o
+obj-$(CONFIG_HAVE_PERF_REGS) += perf-regs.o
obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o bhrb.o
obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \
power5+-pmu.o power6-pmu.o power7-pmu.o \
diff --git a/arch/powerpc/perf/perf-regs.c b/arch/powerpc/perf/perf-regs.c
new file mode 100644
index 0000000..3963038
--- /dev/null
+++ b/arch/powerpc/perf/perf-regs.c
@@ -0,0 +1,104 @@
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <asm/perf_regs.h>
+
+#define PT_REGS_GPR_OFFSET(g) \
+ [PERF_REG_POWERPC_GPR##g] = offsetof(struct pt_regs, gpr[g])
+
+#define PT_REGS_OFFSET(n, r) \
+ [PERF_REG_POWERPC_##n] = offsetof(struct pt_regs, r)
+
+/*
+ * An enum in arch/powerpc/include/uapi/asm/perf_regs.h assigns an "id" to
+ * each register in Power. Build a table mapping each register id to its
+ * offset in 'struct pt_regs', that we can use to quickly read-from or
+ * write-to the register in pt_regs.
+ */
+static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = {
+ PT_REGS_GPR_OFFSET(0),
+ PT_REGS_GPR_OFFSET(1),
+ PT_REGS_GPR_OFFSET(2),
+ PT_REGS_GPR_OFFSET(3),
+ PT_REGS_GPR_OFFSET(4),
+ PT_REGS_GPR_OFFSET(5),
+ PT_REGS_GPR_OFFSET(6),
+ PT_REGS_GPR_OFFSET(7),
+ PT_REGS_GPR_OFFSET(8),
+ PT_REGS_GPR_OFFSET(9),
+ PT_REGS_GPR_OFFSET(10),
+
+ PT_REGS_GPR_OFFSET(11),
+ PT_REGS_GPR_OFFSET(12),
+ PT_REGS_GPR_OFFSET(13),
+ PT_REGS_GPR_OFFSET(14),
+ PT_REGS_GPR_OFFSET(15),
+ PT_REGS_GPR_OFFSET(16),
+ PT_REGS_GPR_OFFSET(17),
+ PT_REGS_GPR_OFFSET(18),
+ PT_REGS_GPR_OFFSET(19),
+ PT_REGS_GPR_OFFSET(20),
+
+ PT_REGS_GPR_OFFSET(21),
+ PT_REGS_GPR_OFFSET(22),
+ PT_REGS_GPR_OFFSET(23),
+ PT_REGS_GPR_OFFSET(24),
+ PT_REGS_GPR_OFFSET(25),
+ PT_REGS_GPR_OFFSET(26),
+ PT_REGS_GPR_OFFSET(27),
+ PT_REGS_GPR_OFFSET(28),
+ PT_REGS_GPR_OFFSET(29),
+ PT_REGS_GPR_OFFSET(30),
+
+ PT_REGS_GPR_OFFSET(31),
+
+ PT_REGS_OFFSET(NIP, nip),
+ PT_REGS_OFFSET(MSR, msr),
+ PT_REGS_OFFSET(ORIG_GPR3, orig_gpr3),
+ PT_REGS_OFFSET(CTR, ctr),
+
+ PT_REGS_OFFSET(LINK, link),
+ PT_REGS_OFFSET(XER, xer),
+ PT_REGS_OFFSET(CCR, ccr),
+#ifdef __powerpc64__
+ PT_REGS_OFFSET(SOFTE, softe),
+#else
+ PT_REGS_OFFSET(MQ, mq),
+#endif
+
+ PT_REGS_OFFSET(TRAP, trap),
+ PT_REGS_OFFSET(DAR, dar),
+ PT_REGS_OFFSET(DSISR, dsisr),
+ PT_REGS_OFFSET(RESULT, result),
+};
+
+u64 perf_reg_value(struct pt_regs *regs, int idx)
+{
+ if (WARN_ON_ONCE(idx >= ARRAY_SIZE(pt_regs_offset)))
+ return 0;
+
+ return regs_get_register(regs, pt_regs_offset[idx]);
+}
+
+u64 perf_reg_validate(u64 mask)
+{
+ /*
+ * TODO: Are there any registers to ignore/check here ?
+ */
+ if (!mask)
+ return -EINVAL;
+
+ return 0;
+}
+
+u64 perf_reg_abi(struct task_struct *task)
+{
+ /*
+ * TODO: WHAT SHOULD WE RETURN HERE ????
+ *
+ * x86 returns PERF_SAMPLE_REGS_ABI_32
+ * perf tool needs this to be non-zero to process registers.
+ */
+ return 1;
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCH 0/3] powerpc/perf: Enable linking with libunwind
From: Sukadev Bhattiprolu @ 2014-03-06 4:41 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
Paul Mackerras, Jiri Olsa
When we try to create backtraces (call-graphs) with the perf tool
perf record -g /tmp/sprintft
we get backtraces with duplicate arcs for sprintft[1]:
14.61% sprintft libc-2.18.so [.] __random
|
--- __random
|
|--61.09%-- __random
| |
| |--97.18%-- rand
| | do_my_sprintf
| | main
| | generic_start_main.isra.0
| | __libc_start_main
| | 0x0
| |
| --2.82%-- do_my_sprintf
| main
| generic_start_main.isra.0
| __libc_start_main
| 0x0
|
--38.91%-- rand
|
|--92.90%-- rand
| |
| |--99.87%-- do_my_sprintf
| | main
| | generic_start_main.isra.0
| | __libc_start_main
| | 0x0
| --0.13%-- [...]
|
--7.10%-- do_my_sprintf
main
generic_start_main.isra.0
__libc_start_main
0x0
(where the two arcs both have the same backtrace but are not merged).
Linking with libunwind seems to create better backtraces. While x86 and
ARM processors have support for linking with libunwind but Power does not.
This patchset is an RFC for linking with libunwind.
With this patchset and running:
/tmp/perf record --call-graph=dwarf,8192 /tmp/sprintft
the backtrace is:
14.94% sprintft libc-2.18.so [.] __random
|
--- __random
rand
do_my_sprintf
main
generic_start_main.isra.0
__libc_start_main
(nil)
This appears better.
One downside is that we now need the kernel to save the entire user stack
(the 8192 in the command line is the default user stack size).
A second issue is that this invocation of perf (with --call-graph=dwarf,8192)
seems to fail for backtraces involving tail-calls[2]
/tmp/perf record -g ./tailcall
gives
20.00% tailcall tailcall [.] work2
|
--- work2
work
shows the tail function 'work2' as "called from" 'work()'
But with libunwind:
/tmp/perf record --call-graph=dwarf,8192 ./tailcall
we get:
20.50% tailcall tailcall [.] work2
|
--- work2
the caller of 'work' is not shown.
I am debugging this, but would appreciate any feedback/pointers on the
patchset/direction:
- Does libunwind need the entire user stack to work or are there
optimizations we can do to save the minimal entries for it to
perform the unwind.
- Does libunwind work with tailcalls like the one above ?
- Are there benefits to linking with libunwind (even if it does not
yet solve the tailcall problem)
- Are there any examples of using libdwarf to solve the tailcall
issue ?
[1] sprintft (excerpt from a test program by Maynard Johnson).
char * do_my_sprintf(char * strx, int num)
{
int i;
for (i = 0; i < inner_iterations; i++) {
int r = rand() % 10;
sprintf(my_string, "%s ...%d\n", strx+r, num);
if (strlen(my_string) > 15)
num = 15;
}
return my_string;
}
[2] tailcall (Powerpc assembly, from Anton Blanchard)
Build with: gcc -O2 --static -nostdlib -o tailcall tailcall.S
#define ITERATIONS 1000000000
.align 2
.globl _start
.globl ._start
.section ".opd","aw"
_start:
.quad ._start
.quad .TOC.@tocbase
.quad 0;
.text;
._start:
lis 4,ITERATIONS@h
ori 4,4,ITERATIONS@l
mtctr 4
1: bl work
bdnz 1b
li 0,1 /* sys_exit */
sc
work:
mflr 30
bl work2
mtlr 30
blr
work2:
blr
Sukadev Bhattiprolu (3):
power: perf: Enable saving the user stack in a sample.
power: perf tool: Add libunwind support for Power
perf: Use 64-bit value when comparing sample_regs
arch/powerpc/Kconfig | 2 +
arch/powerpc/include/uapi/asm/perf_regs.h | 70 ++++++++++++++++++
arch/powerpc/perf/Makefile | 1 +
arch/powerpc/perf/perf-regs.c | 104 +++++++++++++++++++++++++++
tools/perf/arch/powerpc/Makefile | 5 ++
tools/perf/arch/powerpc/include/perf_regs.h | 69 ++++++++++++++++++
tools/perf/arch/powerpc/util/unwind.c | 63 ++++++++++++++++
tools/perf/config/Makefile | 7 ++
tools/perf/util/unwind.c | 4 +-
9 files changed, 323 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/include/uapi/asm/perf_regs.h
create mode 100644 arch/powerpc/perf/perf-regs.c
create mode 100644 tools/perf/arch/powerpc/include/perf_regs.h
create mode 100644 tools/perf/arch/powerpc/util/unwind.c
--
1.7.9.5
^ permalink raw reply
* [PATCH 3/3] perf: Use 64-bit value when comparing sample_regs
From: Sukadev Bhattiprolu @ 2014-03-06 4:41 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
Paul Mackerras, Jiri Olsa
In-Reply-To: <1394080919-17957-1-git-send-email-sukadev@linux.vnet.ibm.com>
When checking whether a bit representing a register is set in
sample_regs, a 64-bit mask, use 64-bit value (1LL).
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
tools/perf/util/unwind.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c
index 742f23b..2b888c6 100644
--- a/tools/perf/util/unwind.c
+++ b/tools/perf/util/unwind.c
@@ -396,11 +396,11 @@ static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id,
{
int i, idx = 0;
- if (!(sample_regs & (1 << id)))
+ if (!(sample_regs & (1LL << id)))
return -EINVAL;
for (i = 0; i < id; i++) {
- if (sample_regs & (1 << i))
+ if (sample_regs & (1LL << i))
idx++;
}
--
1.7.9.5
^ permalink raw reply related
* [RFC][PATCH 2/3] power: perf tool: Add libunwind support for Power
From: Sukadev Bhattiprolu @ 2014-03-06 4:41 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
Paul Mackerras, Jiri Olsa
In-Reply-To: <1394080919-17957-1-git-send-email-sukadev@linux.vnet.ibm.com>
Add ability to link with libunwind on Power.
This is based on similar changes in x86 and arm. Basically, implement
accessor functions that libunwind can call into while building the
backtrace from the user stack (which the kernel saved in a perf sample
- in previous commit).
Tested on Fedora-20 with libunwind and libunwind-devel libdwarf packages
installed.
TODO:
- Not sure if we need to list all the Power registers or restrict
to only those that libunwind needs.
- Check about perf_reg_abi()
- Build for 32-bit
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
tools/perf/arch/powerpc/Makefile | 5 ++
tools/perf/arch/powerpc/include/perf_regs.h | 69 +++++++++++++++++++++++++++
tools/perf/arch/powerpc/util/unwind.c | 63 ++++++++++++++++++++++++
tools/perf/config/Makefile | 7 +++
4 files changed, 144 insertions(+)
create mode 100644 tools/perf/arch/powerpc/include/perf_regs.h
create mode 100644 tools/perf/arch/powerpc/util/unwind.c
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index 744e629..9d3b8ce 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -2,4 +2,9 @@ ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
endif
+
+ifndef NO_LIBUNWIND
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o
+endif
+
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h
new file mode 100644
index 0000000..d5667da
--- /dev/null
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -0,0 +1,69 @@
+#ifndef ARCH_PERF_REGS_H
+#define ARCH_PERF_REGS_H
+
+#include <asm/perf_regs.h>
+
+#define PERF_REGS_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1)
+#define PERF_REG_IP PERF_REG_POWERPC_NIP
+#define PERF_REG_SP PERF_REG_POWERPC_GPR1
+
+static inline const char *perf_reg_name(int id)
+{
+ switch (id) {
+ case PERF_REG_POWERPC_GPR0: return "R0";
+ case PERF_REG_POWERPC_GPR1: return "R1";
+ case PERF_REG_POWERPC_GPR2: return "R2";
+ case PERF_REG_POWERPC_GPR3: return "R3";
+ case PERF_REG_POWERPC_GPR4: return "R4";
+ case PERF_REG_POWERPC_GPR5: return "R5";
+ case PERF_REG_POWERPC_GPR6: return "R6";
+ case PERF_REG_POWERPC_GPR7: return "R7";
+ case PERF_REG_POWERPC_GPR8: return "R8";
+ case PERF_REG_POWERPC_GPR9: return "R9";
+ case PERF_REG_POWERPC_GPR10: return "R10";
+ case PERF_REG_POWERPC_GPR11: return "R11";
+ case PERF_REG_POWERPC_GPR12: return "R12";
+ case PERF_REG_POWERPC_GPR13: return "R13";
+ case PERF_REG_POWERPC_GPR14: return "R14";
+ case PERF_REG_POWERPC_GPR15: return "R15";
+ case PERF_REG_POWERPC_GPR16: return "R16";
+ case PERF_REG_POWERPC_GPR17: return "R17";
+ case PERF_REG_POWERPC_GPR18: return "R18";
+ case PERF_REG_POWERPC_GPR19: return "R19";
+ case PERF_REG_POWERPC_GPR20: return "R20";
+ case PERF_REG_POWERPC_GPR21: return "R21";
+ case PERF_REG_POWERPC_GPR22: return "R22";
+ case PERF_REG_POWERPC_GPR23: return "R23";
+ case PERF_REG_POWERPC_GPR24: return "R24";
+ case PERF_REG_POWERPC_GPR25: return "R25";
+ case PERF_REG_POWERPC_GPR26: return "R26";
+ case PERF_REG_POWERPC_GPR27: return "R27";
+ case PERF_REG_POWERPC_GPR28: return "R28";
+ case PERF_REG_POWERPC_GPR29: return "R29";
+ case PERF_REG_POWERPC_GPR30: return "R30";
+ case PERF_REG_POWERPC_GPR31: return "R31";
+
+ case PERF_REG_POWERPC_NIP: return "NIP";
+ case PERF_REG_POWERPC_MSR: return "MSR";
+ case PERF_REG_POWERPC_ORIG_GPR3: return "ORIG_GPR3";
+ case PERF_REG_POWERPC_CTR: return "CTR";
+ case PERF_REG_POWERPC_LINK: return "LINK";
+ case PERF_REG_POWERPC_XER: return "XER";
+ case PERF_REG_POWERPC_CCR: return "CCR";
+
+#ifdef __powerpc64__
+ case PERF_REG_POWERPC_SOFTE: return "SOFTE";
+#else
+ case PERF_REG_POWERPC_MQ: return "MQ";
+#endif
+ case PERF_REG_POWERPC_TRAP: return "TRAP";
+ case PERF_REG_POWERPC_DAR: return "DAR";
+ case PERF_REG_POWERPC_DSISR: return "DSISR";
+ case PERF_REG_POWERPC_RESULT: return "RESULT";
+
+ default: return NULL;
+ }
+ return NULL;
+}
+
+#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/powerpc/util/unwind.c b/tools/perf/arch/powerpc/util/unwind.c
new file mode 100644
index 0000000..ba73399
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/unwind.c
@@ -0,0 +1,63 @@
+#ifdef HAVE_ARCH_POWERPC_SUPPORT
+#include <libunwind.h> /* UNW_PPC64* macros */
+#include <asm/perf_regs.h> /* PERF_REG* macros */
+#include "../../util/unwind.h" /* unwind__arch_reg_id() prototype */
+#include <errno.h>
+
+/*
+ * Map Libunwind's "UNWIND" register ids to "PERF" register ids.
+ *
+ * One place where this mapping is used is when unwinding the user
+ * stack saved in a perf-sample by the kernel. The kernel uses the
+ * "PERF" register ids to find offset of the register in 'struct
+ * pt_regs'. When using libunwind, we find the "PERF" register id
+ * and use it to retrieve the register contents from the sample.
+ */
+int unwind__arch_reg_id(int regnum)
+{
+ switch (regnum) {
+ case UNW_PPC64_R0: return PERF_REG_POWERPC_GPR0;
+ case UNW_PPC64_R1: return PERF_REG_POWERPC_GPR1;
+ case UNW_PPC64_R2: return PERF_REG_POWERPC_GPR2;
+ case UNW_PPC64_R3: return PERF_REG_POWERPC_GPR3;
+ case UNW_PPC64_R4: return PERF_REG_POWERPC_GPR4;
+ case UNW_PPC64_R5: return PERF_REG_POWERPC_GPR5;
+ case UNW_PPC64_R6: return PERF_REG_POWERPC_GPR6;
+ case UNW_PPC64_R7: return PERF_REG_POWERPC_GPR7;
+ case UNW_PPC64_R8: return PERF_REG_POWERPC_GPR8;
+ case UNW_PPC64_R9: return PERF_REG_POWERPC_GPR9;
+ case UNW_PPC64_R10: return PERF_REG_POWERPC_GPR9;
+ case UNW_PPC64_R11: return PERF_REG_POWERPC_GPR11;
+ case UNW_PPC64_R12: return PERF_REG_POWERPC_GPR12;
+ case UNW_PPC64_R13: return PERF_REG_POWERPC_GPR13;
+ case UNW_PPC64_R14: return PERF_REG_POWERPC_GPR14;
+ case UNW_PPC64_R15: return PERF_REG_POWERPC_GPR15;
+ case UNW_PPC64_R16: return PERF_REG_POWERPC_GPR16;
+ case UNW_PPC64_R17: return PERF_REG_POWERPC_GPR17;
+ case UNW_PPC64_R18: return PERF_REG_POWERPC_GPR18;
+ case UNW_PPC64_R19: return PERF_REG_POWERPC_GPR19;
+ case UNW_PPC64_R20: return PERF_REG_POWERPC_GPR20;
+ case UNW_PPC64_R21: return PERF_REG_POWERPC_GPR21;
+ case UNW_PPC64_R22: return PERF_REG_POWERPC_GPR22;
+ case UNW_PPC64_R23: return PERF_REG_POWERPC_GPR23;
+ case UNW_PPC64_R24: return PERF_REG_POWERPC_GPR24;
+ case UNW_PPC64_R25: return PERF_REG_POWERPC_GPR25;
+ case UNW_PPC64_R26: return PERF_REG_POWERPC_GPR26;
+ case UNW_PPC64_R27: return PERF_REG_POWERPC_GPR27;
+ case UNW_PPC64_R28: return PERF_REG_POWERPC_GPR28;
+ case UNW_PPC64_R29: return PERF_REG_POWERPC_GPR29;
+ case UNW_PPC64_R30: return PERF_REG_POWERPC_GPR30;
+ case UNW_PPC64_R31: return PERF_REG_POWERPC_GPR31;
+
+ case UNW_PPC64_LR: return PERF_REG_POWERPC_LINK;
+ case UNW_PPC64_CTR: return PERF_REG_POWERPC_CTR;
+ case UNW_PPC64_XER: return PERF_REG_POWERPC_XER;
+ case UNW_PPC64_NIP: return PERF_REG_POWERPC_NIP;
+
+ default:
+ pr_err("unwind: invalid reg id %d\n", regnum);
+ return -EINVAL;
+ }
+ return -EINVAL;
+}
+#endif /* HAVE_ARCH_POWERPC_SUPPORT */
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index c48d449..6446afd 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -29,11 +29,18 @@ ifeq ($(ARCH),x86)
endif
NO_PERF_REGS := 0
endif
+
ifeq ($(ARCH),arm)
NO_PERF_REGS := 0
LIBUNWIND_LIBS = -lunwind -lunwind-arm
endif
+ifeq ($(ARCH),powerpc)
+ CFLAGS += -DHAVE_ARCH_POWERPC_SUPPORT
+ NO_PERF_REGS := 0
+ LIBUNWIND_LIBS = -lunwind -lunwind-ppc64
+endif
+
ifeq ($(LIBUNWIND_LIBS),)
NO_LIBUNWIND := 1
else
--
1.7.9.5
^ permalink raw reply related
* [PATCH] powerpc: compat: 32 bit little endian machine name is ppcle, not ppc
From: Anton Blanchard @ 2014-03-06 5:10 UTC (permalink / raw)
To: benh, paulus, linuxppc-dev
I noticed this when testing setarch. No, we don't magically
support a big endian userspace on a little endian kernel.
Signed-off-by: Anton Blanchard <anton@samba.org>
Cc: stable@vger.kernel.org # v3.10+
---
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index 84fdf68..ef22898 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -8,7 +8,11 @@
#include <linux/sched.h>
#define COMPAT_USER_HZ 100
+#ifdef __BIG_ENDIAN__
#define COMPAT_UTS_MACHINE "ppc\0\0"
+#else
+#define COMPAT_UTS_MACHINE "ppcle\0\0"
+#endif
typedef u32 compat_size_t;
typedef s32 compat_ssize_t;
^ permalink raw reply related
* Re: [PATCH] powerpc/le: fix endianness of the arguments passed to the ppc_rtas() syscall
From: Benjamin Herrenschmidt @ 2014-03-06 5:43 UTC (permalink / raw)
To: Greg Kurz; +Cc: linuxppc-dev, paulus, anton, linux-kernel
In-Reply-To: <20140305172006.26117.57219.stgit@bahia.local>
On Wed, 2014-03-05 at 18:20 +0100, Greg Kurz wrote:
> RTAS manipulates its input and output arguments in big endian order.
>
> I have looked at factoring some lines with rtas_call() but it is not really
> worth it because of the variable arguments.
I'm not sure about that one ...
So this assumes that userspace will pass the RTAS arguments LE...
This will work only as long as the arguments are indeed just an array
of u32's. The minute userspace tries to crap something like two u16's
in one argument or a u64 accross two arguments, it has the potential
to be broken depending on how it has been done.
I would have done it the other way around which is to define that
ppc_rtas takes a BE structure since this is what RTAS expects (and
the bit of RMA memory we expose to userspace for communicating with
it also has to be handled BE so userspace has to know anyway).
That means that the only things we need to fix here is when we interpret
the args.nargs etc... we need a be32_to_cpu
Cheers,
Ben.
> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> ---
> arch/powerpc/kernel/rtas.c | 15 +++++++++++++--
> 1 file changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
> index 4cf674d..00dbe36 100644
> --- a/arch/powerpc/kernel/rtas.c
> +++ b/arch/powerpc/kernel/rtas.c
> @@ -1020,6 +1020,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
> char *buff_copy, *errbuf = NULL;
> int nargs;
> int rc;
> + int i;
>
> if (!capable(CAP_SYS_ADMIN))
> return -EPERM;
> @@ -1056,9 +1057,19 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
>
> flags = lock_rtas();
>
> - rtas.args = args;
> + rtas.args.token = cpu_to_be32(args.token);
> + rtas.args.nargs = cpu_to_be32(args.nargs);
> + rtas.args.nret = cpu_to_be32(args.nret);
> + for (i = 0; i < nargs; ++i)
> + rtas.args.args[i] = cpu_to_be32(args.args[i]);
> + rtas.args.rets = &rtas.args.args[nargs];
> + for (i = 0; i < args.nret; ++i)
> + rtas.args.rets[i] = 0;
> +
> enter_rtas(__pa(&rtas.args));
> - args = rtas.args;
> +
> + for (i = 0; i < args.nret; ++i)
> + args.rets[i] = be32_to_cpu(rtas.args.rets[i]);
>
> /* A -1 return code indicates that the last command couldn't
> be completed due to a hardware error. */
^ permalink raw reply
* [PATCH 1/5] powerpc/perf: Reject EBB events which specify a sample_type
From: Michael Ellerman @ 2014-03-06 6:59 UTC (permalink / raw)
To: linuxppc-dev; +Cc: ymanton, Paul Mackerras, khandual
Although we already block EBB events which request sampling using
sample_period, technically it's possible for an event to set sample_type
but not sample_period.
Nothing terrible will happen if an EBB event does specify sample_type,
but it signals a major confusion on the part of userspace, and so we do
them the favor of rejecting it.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/perf/core-book3s.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 67cf220..4b2ba0c 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -502,8 +502,11 @@ static int ebb_event_check(struct perf_event *event)
if (!leader->attr.pinned || !leader->attr.exclusive)
return -EINVAL;
- if (event->attr.inherit || event->attr.sample_period ||
- event->attr.enable_on_exec || event->attr.freq)
+ if (event->attr.freq ||
+ event->attr.inherit ||
+ event->attr.sample_type ||
+ event->attr.sample_period ||
+ event->attr.enable_on_exec)
return -EINVAL;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/5] powerpc/perf: Clean up the EBB hash defines a little
From: Michael Ellerman @ 2014-03-06 6:59 UTC (permalink / raw)
To: linuxppc-dev; +Cc: ymanton, Paul Mackerras, khandual
In-Reply-To: <1394089152-603-1-git-send-email-mpe@ellerman.id.au>
Rather than using PERF_EVENT_CONFIG_EBB_SHIFT everywhere, add an
EVENT_EBB_SHIFT like every other event and use that.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/perf/power8-pmu.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 96cee20..26905ce 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -117,6 +117,7 @@
*/
#define EVENT_EBB_MASK 1ull
+#define EVENT_EBB_SHIFT PERF_EVENT_CONFIG_EBB_SHIFT
#define EVENT_THR_CMP_SHIFT 40 /* Threshold CMP value */
#define EVENT_THR_CMP_MASK 0x3ff
#define EVENT_THR_CTL_SHIFT 32 /* Threshold control value (start/stop) */
@@ -149,7 +150,7 @@
(EVENT_UNIT_MASK << EVENT_UNIT_SHIFT) | \
(EVENT_COMBINE_MASK << EVENT_COMBINE_SHIFT) | \
(EVENT_MARKED_MASK << EVENT_MARKED_SHIFT) | \
- (EVENT_EBB_MASK << PERF_EVENT_CONFIG_EBB_SHIFT) | \
+ (EVENT_EBB_MASK << EVENT_EBB_SHIFT) | \
EVENT_PSEL_MASK)
/* MMCRA IFM bits - POWER8 */
@@ -265,10 +266,10 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
pmc = (event >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK;
unit = (event >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK;
cache = (event >> EVENT_CACHE_SEL_SHIFT) & EVENT_CACHE_SEL_MASK;
- ebb = (event >> PERF_EVENT_CONFIG_EBB_SHIFT) & EVENT_EBB_MASK;
+ ebb = (event >> EVENT_EBB_SHIFT) & EVENT_EBB_MASK;
/* Clear the EBB bit in the event, so event checks work below */
- event &= ~(EVENT_EBB_MASK << PERF_EVENT_CONFIG_EBB_SHIFT);
+ event &= ~(EVENT_EBB_MASK << EVENT_EBB_SHIFT);
if (pmc) {
if (pmc > 6)
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/5] powerpc/perf: Avoid mutating event in power8_get_constraint()
From: Michael Ellerman @ 2014-03-06 6:59 UTC (permalink / raw)
To: linuxppc-dev; +Cc: ymanton, Paul Mackerras, khandual
In-Reply-To: <1394089152-603-1-git-send-email-mpe@ellerman.id.au>
We only need to mask the EBB bit out of the event for the check of the
special PMC 5 & 6 events. So use a local to do it just for that code,
rather than changing the event value for the life of the function.
While we're there move the set of mask and value after all the checks.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/perf/power8-pmu.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 26905ce..04c1c77 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -268,18 +268,20 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
cache = (event >> EVENT_CACHE_SEL_SHIFT) & EVENT_CACHE_SEL_MASK;
ebb = (event >> EVENT_EBB_SHIFT) & EVENT_EBB_MASK;
- /* Clear the EBB bit in the event, so event checks work below */
- event &= ~(EVENT_EBB_MASK << EVENT_EBB_SHIFT);
-
if (pmc) {
+ u64 base_event;
+
if (pmc > 6)
return -1;
- mask |= CNST_PMC_MASK(pmc);
- value |= CNST_PMC_VAL(pmc);
+ /* Ignore Linux defined bits when checking event below */
+ base_event = event & ~(EVENT_EBB_MASK << EVENT_EBB_SHIFT);
- if (pmc >= 5 && event != 0x500fa && event != 0x600f4)
+ if (pmc >= 5 && base_event != 0x500fa && base_event != 0x600f4)
return -1;
+
+ mask |= CNST_PMC_MASK(pmc);
+ value |= CNST_PMC_VAL(pmc);
}
if (pmc <= 4) {
--
1.8.3.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox