LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 2/3] dts: mpc512x: adjust clock specs for FEC nodes
From: Sascha Hauer @ 2014-03-06 10:21 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mark Rutland, devicetree, Anatolij Gustschin, Mike Turquette,
	Pawel Moll, Ian Campbell, Rob Herring, Shawn Guo, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <20140305105209.GZ3327@book.gsilab.sittig.org>

On Wed, Mar 05, 2014 at 11:52:09AM +0100, Gerhard Sittig wrote:
> On Wed, Mar 05, 2014 at 09:48 +0800, Shawn Guo wrote:
> > 
> > On Mon, Mar 03, 2014 at 10:22:31AM +0100, Gerhard Sittig wrote:
> > > On Mon, Feb 24, 2014 at 11:25 +0100, Gerhard Sittig wrote:
> > > > 
> > > > a recent FEC binding document update that was motivated by i.MX
> > > > development revealed that ARM and PowerPC implementations in Linux
> > > > did not agree on the clock names to use for the FEC nodes
> > > > 
> > > > change clock names from "per" to "ipg" in the FEC nodes of the
> > > > mpc5121.dtsi include file such that the .dts specs comply with
> > > > the common FEC binding
> > > > 
> > > > this "incompatible" change does not break operation, because
> > > > - COMMON_CLK support for MPC5121/23/25 and adjusted .dts files
> > > >   were only introduced in Linux v3.14-rc1, no mainline release
> > > >   provided these specs before
> > > > - if this change won't make it for v3.14, the MPC512x CCF support
> > > >   provides full backwards compability, and keeps operating with
> > > >   device trees which lack clock specs or don't match in the names
> > > > 
> > > > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > > 
> > > ping
> > > 
> > > Are there opinions about making PowerPC users of FEC use the same
> > > clock names as ARM users do, to re-use (actually: keep sharing)
> > > the FEC binding?  The alternative would be to fragment the FEC
> > > binding into several bindings for ARM and PowerPC, which I feel
> > > would be undesirable, and is not necessary.
> > 
> > As I already said, Documentation/devicetree/bindings/net/fsl-fec.txt
> > was created specifically for i.MX FEC controller from day one.  And even
> > as of today, it doesn't serve PowerPC, because for example the property
> > 'phy-mode' documented as required one is not required by PowerPC FEC.
> > My opinion would be to patch fsl-fec.txt a little bit to make it clear
> > that it's a binding doc for i.MX FEC, and create the other one for
> > PowerPC FEC.  This is the way less confusing to people and easier for
> > binding maintenance.
> 
> Should we still try to have a common behaviour where possible?
> Such that even if there are two bindings, they don't diverge in
> "unnecessary" ways?

Maybe the long term goal should be to share the code. The MPC5200 FEC
and the i.MX FEC are very similar. Only the DMA engine is quite
different.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* [PATCH 2/2] KVM: PPC: Book3S HV: Fix register usage when loading/saving VRSAVE
From: Aneesh Kumar K.V @ 2014-03-06 10:36 UTC (permalink / raw)
  To: agraf, benh, paulus; +Cc: linuxppc-dev, kvm, kvm-ppc, Aneesh Kumar K.V
In-Reply-To: <1394102170-22126-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>

From: Paul Mackerras <paulus@samba.org>

Commit 595e4f7e697e ("KVM: PPC: Book3S HV: Use load/store_fp_state functions
in HV guest entry/exit") changed the register usage in kvmppc_save_fp() and
kvmppc_load_fp() but omitted changing the instructions that load and save VRSAVE.
The result is that the VRSAVE value was loaded from a constant address, and
saved to a location past the end of the vcpu struct, causing host kernel memory
corruption and various kinds of host kernel crashes.

This fixes the problem by using register r31, which contains the
vcpu pointer, instead of r3 and r4.

Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 557a47800ca1..6962d38c76f5 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -2132,7 +2132,7 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif
 	mfspr	r6,SPRN_VRSAVE
-	stw	r6,VCPU_VRSAVE(r3)
+	stw	r6,VCPU_VRSAVE(r31)
 	mtlr	r30
 	mtmsrd	r5
 	isync
@@ -2169,7 +2169,7 @@ BEGIN_FTR_SECTION
 	bl	.load_vr_state
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif
-	lwz	r7,VCPU_VRSAVE(r4)
+	lwz	r7,VCPU_VRSAVE(r31)
 	mtspr	SPRN_VRSAVE,r7
 	mtlr	r30
 	mr	r4,r31
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 1/2] Revert "KVM: PPC: Book3S HV: Add new state for transactional memory"
From: Aneesh Kumar K.V @ 2014-03-06 10:36 UTC (permalink / raw)
  To: agraf, benh, paulus; +Cc: linuxppc-dev, kvm, kvm-ppc, Aneesh Kumar K.V

From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>

This reverts commit 7b490411c37f7ab7965cbdfe5e3ec28eadb6db5b which cause
the below crash in the host.

Unable to handle kernel paging request for data at address 0xf00000001223f278
Faulting instruction address: 0xc000000000202a00
cpu 0x30: Vector: 300 (Data Access) at [c000001e4debb2d0]
    pc: c000000000202a00: .kfree+0x40/0x200
    lr: c000000000098338: .kvmppc_core_destroy_vm_hv+0x38/0x90
    sp: c000001e4debb550
   msr: 9000000000009032
   dar: f00000001223f278
 dsisr: 40000000
  current = 0xc000001e4de195c0
  paca    = 0xc00000000fefb000   softe: 0        irq_happened: 0x01
    pid   = 29379, comm = qemu-system-ppc
enter ? for help
[c000001e4debb5e0] c000000000098338 .kvmppc_core_destroy_vm_hv+0x38/0x90
[c000001e4debb670] c000000000087f80 .kvmppc_core_destroy_vm+0x30/0x70
[c000001e4debb6f0] c000000000084f28 .kvm_arch_destroy_vm+0xd8/0x120
[c000001e4debb780] c000000000080218 .kvm_put_kvm+0x198/0x2e0
[c000001e4debb820] c0000000000880d4 .kvm_spapr_tce_release+0xe4/0x110
[c000001e4debb8b0] c000000000218578 .__fput+0xb8/0x2a0
[c000001e4debb950] c0000000000d9af4 .task_work_run+0x114/0x150
[c000001e4debb9f0] c0000000000b31e8 .do_exit+0x328/0xbc0
[c000001e4debbae0] c0000000000b4cd4 .do_group_exit+0x54/0xf0
[c000001e4debbb70] c0000000000c8448 .get_signal_to_deliver+0x1e8/0x6f0
[c000001e4debbc70] c000000000017ee4 .do_signal+0x54/0x320
[c000001e4debbdb0] c0000000000182e8 .do_notify_resume+0x68/0x80
[c000001e4debbe30] c00000000000a7b0 .ret_from_except_lite+0x5c/0x60
--- Exception: c00 (System Call) at 00003fffb38a4744
SP (3ffd36ffe360) is in userspace
30:mon> zr

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/kvm_host.h     | 24 ++---------
 arch/powerpc/kernel/asm-offsets.c       | 19 ++-------
 arch/powerpc/kvm/book3s_hv.c            |  4 --
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 75 +--------------------------------
 4 files changed, 8 insertions(+), 114 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 1eaea2dea174..7726a3bc8ff0 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -475,6 +475,9 @@ struct kvm_vcpu_arch {
 	ulong ppr;
 	ulong pspb;
 	ulong fscr;
+	ulong tfhar;
+	ulong tfiar;
+	ulong texasr;
 	ulong ebbhr;
 	ulong ebbrr;
 	ulong bescr;
@@ -523,27 +526,6 @@ struct kvm_vcpu_arch {
 	u64 siar;
 	u64 sdar;
 	u64 sier;
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-	u64 tfhar;
-	u64 texasr;
-	u64 tfiar;
-
-	u32 cr_tm;
-	u64 lr_tm;
-	u64 ctr_tm;
-	u64 amr_tm;
-	u64 ppr_tm;
-	u64 dscr_tm;
-	u64 tar_tm;
-
-	ulong gpr_tm[32];
-
-	struct thread_fp_state fp_tm;
-
-	struct thread_vr_state vr_tm;
-	u32 vrsave_tm; /* also USPRG0 */
-
-#endif
 
 #ifdef CONFIG_KVM_EXIT_TIMING
 	struct mutex exit_timing_lock;
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index b5aacf72ae6f..936d445b961a 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -534,6 +534,9 @@ int main(void)
 	DEFINE(VCPU_PPR, offsetof(struct kvm_vcpu, arch.ppr));
 	DEFINE(VCPU_FSCR, offsetof(struct kvm_vcpu, arch.fscr));
 	DEFINE(VCPU_PSPB, offsetof(struct kvm_vcpu, arch.pspb));
+	DEFINE(VCPU_TFHAR, offsetof(struct kvm_vcpu, arch.tfhar));
+	DEFINE(VCPU_TFIAR, offsetof(struct kvm_vcpu, arch.tfiar));
+	DEFINE(VCPU_TEXASR, offsetof(struct kvm_vcpu, arch.texasr));
 	DEFINE(VCPU_EBBHR, offsetof(struct kvm_vcpu, arch.ebbhr));
 	DEFINE(VCPU_EBBRR, offsetof(struct kvm_vcpu, arch.ebbrr));
 	DEFINE(VCPU_BESCR, offsetof(struct kvm_vcpu, arch.bescr));
@@ -555,22 +558,6 @@ int main(void)
 	DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
 	DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv));
 	DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb));
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-	DEFINE(VCPU_TFHAR, offsetof(struct kvm_vcpu, arch.tfhar));
-	DEFINE(VCPU_TFIAR, offsetof(struct kvm_vcpu, arch.tfiar));
-	DEFINE(VCPU_TEXASR, offsetof(struct kvm_vcpu, arch.texasr));
-	DEFINE(VCPU_GPR_TM, offsetof(struct kvm_vcpu, arch.gpr_tm));
-	DEFINE(VCPU_FPRS_TM, offsetof(struct kvm_vcpu, arch.fp_tm.fpr));
-	DEFINE(VCPU_VRS_TM, offsetof(struct kvm_vcpu, arch.vr_tm.vr));
-	DEFINE(VCPU_VRSAVE_TM, offsetof(struct kvm_vcpu, arch.vrsave_tm));
-	DEFINE(VCPU_CR_TM, offsetof(struct kvm_vcpu, arch.cr_tm));
-	DEFINE(VCPU_LR_TM, offsetof(struct kvm_vcpu, arch.lr_tm));
-	DEFINE(VCPU_CTR_TM, offsetof(struct kvm_vcpu, arch.ctr_tm));
-	DEFINE(VCPU_AMR_TM, offsetof(struct kvm_vcpu, arch.amr_tm));
-	DEFINE(VCPU_PPR_TM, offsetof(struct kvm_vcpu, arch.ppr_tm));
-	DEFINE(VCPU_DSCR_TM, offsetof(struct kvm_vcpu, arch.dscr_tm));
-	DEFINE(VCPU_TAR_TM, offsetof(struct kvm_vcpu, arch.tar_tm));
-#endif
 
 #ifdef CONFIG_PPC_BOOK3S_64
 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 3b498d942a22..71f2e8e6e7b1 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -879,7 +879,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
 	case KVM_REG_PPC_IAMR:
 		*val = get_reg_val(id, vcpu->arch.iamr);
 		break;
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 	case KVM_REG_PPC_TFHAR:
 		*val = get_reg_val(id, vcpu->arch.tfhar);
 		break;
@@ -889,7 +888,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
 	case KVM_REG_PPC_TEXASR:
 		*val = get_reg_val(id, vcpu->arch.texasr);
 		break;
-#endif
 	case KVM_REG_PPC_FSCR:
 		*val = get_reg_val(id, vcpu->arch.fscr);
 		break;
@@ -1039,7 +1037,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
 	case KVM_REG_PPC_IAMR:
 		vcpu->arch.iamr = set_reg_val(id, *val);
 		break;
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 	case KVM_REG_PPC_TFHAR:
 		vcpu->arch.tfhar = set_reg_val(id, *val);
 		break;
@@ -1049,7 +1046,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
 	case KVM_REG_PPC_TEXASR:
 		vcpu->arch.texasr = set_reg_val(id, *val);
 		break;
-#endif
 	case KVM_REG_PPC_FSCR:
 		vcpu->arch.fscr = set_reg_val(id, *val);
 		break;
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index e66d4ec04d95..557a47800ca1 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -704,15 +704,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
 	ld	r6, VCPU_VTB(r4)
 	mtspr	SPRN_IC, r5
 	mtspr	SPRN_VTB, r6
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 	ld	r5, VCPU_TFHAR(r4)
 	ld	r6, VCPU_TFIAR(r4)
 	ld	r7, VCPU_TEXASR(r4)
+	ld	r8, VCPU_EBBHR(r4)
 	mtspr	SPRN_TFHAR, r5
 	mtspr	SPRN_TFIAR, r6
 	mtspr	SPRN_TEXASR, r7
-#endif
-	ld	r8, VCPU_EBBHR(r4)
 	mtspr	SPRN_EBBHR, r8
 	ld	r5, VCPU_EBBRR(r4)
 	ld	r6, VCPU_BESCR(r4)
@@ -1122,15 +1120,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
 	std	r5, VCPU_IC(r9)
 	std	r6, VCPU_VTB(r9)
 	std	r7, VCPU_TAR(r9)
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 	mfspr	r5, SPRN_TFHAR
 	mfspr	r6, SPRN_TFIAR
 	mfspr	r7, SPRN_TEXASR
+	mfspr	r8, SPRN_EBBHR
 	std	r5, VCPU_TFHAR(r9)
 	std	r6, VCPU_TFIAR(r9)
 	std	r7, VCPU_TEXASR(r9)
-#endif
-	mfspr	r8, SPRN_EBBHR
 	std	r8, VCPU_EBBHR(r9)
 	mfspr	r5, SPRN_EBBRR
 	mfspr	r6, SPRN_BESCR
@@ -1504,73 +1500,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 1:	addi	r8,r8,16
 	.endr
 
-	/* Save DEC */
-	mfspr	r5,SPRN_DEC
-	mftb	r6
-	extsw	r5,r5
-	add	r5,r5,r6
-	std	r5,VCPU_DEC_EXPIRES(r9)
-
-BEGIN_FTR_SECTION
-	b	8f
-END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
-	/* Turn on TM so we can access TFHAR/TFIAR/TEXASR */
-	mfmsr	r8
-	li	r0, 1
-	rldimi	r8, r0, MSR_TM_LG, 63-MSR_TM_LG
-	mtmsrd	r8
-
-	/* Save POWER8-specific registers */
-	mfspr	r5, SPRN_IAMR
-	mfspr	r6, SPRN_PSPB
-	mfspr	r7, SPRN_FSCR
-	std	r5, VCPU_IAMR(r9)
-	stw	r6, VCPU_PSPB(r9)
-	std	r7, VCPU_FSCR(r9)
-	mfspr	r5, SPRN_IC
-	mfspr	r6, SPRN_VTB
-	mfspr	r7, SPRN_TAR
-	std	r5, VCPU_IC(r9)
-	std	r6, VCPU_VTB(r9)
-	std	r7, VCPU_TAR(r9)
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-	mfspr	r5, SPRN_TFHAR
-	mfspr	r6, SPRN_TFIAR
-	mfspr	r7, SPRN_TEXASR
-	std	r5, VCPU_TFHAR(r9)
-	std	r6, VCPU_TFIAR(r9)
-	std	r7, VCPU_TEXASR(r9)
-#endif
-	mfspr	r8, SPRN_EBBHR
-	std	r8, VCPU_EBBHR(r9)
-	mfspr	r5, SPRN_EBBRR
-	mfspr	r6, SPRN_BESCR
-	mfspr	r7, SPRN_CSIGR
-	mfspr	r8, SPRN_TACR
-	std	r5, VCPU_EBBRR(r9)
-	std	r6, VCPU_BESCR(r9)
-	std	r7, VCPU_CSIGR(r9)
-	std	r8, VCPU_TACR(r9)
-	mfspr	r5, SPRN_TCSCR
-	mfspr	r6, SPRN_ACOP
-	mfspr	r7, SPRN_PID
-	mfspr	r8, SPRN_WORT
-	std	r5, VCPU_TCSCR(r9)
-	std	r6, VCPU_ACOP(r9)
-	stw	r7, VCPU_GUEST_PID(r9)
-	std	r8, VCPU_WORT(r9)
-8:
-
-	/* Save and reset AMR and UAMOR before turning on the MMU */
-BEGIN_FTR_SECTION
-	mfspr	r5,SPRN_AMR
-	mfspr	r6,SPRN_UAMOR
-	std	r5,VCPU_AMR(r9)
-	std	r6,VCPU_UAMOR(r9)
-	li	r6,0
-	mtspr	SPRN_AMR,r6
-END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
-
 	/* Unset guest mode */
 	li	r0, KVM_GUEST_MODE_NONE
 	stb	r0, HSTATE_IN_GUEST(r13)
-- 
1.8.3.2

^ permalink raw reply related

* RE: [PATCH 3/3] perf: Use 64-bit value when comparing sample_regs
From: David Laight @ 2014-03-06  9:44 UTC (permalink / raw)
  To: 'Sukadev Bhattiprolu', Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, linux-kernel@vger.kernel.org, Stephane Eranian,
	linuxppc-dev@ozlabs.org, Paul Mackerras, Jiri Olsa
In-Reply-To: <1394080919-17957-4-git-send-email-sukadev@linux.vnet.ibm.com>

RnJvbTogU3VrYWRldiBCaGF0dGlwcm9sdQ0KPiBXaGVuIGNoZWNraW5nIHdoZXRoZXIgYSBiaXQg
cmVwcmVzZW50aW5nIGEgcmVnaXN0ZXIgaXMgc2V0IGluDQo+IHNhbXBsZV9yZWdzLCBhIDY0LWJp
dCBtYXNrLCB1c2UgNjQtYml0IHZhbHVlICgxTEwpLg0KPiANCj4gU2lnbmVkLW9mZi1ieTogU3Vr
YWRldiBCaGF0dGlwcm9sdSA8c3VrYWRldkBsaW51eC52bmV0LmlibS5jb20+DQo+IC0tLQ0KPiAg
dG9vbHMvcGVyZi91dGlsL3Vud2luZC5jIHwgICAgNCArKy0tDQo+ICAxIGZpbGUgY2hhbmdlZCwg
MiBpbnNlcnRpb25zKCspLCAyIGRlbGV0aW9ucygtKQ0KPiANCj4gZGlmZiAtLWdpdCBhL3Rvb2xz
L3BlcmYvdXRpbC91bndpbmQuYyBiL3Rvb2xzL3BlcmYvdXRpbC91bndpbmQuYw0KPiBpbmRleCA3
NDJmMjNiLi4yYjg4OGM2IDEwMDY0NA0KPiAtLS0gYS90b29scy9wZXJmL3V0aWwvdW53aW5kLmMN
Cj4gKysrIGIvdG9vbHMvcGVyZi91dGlsL3Vud2luZC5jDQo+IEBAIC0zOTYsMTEgKzM5NiwxMSBA
QCBzdGF0aWMgaW50IHJlZ192YWx1ZSh1bndfd29yZF90ICp2YWxwLCBzdHJ1Y3QgcmVnc19kdW1w
ICpyZWdzLCBpbnQgaWQsDQo+ICB7DQo+ICAJaW50IGksIGlkeCA9IDA7DQo+IA0KPiAtCWlmICgh
KHNhbXBsZV9yZWdzICYgKDEgPDwgaWQpKSkNCj4gKwlpZiAoIShzYW1wbGVfcmVncyAmICgxTEwg
PDwgaWQpKSkNCj4gIAkJcmV0dXJuIC1FSU5WQUw7DQo+IA0KPiAgCWZvciAoaSA9IDA7IGkgPCBp
ZDsgaSsrKSB7DQo+IC0JCWlmIChzYW1wbGVfcmVncyAmICgxIDw8IGkpKQ0KPiArCQlpZiAoc2Ft
cGxlX3JlZ3MgJiAoMUxMIDw8IGkpKQ0KPiAgCQkJaWR4Kys7DQo+ICAJfQ0KDQpUaGVyZSBhcmUg
bXVjaCBmYXN0ZXIgd2F5cyB0byBjb3VudCB0aGUgbnVtYmVyIG9mIHNldCBiaXRzLCBlc3BlY2lh
bGx5DQppZiB5b3UgbWlnaHQgbmVlZCB0byBjaGVjayBhIHNpZ25pZmljYW50IG51bWJlciBvZiBi
aXRzLg0KVGhlcmUgbWlnaHQgZXZlbiBiZSBhIGZ1bmN0aW9uIGRlZmluZWQgc29tZXdoZXJlIHRv
IGRvIGl0Lg0KQmFzaWNhbGx5IHlvdSBqdXN0IGFkZCB1cCB0aGUgYml0cywgZm9yIDE2IGJpdCBp
dCB3b3VsZCBiZToNCgl2YWwgPSAodmFsICYgMHg1NTU1KSArICh2YWwgPj4gMSkgJiAweDU1NTU7
DQoJdmFsID0gKHZhbCAmIDB4MzMzMykgKyAodmFsID4+IDIpICYgMHgzMzMzOw0KCXZhbCA9ICh2
YWwgJiAweDBmMGYpICsgKHZhbCA+PiA0KSAmIDB4MGYwZjsNCgl2YWwgPSAodmFsICYgMHgwMGZm
KSArICh2YWwgPj4gOCkgJiAweDAwZmY7DQpBcyB0aGUgc2l6ZSBvZiB0aGUgd29yayBpbmNyZWFz
ZXMgdGhlIGltcHJvdmVtZW50IGlzIG1vcmUgc2lnbmlmaWNhbnQuDQooU29tZSBvZiB0aGUgbGF0
ZXIgbWFza2luZyBjYW4gcHJvYmFibHkgYmUgcHJvdmVuIHVubmVjZXNzYXJ5LikNCg0KCURhdmlk
DQoNCg==

^ permalink raw reply

* [PATCH 5/5] powerpc/perf: Enable BHRB access for EBB events
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>

The previous commit added constraint and register handling to allow
processes using EBB (Event Based Branches) to request access to the BHRB
(Branch History Rolling Buffer).

With that in place we can allow processes using EBB to access the BHRB.
This is achieved by setting BHRBA in MMCR0 when we enable EBB access. We
must also clear BHRBA when we are disabling.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/include/asm/reg.h  |  1 +
 arch/powerpc/perf/core-book3s.c | 10 ++++++----
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 90c06ec..d48ce94 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -664,6 +664,7 @@
 #define   MMCR0_PMXE	0x04000000UL /* performance monitor exception enable */
 #define   MMCR0_FCECE	0x02000000UL /* freeze ctrs on enabled cond or event */
 #define   MMCR0_TBEE	0x00400000UL /* time base exception enable */
+#define   MMCR0_BHRBA	0x00200000UL /* BHRB Access allowed in userspace */
 #define   MMCR0_EBE	0x00100000UL /* Event based branch enable */
 #define   MMCR0_PMCC	0x000c0000UL /* PMC control */
 #define   MMCR0_PMCC_U6	0x00080000UL /* PMC1-6 are R/W by user (PR) */
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 4b2ba0c..a75bb69 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -78,6 +78,7 @@ static unsigned int freeze_events_kernel = MMCR0_FCS;
 #define MMCR0_FC56		0
 #define MMCR0_PMAO		0
 #define MMCR0_EBE		0
+#define MMCR0_BHRBA		0
 #define MMCR0_PMCC		0
 #define MMCR0_PMCC_U6		0
 
@@ -545,8 +546,8 @@ static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0)
 	if (!ebb)
 		goto out;
 
-	/* Enable EBB and read/write to all 6 PMCs for userspace */
-	mmcr0 |= MMCR0_EBE | MMCR0_PMCC_U6;
+	/* Enable EBB and read/write to all 6 PMCs and BHRB for userspace */
+	mmcr0 |= MMCR0_EBE | MMCR0_BHRBA | MMCR0_PMCC_U6;
 
 	/* Add any bits from the user reg, FC or PMAO */
 	mmcr0 |= current->thread.mmcr0;
@@ -976,11 +977,12 @@ static void power_pmu_disable(struct pmu *pmu)
 		}
 
 		/*
-		 * Set the 'freeze counters' bit, clear EBE/PMCC/PMAO/FC56.
+		 * Set the 'freeze counters' bit, clear EBE/BHRBA/PMCC/PMAO/FC56
 		 */
 		val  = mmcr0 = mfspr(SPRN_MMCR0);
 		val |= MMCR0_FC;
-		val &= ~(MMCR0_EBE | MMCR0_PMCC | MMCR0_PMAO | MMCR0_FC56);
+		val &= ~(MMCR0_EBE | MMCR0_BHRBA | MMCR0_PMCC | MMCR0_PMAO |
+			 MMCR0_FC56);
 
 		/*
 		 * The barrier is to make sure the mtspr has been
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 4/5] powerpc/perf: Add BHRB constraint and IFM MMCRA handling for EBB
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 want a way for users of EBB (Event Based Branches) to also access the
BHRB (Branch History Rolling Buffer). EBB does not interoperate with our
existing BHRB support, which is wired into the generic Linux branch
stack sampling support.

To support EBB & BHRB we add three new bits to the event code. The first
bit indicates that the event wants access to the BHRB, and the other two
bits indicate the desired IFM (Instruction Filtering Mode).

We allow multiple events to request access to the BHRB, but they must
agree on the IFM value. Events which are not interested in the BHRB can
also interoperate with events which do.

Finally we program the desired IFM value into MMCRA. Although we do this
for every event, we know that the value will be identical for all events
that request BHRB access.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/perf/power8-pmu.c | 53 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 04c1c77..babc3c0 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -62,9 +62,11 @@
  *
  *        60        56        52        48        44        40        36        32
  * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
- *   |                                 [      thresh_cmp     ]   [  thresh_ctl   ]
- *   |                                                                   |
- *   *- EBB (Linux)                      thresh start/stop OR FAB match -*
+ *   | | [ ]                           [      thresh_cmp     ]   [  thresh_ctl   ]
+ *   | |  |                                                              |
+ *   | |  *- IFM (Linux)                 thresh start/stop OR FAB match -*
+ *   | *- BHRB (Linux)
+ *   *- EBB (Linux)
  *
  *        28        24        20        16        12         8         4         0
  * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
@@ -114,10 +116,18 @@
  *	MMCRA[57:59] = sample[0:2]	(RAND_SAMP_ELIG)
  *	MMCRA[61:62] = sample[3:4]	(RAND_SAMP_MODE)
  *
+ * if EBB and BHRB:
+ *	MMCRA[32:33] = IFM
+ *
  */
 
 #define EVENT_EBB_MASK		1ull
 #define EVENT_EBB_SHIFT		PERF_EVENT_CONFIG_EBB_SHIFT
+#define EVENT_BHRB_MASK		1ull
+#define EVENT_BHRB_SHIFT	62
+#define EVENT_WANTS_BHRB	(EVENT_BHRB_MASK << EVENT_BHRB_SHIFT)
+#define EVENT_IFM_MASK		3ull
+#define EVENT_IFM_SHIFT		60
 #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) */
@@ -142,6 +152,12 @@
 #define EVENT_IS_MARKED		(EVENT_MARKED_MASK << EVENT_MARKED_SHIFT)
 #define EVENT_PSEL_MASK		0xff	/* PMCxSEL value */
 
+/* Bits defined by Linux */
+#define EVENT_LINUX_MASK	\
+	((EVENT_EBB_MASK  << EVENT_EBB_SHIFT)			|	\
+	 (EVENT_BHRB_MASK << EVENT_BHRB_SHIFT)			|	\
+	 (EVENT_IFM_MASK  << EVENT_IFM_SHIFT))
+
 #define EVENT_VALID_MASK	\
 	((EVENT_THRESH_MASK    << EVENT_THRESH_SHIFT)		|	\
 	 (EVENT_SAMPLE_MASK    << EVENT_SAMPLE_SHIFT)		|	\
@@ -150,7 +166,7 @@
 	 (EVENT_UNIT_MASK      << EVENT_UNIT_SHIFT)		|	\
 	 (EVENT_COMBINE_MASK   << EVENT_COMBINE_SHIFT)		|	\
 	 (EVENT_MARKED_MASK    << EVENT_MARKED_SHIFT)		|	\
-	 (EVENT_EBB_MASK       << EVENT_EBB_SHIFT)		|	\
+	  EVENT_LINUX_MASK					|	\
 	  EVENT_PSEL_MASK)
 
 /* MMCRA IFM bits - POWER8 */
@@ -174,10 +190,11 @@
  *
  *        28        24        20        16        12         8         4         0
  * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
- *                   |   [ ]   [  sample ]   [     ]   [6] [5]   [4] [3]   [2] [1]
- *              EBB -*    |                     |
- *                        |                     |      Count of events for each PMC.
- *      L1 I/D qualifier -*                     |        p1, p2, p3, p4, p5, p6.
+ *               [ ] |   [ ]   [  sample ]   [     ]   [6] [5]   [4] [3]   [2] [1]
+ *                |  |    |                     |
+ *      BHRB IFM -*  |    |                     |      Count of events for each PMC.
+ *              EBB -*    |                     |        p1, p2, p3, p4, p5, p6.
+ *      L1 I/D qualifier -*                     |
  *                     nc - number of counters -*
  *
  * The PMC fields P1..P6, and NC, are adder fields. As we accumulate constraints
@@ -196,6 +213,9 @@
 #define CNST_EBB_VAL(v)		(((v) & EVENT_EBB_MASK) << 24)
 #define CNST_EBB_MASK		CNST_EBB_VAL(EVENT_EBB_MASK)
 
+#define CNST_IFM_VAL(v)		(((v) & EVENT_IFM_MASK) << 25)
+#define CNST_IFM_MASK		CNST_IFM_VAL(EVENT_IFM_MASK)
+
 #define CNST_L1_QUAL_VAL(v)	(((v) & 3) << 22)
 #define CNST_L1_QUAL_MASK	CNST_L1_QUAL_VAL(3)
 
@@ -242,6 +262,7 @@
 #define MMCRA_THR_SEL_SHIFT		16
 #define MMCRA_THR_CMP_SHIFT		32
 #define MMCRA_SDAR_MODE_TLB		(1ull << 42)
+#define MMCRA_IFM_SHIFT			30
 
 
 static inline bool event_is_fab_match(u64 event)
@@ -275,7 +296,7 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
 			return -1;
 
 		/* Ignore Linux defined bits when checking event below */
-		base_event = event & ~(EVENT_EBB_MASK << EVENT_EBB_SHIFT);
+		base_event = event & ~EVENT_LINUX_MASK;
 
 		if (pmc >= 5 && base_event != 0x500fa && base_event != 0x600f4)
 			return -1;
@@ -345,6 +366,15 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
 		/* EBB events must specify the PMC */
 		return -1;
 
+	if (event & EVENT_WANTS_BHRB) {
+		if (!ebb)
+			/* Only EBB events can request BHRB */
+			return -1;
+
+		mask  |= CNST_IFM_MASK;
+		value |= CNST_IFM_VAL(event >> EVENT_IFM_SHIFT);
+	}
+
 	/*
 	 * All events must agree on EBB, either all request it or none.
 	 * EBB events are pinned & exclusive, so this should never actually
@@ -434,6 +464,11 @@ static int power8_compute_mmcr(u64 event[], int n_ev,
 			mmcra |= val << MMCRA_THR_CMP_SHIFT;
 		}
 
+		if (event[i] & EVENT_WANTS_BHRB) {
+			val = (event[i] >> EVENT_IFM_SHIFT) & EVENT_IFM_MASK;
+			mmcra |= val << MMCRA_IFM_SHIFT;
+		}
+
 		hwc[i] = pmc - 1;
 	}
 
-- 
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

* [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 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

* 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] 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

* [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 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

* [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

* [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 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

* [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 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 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 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 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

* 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

* 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

* [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

* [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


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox