LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] KVM: PPC: 64-bit Book3E arch support
From: Mihai Caraman @ 2012-10-11 16:13 UTC (permalink / raw)
  To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm

This patchset adds arch support to KVM for 64-bit Book3E PowerPC procesosrs
with Embedded.Hypervisor category. The support is limited to the bolted TLB miss
exception handlers version and was validated on Freescale's e5500 cores
using P5020DS boards.

This patchset is based on Alex G. kvm-ppc-next branch with the following
core prerequisites:

The changes since commit 8b7b80b9ebb46dd88fbb94e918297295cf312b59:

    powerpc: Uprobes port to powerpc

up to commit 8b64a9dfb091f1eca8b7e58da82f1e7d1d5fe0ad:

    powerpc/booke64: Use SPRG0/3 scratch for bolted TLB miss & crit int


and the changes since commit d0832a75075b1119635e0f48549e378040cf5e67:

    powerpc/85xx: add HOTPLUG_CPU support

up to commit 39be5b4a7f232870aad0b3c130791eacd0d34347:

    powerpc/booke: Add CPU_FTR_EMB_HV check for e5500.


available in the git repository

    git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git



Mihai Caraman (12):
  KVM: PPC: e500: Silence bogus GCC warning in tlb code
  KVM: PPC: booke: Fix get_tb() compile error on 64-bit
  KVM: PPC: bookehv: Remove GET_VCPU macro from exception handler
  KVM: PPC64: bookehv: Add support for interrupt handling
  KVM: PPC: Add emulation helper for getting instruction ea
  KVM: PPC: Mask ea's high 32-bits in 32/64 instr emulation
  KVM: PPC: e500: Mask MAS2 EPN high 32-bits in 32/64 tlbwe emulation
  KVM: PPC: booke: Extend MAS2 EPN mask for 64-bit
  KVM: PPC: bookehv: Add guest computation mode for irq delivery
  KVM: PPC: bookehv: Add EPCR support in mtspr/mfspr emulation
  KVM: PPC: booke: Add EPCR support in sregs
  KVM: PPC: booke: Get/set guest EPCR register using ONE_REG interface

 Documentation/virtual/kvm/api.txt           |    1 +
 arch/powerpc/include/asm/kvm.h              |    2 +
 arch/powerpc/include/asm/kvm_booke_hv_asm.h |   25 +++++
 arch/powerpc/include/asm/kvm_ppc.h          |   21 ++++
 arch/powerpc/include/asm/mmu-book3e.h       |    2 +-
 arch/powerpc/kvm/booke.c                    |   43 ++++++++-
 arch/powerpc/kvm/booke.h                    |    1 +
 arch/powerpc/kvm/booke_emulate.c            |   12 ++-
 arch/powerpc/kvm/bookehv_interrupts.S       |  145 ++++++++++++++++++++++++---
 arch/powerpc/kvm/e500.h                     |    8 +-
 arch/powerpc/kvm/e500_emulate.c             |   15 ++-
 arch/powerpc/kvm/e500_tlb.c                 |   38 +++----
 12 files changed, 265 insertions(+), 48 deletions(-)

-- 
1.7.4.1

^ permalink raw reply

* [PATCH 07/12] KVM: PPC: e500: Mask MAS2 EPN high 32-bits in 32/64 tlbwe emulation
From: Mihai Caraman @ 2012-10-11 16:13 UTC (permalink / raw)
  To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1349972009-23027-1-git-send-email-mihai.caraman@freescale.com>

Mask high 32 bits of MAS2's effective page number in tlbwe emulation for guests
running in 32-bit mode.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v1: patch splited.

 arch/powerpc/kvm/e500_tlb.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index b5a188a..6c0997e 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -871,6 +871,8 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
 
 	gtlbe->mas1 = vcpu->arch.shared->mas1;
 	gtlbe->mas2 = vcpu->arch.shared->mas2;
+	if (!(vcpu->arch.shared->msr & MSR_CM))
+		gtlbe->mas2 &= 0xffffffffUL;
 	gtlbe->mas7_3 = vcpu->arch.shared->mas7_3;
 
 	trace_kvm_booke206_gtlb_write(vcpu->arch.shared->mas0, gtlbe->mas1,
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 06/12] KVM: PPC: Mask ea's high 32-bits in 32/64 instr emulation
From: Mihai Caraman @ 2012-10-11 16:13 UTC (permalink / raw)
  To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1349972009-23027-1-git-send-email-mihai.caraman@freescale.com>

Mask high 32 bits of effective address in emulation layer for guests running
in 32-bit mode.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v1: added BOOK3S implementation.

 arch/powerpc/include/asm/kvm_ppc.h |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index a08e756..4a3fdbd 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -296,11 +296,21 @@ static inline void kvmppc_lazy_ee_enable(void)
 static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
 {
 	ulong ea;
+	ulong msr_64bit = 0;
 
 	ea = kvmppc_get_gpr(vcpu, rb);
 	if (ra)
 		ea += kvmppc_get_gpr(vcpu, ra);
 
+#if defined(CONFIG_PPC_BOOK3E_64)
+	msr_64bit = MSR_CM;
+#elif defined(CONFIG_PPC_BOOK3S_64)
+	msr_64bit = MSR_SF;
+#endif
+
+	if (!(vcpu->arch.shared->msr & msr_64bit))
+	    ea = (uint32_t)ea;
+
 	return ea;
 }
 
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 03/12] KVM: PPC: bookehv: Remove GET_VCPU macro from exception handler
From: Mihai Caraman @ 2012-10-11 16:13 UTC (permalink / raw)
  To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1349972009-23027-1-git-send-email-mihai.caraman@freescale.com>

GET_VCPU define will not be implemented for 64-bit for performance reasons
so get rid of it also on 32-bit.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
 arch/powerpc/kvm/bookehv_interrupts.S |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
index 099fe82..fa6d552 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -32,9 +32,6 @@
 
 #include "../kernel/head_booke.h" /* for THREAD_NORMSAVE() */
 
-#define GET_VCPU(vcpu, thread)	\
-	PPC_LL	vcpu, THREAD_KVM_VCPU(thread)
-
 #define LONGBYTES		(BITS_PER_LONG / 8)
 
 #define VCPU_GUEST_SPRG(n)	(VCPU_GUEST_SPRGS + (n * LONGBYTES))
@@ -206,7 +203,7 @@
  */
 .macro kvm_handler intno srr0, srr1, flags
 _GLOBAL(kvmppc_handler_\intno\()_\srr1)
-	GET_VCPU(r11, r10)
+	PPC_LL	r11, THREAD_KVM_VCPU(r10)
 	PPC_STL r3, VCPU_GPR(R3)(r11)
 	mfspr	r3, SPRN_SPRG_RSCRATCH0
 	PPC_STL	r4, VCPU_GPR(R4)(r11)
@@ -233,7 +230,7 @@ _GLOBAL(kvmppc_handler_\intno\()_\srr1)
 .macro kvm_lvl_handler intno scratch srr0, srr1, flags
 _GLOBAL(kvmppc_handler_\intno\()_\srr1)
 	mfspr	r10, SPRN_SPRG_THREAD
-	GET_VCPU(r11, r10)
+	PPC_LL	r11, THREAD_KVM_VCPU(r10)
 	PPC_STL r3, VCPU_GPR(R3)(r11)
 	mfspr	r3, \scratch
 	PPC_STL	r4, VCPU_GPR(R4)(r11)
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 05/12] KVM: PPC: e500: Add emulation helper for getting instruction ea
From: Mihai Caraman @ 2012-10-11 16:13 UTC (permalink / raw)
  To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1349972009-23027-1-git-send-email-mihai.caraman@freescale.com>

Add emulation helper for getting instruction ea and refactor tlb instruction
emulation to use it.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v1: use _t_ype instead of _t_arget _r_egister in tlbilx emulation.

 arch/powerpc/include/asm/kvm_ppc.h |   11 +++++++++++
 arch/powerpc/kvm/e500.h            |    6 +++---
 arch/powerpc/kvm/e500_emulate.c    |   15 ++++++++++-----
 arch/powerpc/kvm/e500_tlb.c        |   33 +++++++++++----------------------
 4 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 609cca3..a08e756 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -293,4 +293,15 @@ static inline void kvmppc_lazy_ee_enable(void)
 #endif
 }
 
+static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
+{
+	ulong ea;
+
+	ea = kvmppc_get_gpr(vcpu, rb);
+	if (ra)
+		ea += kvmppc_get_gpr(vcpu, ra);
+
+	return ea;
+}
+
 #endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index d162286..32e98a7 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -129,9 +129,9 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500,
 				ulong value);
 int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu);
 int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu);
-int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb);
-int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb);
-int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb);
+int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea);
+int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea);
+int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea);
 int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500);
 void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500);
 
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index e04b0ef..3bf2486 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -88,7 +88,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	int emulated = EMULATE_DONE;
 	int ra = get_ra(inst);
 	int rb = get_rb(inst);
-	int rt = get_rt(inst);
+	gva_t ea;
 
 	switch (get_op(inst)) {
 	case 31:
@@ -113,15 +113,20 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
 			break;
 
 		case XOP_TLBSX:
-			emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
+			ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+			emulated = kvmppc_e500_emul_tlbsx(vcpu, ea);
 			break;
 
-		case XOP_TLBILX:
-			emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ra, rb);
+		case XOP_TLBILX: {
+			int t = (inst >> 21) & 0x3;
+			ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+			emulated = kvmppc_e500_emul_tlbilx(vcpu, t, ea);
 			break;
+		}
 
 		case XOP_TLBIVAX:
-			emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb);
+			ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+			emulated = kvmppc_e500_emul_tlbivax(vcpu, ea);
 			break;
 
 		default:
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index 23b3de6..b5a188a 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -689,14 +689,11 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value)
 	return EMULATE_DONE;
 }
 
-int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
+int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
 	unsigned int ia;
 	int esel, tlbsel;
-	gva_t ea;
-
-	ea = ((ra) ? kvmppc_get_gpr(vcpu, ra) : 0) + kvmppc_get_gpr(vcpu, rb);
 
 	ia = (ea >> 2) & 0x1;
 
@@ -723,7 +720,7 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
 }
 
 static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
-		       int pid, int rt)
+		       int pid, int type)
 {
 	struct kvm_book3e_206_tlb_entry *tlbe;
 	int tid, esel;
@@ -732,7 +729,7 @@ static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
 	for (esel = 0; esel < vcpu_e500->gtlb_params[tlbsel].entries; esel++) {
 		tlbe = get_entry(vcpu_e500, tlbsel, esel);
 		tid = get_tlb_tid(tlbe);
-		if (rt == 0 || tid == pid) {
+		if (type == 0 || tid == pid) {
 			inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
 			kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
 		}
@@ -740,14 +737,9 @@ static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
 }
 
 static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
-		       int ra, int rb)
+		       gva_t ea)
 {
 	int tlbsel, esel;
-	gva_t ea;
-
-	ea = kvmppc_get_gpr(&vcpu_e500->vcpu, rb);
-	if (ra)
-		ea += kvmppc_get_gpr(&vcpu_e500->vcpu, ra);
 
 	for (tlbsel = 0; tlbsel < 2; tlbsel++) {
 		esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, -1);
@@ -759,16 +751,16 @@ static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
 	}
 }
 
-int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb)
+int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
 	int pid = get_cur_spid(vcpu);
 
-	if (rt == 0 || rt == 1) {
-		tlbilx_all(vcpu_e500, 0, pid, rt);
-		tlbilx_all(vcpu_e500, 1, pid, rt);
-	} else if (rt == 3) {
-		tlbilx_one(vcpu_e500, pid, ra, rb);
+	if (type == 0 || type == 1) {
+		tlbilx_all(vcpu_e500, 0, pid, type);
+		tlbilx_all(vcpu_e500, 1, pid, type);
+	} else if (type == 3) {
+		tlbilx_one(vcpu_e500, pid, ea);
 	}
 
 	return EMULATE_DONE;
@@ -793,16 +785,13 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
 	return EMULATE_DONE;
 }
 
-int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
+int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
 	int as = !!get_cur_sas(vcpu);
 	unsigned int pid = get_cur_spid(vcpu);
 	int esel, tlbsel;
 	struct kvm_book3e_206_tlb_entry *gtlbe = NULL;
-	gva_t ea;
-
-	ea = kvmppc_get_gpr(vcpu, rb);
 
 	for (tlbsel = 0; tlbsel < 2; tlbsel++) {
 		esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 04/12] KVM: PPC64: bookehv: Add support for interrupt handling
From: Mihai Caraman @ 2012-10-11 16:13 UTC (permalink / raw)
  To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1349972009-23027-1-git-send-email-mihai.caraman@freescale.com>

Add interrupt handling support for 64-bit bookehv hosts. Unify 32 and 64 bit
implementations using a common stack layout and a common execution flow starting
from kvm_handler_common macro. Update documentation for 64-bit input register
values. This patch only address the bolted TLB miss exception handlers version.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v1: updated CRIT and TLB exception handling following core side changes.

 arch/powerpc/include/asm/kvm_booke_hv_asm.h |   25 +++++
 arch/powerpc/kvm/bookehv_interrupts.S       |  138 +++++++++++++++++++++++++--
 2 files changed, 155 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_booke_hv_asm.h b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
index a37a12a..7ad5af7 100644
--- a/arch/powerpc/include/asm/kvm_booke_hv_asm.h
+++ b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
@@ -17,6 +17,7 @@
  * there are no exceptions for which we fall through directly to
  * the normal host handler.
  *
+ * 32-bit host
  * Expected inputs (normal exceptions):
  *   SCRATCH0 = saved r10
  *   r10 = thread struct
@@ -33,6 +34,30 @@
  *   *(r8 + GPR9) = saved r9
  *   *(r8 + GPR10) = saved r10 (r10 not yet clobbered)
  *   *(r8 + GPR11) = saved r11
+ *
+ * 64-bit host
+ * Expected inputs (GEN/GDBELL/DBG/MC exception types):
+ *  r10 = saved CR 
+ *  r13 = PACA_POINTER
+ *  *(r13 + PACA_EX##type + EX_R10) = saved r10
+ *  *(r13 + PACA_EX##type + EX_R11) = saved r11
+ *  SPRN_SPRG_##type##_SCRATCH = saved r13 
+ *
+  * Expected inputs (CRIT exception type):
+ *  r10 = saved CR
+ *  r13 = PACA_POINTER
+ *  *(r13 + PACA_EX##type + EX_R10) = saved r10
+ *  *(r13 + PACA_EX##type + EX_R11) = saved r11
+ *  *(r13 + PACA_EX##type + EX_R13) = saved r13
+ *
+ * Expected inputs (TLB exception type):
+ *  r10 = saved CR
+ *  r13 = PACA_POINTER
+ *  *(r13 + PACA_EX##type + EX_TLB_R10) = saved r10
+ *  *(r13 + PACA_EX##type + EX_TLB_R11) = saved r11
+ *  SPRN_SPRG_GEN_SCRATCH = saved r13
+ *
+ * Only the bolted version of TLB miss exception handlers is supported now.
  */
 .macro DO_KVM intno srr1
 #ifdef CONFIG_KVM_BOOKE_HV
diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
index fa6d552..e8ed7d6 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -16,6 +16,7 @@
  *
  * Author: Varun Sethi <varun.sethi@freescale.com>
  * Author: Scott Wood <scotwood@freescale.com>
+ * Author: Mihai Caraman <mihai.caraman@freescale.com>
  *
  * This file is derived from arch/powerpc/kvm/booke_interrupts.S
  */
@@ -30,28 +31,33 @@
 #include <asm/bitsperlong.h>
 #include <asm/thread_info.h>
 
+#ifdef CONFIG_64BIT
+#include <asm/exception-64e.h>
+#else
 #include "../kernel/head_booke.h" /* for THREAD_NORMSAVE() */
+#endif
 
 #define LONGBYTES		(BITS_PER_LONG / 8)
 
 #define VCPU_GUEST_SPRG(n)	(VCPU_GUEST_SPRGS + (n * LONGBYTES))
 
 /* The host stack layout: */
-#define HOST_R1         (0 * LONGBYTES) /* Implied by stwu. */
-#define HOST_CALLEE_LR  (1 * LONGBYTES)
-#define HOST_RUN        (2 * LONGBYTES) /* struct kvm_run */
+#define HOST_R1         0 /* Implied by stwu. */
+#define HOST_CALLEE_LR  PPC_LR_STKOFF
+#define HOST_RUN        (HOST_CALLEE_LR + LONGBYTES)
 /*
  * r2 is special: it holds 'current', and it made nonvolatile in the
  * kernel with the -ffixed-r2 gcc option.
  */
-#define HOST_R2         (3 * LONGBYTES)
-#define HOST_CR         (4 * LONGBYTES)
-#define HOST_NV_GPRS    (5 * LONGBYTES)
+#define HOST_R2         (HOST_RUN + LONGBYTES)
+#define HOST_CR         (HOST_R2 + LONGBYTES)
+#define HOST_NV_GPRS    (HOST_CR + LONGBYTES)
 #define __HOST_NV_GPR(n)  (HOST_NV_GPRS + ((n - 14) * LONGBYTES))
 #define HOST_NV_GPR(n)  __HOST_NV_GPR(__REG_##n)
 #define HOST_MIN_STACK_SIZE (HOST_NV_GPR(R31) + LONGBYTES)
 #define HOST_STACK_SIZE ((HOST_MIN_STACK_SIZE + 15) & ~15) /* Align. */
-#define HOST_STACK_LR   (HOST_STACK_SIZE + LONGBYTES) /* In caller stack frame. */
+/* LR in caller stack frame. */
+#define HOST_STACK_LR	(HOST_STACK_SIZE + PPC_LR_STKOFF)
 
 #define NEED_EMU		0x00000001 /* emulation -- save nv regs */
 #define NEED_DEAR		0x00000002 /* save faulting DEAR */
@@ -198,6 +204,122 @@
 	b	kvmppc_resume_host
 .endm
 
+#ifdef CONFIG_64BIT
+/* Exception types */
+#define EX_GEN			1
+#define EX_GDBELL		2
+#define EX_DBG			3
+#define EX_MC			4
+#define EX_CRIT			5
+#define EX_TLB			6
+
+/*
+ * For input register values, see arch/powerpc/include/asm/kvm_booke_hv_asm.h
+ */
+.macro kvm_handler intno type scratch, paca_ex, ex_r10, ex_r11, srr0, srr1, flags
+ _GLOBAL(kvmppc_handler_\intno\()_\srr1)
+	mr	r11, r4
+	/*
+	 * Get vcpu from Paca: paca->__current.thread->kvm_vcpu
+	 */
+	PPC_LL	r4, PACACURRENT(r13)
+	PPC_LL	r4, (THREAD + THREAD_KVM_VCPU)(r4)
+	stw	r10, VCPU_CR(r4)
+	PPC_STL r11, VCPU_GPR(R4)(r4)
+	PPC_STL	r5, VCPU_GPR(R5)(r4)
+	.if \type == EX_CRIT
+	PPC_LL	r5, (\paca_ex + EX_R13)(r13)
+	.else
+	mfspr	r5, \scratch
+	.endif
+	PPC_STL	r6, VCPU_GPR(R6)(r4)
+	PPC_STL	r8, VCPU_GPR(R8)(r4)
+	PPC_STL	r9, VCPU_GPR(R9)(r4)
+	PPC_STL r5, VCPU_GPR(R13)(r4)
+	PPC_LL	r6, (\paca_ex + \ex_r10)(r13)
+	PPC_LL	r8, (\paca_ex + \ex_r11)(r13)
+	PPC_STL r3, VCPU_GPR(R3)(r4)
+	PPC_STL r7, VCPU_GPR(R7)(r4)
+	PPC_STL r12, VCPU_GPR(R12)(r4)
+	PPC_STL r6, VCPU_GPR(R10)(r4)
+	PPC_STL r8, VCPU_GPR(R11)(r4)
+	mfctr	r5
+	PPC_STL	r5, VCPU_CTR(r4)
+	mfspr	r5, \srr0
+	mfspr	r6, \srr1
+	kvm_handler_common \intno, \srr0, \flags
+.endm
+
+#define EX_PARAMS(type) \
+	EX_##type, \
+	SPRN_SPRG_##type##_SCRATCH, \
+	PACA_EX##type, \
+	EX_R10, \
+	EX_R11
+
+#define EX_PARAMS_TLB \
+	EX_TLB, \
+	SPRN_SPRG_GEN_SCRATCH, \
+	PACA_EXTLB, \
+	EX_TLB_R10, \
+	EX_TLB_R11
+
+kvm_handler BOOKE_INTERRUPT_CRITICAL, EX_PARAMS(CRIT), \
+	SPRN_CSRR0, SPRN_CSRR1, 0
+kvm_handler BOOKE_INTERRUPT_MACHINE_CHECK, EX_PARAMS(MC), \
+	SPRN_MCSRR0, SPRN_MCSRR1, 0
+kvm_handler BOOKE_INTERRUPT_DATA_STORAGE, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1,(NEED_EMU | NEED_DEAR | NEED_ESR)
+kvm_handler BOOKE_INTERRUPT_INST_STORAGE, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, NEED_ESR
+kvm_handler BOOKE_INTERRUPT_EXTERNAL, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_ALIGNMENT, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1,(NEED_DEAR | NEED_ESR)
+kvm_handler BOOKE_INTERRUPT_PROGRAM, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1,NEED_ESR
+kvm_handler BOOKE_INTERRUPT_FP_UNAVAIL, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_AP_UNAVAIL, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_DECREMENTER, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_FIT, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_WATCHDOG, EX_PARAMS(CRIT),\
+	SPRN_CSRR0, SPRN_CSRR1, 0
+/*
+ * Only bolted TLB miss exception handlers are supported for now
+ */
+kvm_handler BOOKE_INTERRUPT_DTLB_MISS, EX_PARAMS_TLB, \
+	SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
+kvm_handler BOOKE_INTERRUPT_ITLB_MISS, EX_PARAMS_TLB, \
+	SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_SPE_UNAVAIL, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_PERFORMANCE_MONITOR, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_DOORBELL, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_DOORBELL_CRITICAL, EX_PARAMS(CRIT), \
+	SPRN_CSRR0, SPRN_CSRR1, 0
+kvm_handler BOOKE_INTERRUPT_HV_PRIV, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, NEED_EMU
+kvm_handler BOOKE_INTERRUPT_HV_SYSCALL, EX_PARAMS(GEN), \
+	SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_GUEST_DBELL, EX_PARAMS(GDBELL), \
+	SPRN_GSRR0, SPRN_GSRR1, 0
+kvm_handler BOOKE_INTERRUPT_GUEST_DBELL_CRIT, EX_PARAMS(CRIT), \
+	SPRN_CSRR0, SPRN_CSRR1, 0
+kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(DBG), \
+	SPRN_DSRR0, SPRN_DSRR1, 0
+kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(CRIT), \
+	SPRN_CSRR0, SPRN_CSRR1, 0
+#else
 /*
  * For input register values, see arch/powerpc/include/asm/kvm_booke_hv_asm.h
  */
@@ -292,7 +414,7 @@ kvm_lvl_handler BOOKE_INTERRUPT_DEBUG, \
 	SPRN_SPRG_RSCRATCH_CRIT, SPRN_CSRR0, SPRN_CSRR1, 0
 kvm_lvl_handler BOOKE_INTERRUPT_DEBUG, \
 	SPRN_SPRG_RSCRATCH_DBG, SPRN_DSRR0, SPRN_DSRR1, 0
-
+#endif
 
 /* Registers:
  *  SPRG_SCRATCH0: guest r10
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 10/12] KVM: PPC: bookehv: Add EPCR support in mtspr/mfspr emulation
From: Mihai Caraman @ 2012-10-11 16:13 UTC (permalink / raw)
  To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1349972009-23027-1-git-send-email-mihai.caraman@freescale.com>

Add EPCR support in booke mtspr/mfspr emulation. EPCR register is defined only
for 64-bit and HV categories, we will expose it at this point only to 64-bit
virtual processors running on 64-bit HV hosts.
Define a reusable setter function for vcpu's EPCR.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v1: extended guard defines with CONFIG_KVM_BOOKE_HV required by arch's epcr and
shadow_epcr fields.

 arch/powerpc/kvm/booke.c         |   10 ++++++++++
 arch/powerpc/kvm/booke.h         |    1 +
 arch/powerpc/kvm/booke_emulate.c |   12 +++++++++++-
 3 files changed, 22 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 86f0d0d..e6159f5 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -1473,6 +1473,16 @@ void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
 {
 }
 
+void kvmppc_set_epcr(struct kvm_vcpu *vcpu, u32 new_epcr)
+{
+#if defined(CONFIG_64BIT) && defined(CONFIG_KVM_BOOKE_HV)
+	vcpu->arch.epcr = new_epcr;
+	vcpu->arch.shadow_epcr &= ~SPRN_EPCR_GICM;
+	if (vcpu->arch.epcr  & SPRN_EPCR_ICM)
+		vcpu->arch.shadow_epcr |= SPRN_EPCR_GICM;
+#endif
+}
+
 void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr)
 {
 	vcpu->arch.tcr = new_tcr;
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index ba61974..e9b88e4 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -69,6 +69,7 @@ extern unsigned long kvmppc_booke_handlers;
 void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr);
 void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr);
 
+void kvmppc_set_epcr(struct kvm_vcpu *vcpu, u32 new_epcr);
 void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr);
 void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits);
 void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits);
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index 514790f..8d9d8f9 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -240,7 +240,12 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 	case SPRN_MCSR:
 		vcpu->arch.mcsr &= ~spr_val;
 		break;
-
+#if defined(CONFIG_64BIT) && defined(CONFIG_KVM_BOOKE_HV)
+	case SPRN_EPCR:
+		kvmppc_set_epcr(vcpu, spr_val);
+		mtspr(SPRN_EPCR, vcpu->arch.shadow_epcr);
+		break;
+#endif
 	default:
 		emulated = EMULATE_FAIL;
 	}
@@ -335,6 +340,11 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
 	case SPRN_MCSR:
 		*spr_val = vcpu->arch.mcsr;
 		break;
+#if defined(CONFIG_64BIT) && defined(CONFIG_KVM_BOOKE_HV)
+	case SPRN_EPCR:
+		*spr_val = vcpu->arch.epcr;
+		break;
+#endif
 
 	default:
 		emulated = EMULATE_FAIL;
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 12/12] KVM: PPC: booke: Get/set guest EPCR register using ONE_REG interface
From: Mihai Caraman @ 2012-10-11 16:13 UTC (permalink / raw)
  To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1349972009-23027-1-git-send-email-mihai.caraman@freescale.com>

Implement ONE_REG interface for EPCR register adding KVM_REG_PPC_EPCR to
the list of ONE_REG PPC supported registers.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
 Documentation/virtual/kvm/api.txt |    1 +
 arch/powerpc/include/asm/kvm.h    |    2 ++
 arch/powerpc/kvm/booke.c          |   16 ++++++++++++++++
 3 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index e726d76..c78dff4 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1773,6 +1773,7 @@ registers, find a list below:
   PPC   | KVM_REG_PPC_VPA_ADDR  | 64
   PPC   | KVM_REG_PPC_VPA_SLB   | 128
   PPC   | KVM_REG_PPC_VPA_DTL   | 128
+  PPC   | KVM_REG_PPC_EPCR	| 32
 
 4.69 KVM_GET_ONE_REG
 
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h
index b89ae4d..beb6b20 100644
--- a/arch/powerpc/include/asm/kvm.h
+++ b/arch/powerpc/include/asm/kvm.h
@@ -386,4 +386,6 @@ struct kvm_book3e_206_tlb_params {
 #define KVM_REG_PPC_VPA_SLB	(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x83)
 #define KVM_REG_PPC_VPA_DTL	(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84)
 
+#define KVM_REG_PPC_EPCR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x85)
+
 #endif /* __LINUX_KVM_POWERPC_H */
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index d396374..60b8237 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -1395,6 +1395,12 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 				 &vcpu->arch.dbg_reg.dac[dac], sizeof(u64));
 		break;
 	}
+#if defined(CONFIG_64BIT) && defined(CONFIG_KVM_BOOKE_HV)
+	case KVM_REG_PPC_EPCR:
+		r = copy_to_user((u32 __user *)(long)reg->addr,
+				 &vcpu->arch.epcr, sizeof(u32));
+		break;
+#endif
 	default:
 		break;
 	}
@@ -1422,6 +1428,16 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 			     (u64 __user *)(long)reg->addr, sizeof(u64));
 		break;
 	}
+#if defined(CONFIG_64BIT) && defined(CONFIG_KVM_BOOKE_HV)
+	case KVM_REG_PPC_EPCR: {
+		u32 new_epcr;
+		r = copy_from_user(&new_epcr,
+			     (u32 __user *)(long)reg->addr, sizeof(u32));
+		if (r == 0)
+			kvmppc_set_epcr(vcpu, new_epcr);
+		break;
+	}
+#endif
 	default:
 		break;
 	}
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 11/12] KVM: PPC: booke: Add EPCR support in sregs
From: Mihai Caraman @ 2012-10-11 16:13 UTC (permalink / raw)
  To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1349972009-23027-1-git-send-email-mihai.caraman@freescale.com>

Add KVM_SREGS_E_64 feature and EPCR spr support in get/set sregs for 64-bit
hosts.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
 arch/powerpc/kvm/booke.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index e6159f5..d396374 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -1215,6 +1215,9 @@ static void get_sregs_base(struct kvm_vcpu *vcpu,
 	u64 tb = get_tb();
 
 	sregs->u.e.features |= KVM_SREGS_E_BASE;
+#ifdef CONFIG_64BIT
+	sregs->u.e.features |= KVM_SREGS_E_64;
+#endif
 
 	sregs->u.e.csrr0 = vcpu->arch.csrr0;
 	sregs->u.e.csrr1 = vcpu->arch.csrr1;
@@ -1226,6 +1229,9 @@ static void get_sregs_base(struct kvm_vcpu *vcpu,
 	sregs->u.e.dec = kvmppc_get_dec(vcpu, tb);
 	sregs->u.e.tb = tb;
 	sregs->u.e.vrsave = vcpu->arch.vrsave;
+#if defined(CONFIG_64BIT) && defined(CONFIG_KVM_BOOKE_HV)
+	sregs->u.e.epcr = vcpu->arch.epcr;
+#endif
 }
 
 static int set_sregs_base(struct kvm_vcpu *vcpu,
@@ -1241,6 +1247,7 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
 	set_guest_dear(vcpu, sregs->u.e.dear);
 	vcpu->arch.vrsave = sregs->u.e.vrsave;
 	kvmppc_set_tcr(vcpu, sregs->u.e.tcr);
+	kvmppc_set_epcr(vcpu, sregs->u.e.epcr);
 
 	if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_DEC) {
 		vcpu->arch.dec = sregs->u.e.dec;
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 01/12] KVM: PPC: e500: Silence bogus GCC warning in tlb code
From: Mihai Caraman @ 2012-10-11 16:13 UTC (permalink / raw)
  To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1349972009-23027-1-git-send-email-mihai.caraman@freescale.com>

64-bit GCC 4.5.1 warns about an uninitialized variable which was guarded
by a flag. Initialize the variable to make it happy.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
 arch/powerpc/kvm/e500_tlb.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index c733894..23b3de6 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -415,7 +415,8 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 	struct tlbe_ref *ref)
 {
 	struct kvm_memory_slot *slot;
-	unsigned long pfn, hva;
+	unsigned long pfn = 0; /* shut up 64-bit GCC */
+	unsigned long hva;
 	int pfnmap = 0;
 	int tsize = BOOK3E_PAGESZ_4K;
 
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 09/12] KVM: PPC: bookehv: Add guest computation mode for irq delivery
From: Mihai Caraman @ 2012-10-11 16:13 UTC (permalink / raw)
  To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1349972009-23027-1-git-send-email-mihai.caraman@freescale.com>

When delivering guest IRQs, update MSR computation mode according to guest
interrupt computation mode found in EPCR.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v1: added intermediate msr variable.

 arch/powerpc/kvm/booke.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 7c9c389..86f0d0d 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -312,6 +312,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
 	bool crit;
 	bool keep_irq = false;
 	enum int_class int_class;
+	ulong new_msr = vcpu->arch.shared->msr;
 
 	/* Truncate crit indicators in 32 bit mode */
 	if (!(vcpu->arch.shared->msr & MSR_SF)) {
@@ -407,7 +408,13 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
 			set_guest_esr(vcpu, vcpu->arch.queued_esr);
 		if (update_dear == true)
 			set_guest_dear(vcpu, vcpu->arch.queued_dear);
-		kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
+
+		new_msr &= msr_mask;
+#if defined(CONFIG_64BIT) && defined(CONFIG_KVM_BOOKE_HV)
+		if (vcpu->arch.epcr & SPRN_EPCR_ICM)
+			new_msr |= MSR_CM;
+#endif
+		kvmppc_set_msr(vcpu, new_msr);
 
 		if (!keep_irq)
 			clear_bit(priority, &vcpu->arch.pending_exceptions);
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 02/12] KVM: PPC: booke: Fix get_tb() compile error on 64-bit
From: Mihai Caraman @ 2012-10-11 16:13 UTC (permalink / raw)
  To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1349972009-23027-1-git-send-email-mihai.caraman@freescale.com>

Include header file for get_tb() declaration.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
 arch/powerpc/kvm/booke.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 3d1f35d..7c9c389 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -36,6 +36,7 @@
 #include <asm/dbell.h>
 #include <asm/hw_irq.h>
 #include <asm/irq.h>
+#include <asm/time.h>
 
 #include "timing.h"
 #include "booke.h"
-- 
1.7.4.1

^ permalink raw reply related

* Re: linux-next: manual merge of the kvm-ppc tree with the powerpc-merge tree
From: Scott Wood @ 2012-10-11 16:33 UTC (permalink / raw)
  To: Alexander Graf
  Cc: Stephen Rothwell, Tabi Timur-B04825, linux-kernel@vger.kernel.org,
	David Howells, linux-next@vger.kernel.org, Paul Mackerras,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <CDB8B53D-EEC2-41A4-9BEA-66783409EE66@suse.de>

On 10/11/2012 10:56:51 AM, Alexander Graf wrote:
>=20
> On 11.10.2012, at 17:50, Scott Wood wrote:
>=20
> > On 10/11/2012 08:04:58 AM, Alexander Graf wrote:
> >> On 11.10.2012, at 05:32, Tabi Timur-B04825 wrote:
> >> > On Wed, Oct 10, 2012 at 9:47 PM, Stephen Rothwell =20
> <sfr@canb.auug.org.au> wrote:
> >> >
> >> >> Commit 549d62d889b4 ("KVM: PPC: use definitions in epapr header
> >> >> for hcalls") from the kvm-ppc tree added an include of =20
> asm/epapr_hcall.h
> >> >> to the user visible part of asm/kvm_para.h so asm/epapr_hcall.h =20
> became a
> >> >> user visible header file.
> >> >
> >> > Any real user-space code that tries to call any of the functions =20
> in
> >> > epapr_hcall.h will cause an exception.
> >
> > Actually it'll cause a linker error, as of the "Don't use hardcoded =20
> opcode for ePAPR hcall invocation" patch.
> >
> >> > Claiming that kernel header files that KVM needs are suddenly
> >> > user-space header files doesn't make much sense to me, but I =20
> guess
> >> > it's not my decision.
> >> This is about kvm_host.h, which is the part that is exported to =20
> user space. It usually contains constants and structs that are =20
> required for the API.
> >
> > s/kvm_host/kvm_para/
> >
> > I'm not sure anything in kvm_para.h or epapr_hcalls.h would be of =20
> use to userspace, but it would be of use to the guest OS, so it's =20
> still not kernel-internal.
> >
> > The variable externs should be #ifdef __KERNEL__ as David points =20
> out.  The asm stuff could still be useful in a guest OS if the guest =20
> provides epapr_hypercall_start.
>=20
> I don't think we should worry about guest kernel code potentially =20
> having use for this. Let's make the user space headers be great for =20
> user space usage, not for guest code usage :).

Well, that asm stuff started out as a guest header (from Freescale's =20
Topaz hypervisor), not a Linux header. :-)

-Scott=

^ permalink raw reply

* Re: linux-next: manual merge of the kvm-ppc tree with the powerpc-merge tree
From: Scott Wood @ 2012-10-11 16:37 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Stephen Rothwell, Alexander Graf, linux-kernel@vger.kernel.org,
	David Howells, linux-next@vger.kernel.org, Paul Mackerras,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <5076EBFE.5060208@freescale.com>

On 10/11/2012 10:55:42 AM, Timur Tabi wrote:
> Alexander Graf wrote:
>=20
>=20
> > This is about kvm_host.h, which is the part that is exported to user
> > space. It usually contains constants and structs that are required =20
> for
> > the API.
>=20
> Which API?  I'm not familiar with KVM internals.
>=20
> My concern is that when I think of a user-space header file, I think =20
> of a
> user-space application that calls ioctls.  I know that KVM guest =20
> kernels
> run as user-space processes, but that does not seem like a reason to
> combine all of the header files that the KVM guest kernel needs with
> "real" user-space header files.

So where should guest headers go?

-Scott=

^ permalink raw reply

* Re: linux-next: manual merge of the kvm-ppc tree with the powerpc-merge tree
From: Timur Tabi @ 2012-10-11 17:24 UTC (permalink / raw)
  To: Scott Wood
  Cc: Stephen Rothwell, Alexander Graf, linux-kernel@vger.kernel.org,
	David Howells, linux-next@vger.kernel.org, Paul Mackerras,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1349973438.6903.4@snotra>

Scott Wood wrote:
>> > My concern is that when I think of a user-space header file, I think  
>> > of a
>> > user-space application that calls ioctls.  I know that KVM guest  
>> > kernels
>> > run as user-space processes, but that does not seem like a reason to
>> > combine all of the header files that the KVM guest kernel needs with
>> > "real" user-space header files.

> So where should guest headers go?

I admit that I don't have any answers, especially since this whole thing
is new to me.  Like I said, I don't know much about KVM internals, so I
just don't understand why KVM guests need to have access to these kernel
header files as if they're user header files.  The guests are still Linux
kernels (or other OSes that think they're running as privileged code).

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply

* Re: linux-next: manual merge of the kvm-ppc tree with the powerpc-merge tree
From: Scott Wood @ 2012-10-11 17:28 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Stephen Rothwell, Alexander Graf, linux-kernel@vger.kernel.org,
	David Howells, linux-next@vger.kernel.org, Paul Mackerras,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <507700EB.5090307@freescale.com>

On 10/11/2012 12:24:59 PM, Timur Tabi wrote:
> Scott Wood wrote:
> >> > My concern is that when I think of a user-space header file, I =20
> think
> >> > of a
> >> > user-space application that calls ioctls.  I know that KVM guest
> >> > kernels
> >> > run as user-space processes, but that does not seem like a =20
> reason to
> >> > combine all of the header files that the KVM guest kernel needs =20
> with
> >> > "real" user-space header files.
>=20
> > So where should guest headers go?
>=20
> I admit that I don't have any answers, especially since this whole =20
> thing
> is new to me.  Like I said, I don't know much about KVM internals, so =20
> I
> just don't understand why KVM guests need to have access to these =20
> kernel
> header files as if they're user header files.  The guests are still =20
> Linux
> kernels (or other OSes that think they're running as privileged code).

For hypercalls and other paravirt.  That's the point -- they're not =20
kernel headers.  They're guest API headers.

-scott=

^ permalink raw reply

* Re: linux-next: manual merge of the kvm-ppc tree with the powerpc-merge tree
From: Timur Tabi @ 2012-10-11 17:30 UTC (permalink / raw)
  To: Scott Wood
  Cc: Stephen Rothwell, Alexander Graf, linux-kernel@vger.kernel.org,
	David Howells, linux-next@vger.kernel.org, Paul Mackerras,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1349976536.6903.7@snotra>

Scott Wood wrote:
> For hypercalls and other paravirt.  That's the point -- they're not  
> kernel headers.  They're guest API headers.

Well, IMHO, guest API != user-space.  Maybe we should have a parallel
mechanism to uapi to make the kvm guest header files available.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply

* Re: [PATCH] vfio: enabled and supported on power (v7)
From: Alex Williamson @ 2012-10-11 18:09 UTC (permalink / raw)
  To: Alexey Kardashevskiy; +Cc: Paul Mackerras, linuxppc-dev, David Gibson
In-Reply-To: <50768102.5030002@ozlabs.ru>

On Thu, 2012-10-11 at 19:19 +1100, Alexey Kardashevskiy wrote:
> Ok I'm back, nothing seems happened during last month :)

Nope, not much ;)  Note that I added a hack to avoid the INTx EOI
problem, I expect it should work for you too.

> On 14/09/12 14:35, Alex Williamson wrote:
> > On Fri, 2012-09-14 at 10:51 +1000, Alexey Kardashevskiy wrote:
> >> On 14/09/12 08:34, Alex Williamson wrote:
> >>> On Tue, 2012-09-11 at 18:28 +1000, Alexey Kardashevskiy wrote:
> >>>> On 11/09/12 02:02, Alex Williamson wrote:
> >>>>> On Tue, 2012-09-04 at 17:33 +1000, Alexey Kardashevskiy wrote:
> >>>>>> Cc: David Gibson <david@gibson.dropbear.id.au>
> >>>>>> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> >>>>>> Cc: Paul Mackerras <paulus@samba.org>
> >>>>>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> >>>>>> ---
> >>>>>
> >>>>> Please at least cc kvm@vger as well since we list that as the devel list
> >>>>> for vfio.
> >>>>>
> >>>>>>     arch/powerpc/include/asm/iommu.h    |    3 +
> >>>>>
> >>>>> I'll need an ack from Ben or Paul for this change.
> >>>>>
> >>>>>>     drivers/iommu/Kconfig               |    8 +
> >>>>>>     drivers/vfio/Kconfig                |    6 +
> >>>>>>     drivers/vfio/Makefile               |    1 +
> >>>>>>     drivers/vfio/vfio_iommu_spapr_tce.c |  440 +++++++++++++++++++++++++++++++++++
> >>>>>>     include/linux/vfio.h                |   29 +++
> >>>>>>     6 files changed, 487 insertions(+)
> >>>>>>     create mode 100644 drivers/vfio/vfio_iommu_spapr_tce.c
> >>>>>>
> >>>>>> diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
> >>>>>> index 957a83f..c64bce7 100644
> >>>>>> --- a/arch/powerpc/include/asm/iommu.h
> >>>>>> +++ b/arch/powerpc/include/asm/iommu.h
> >>>>>> @@ -66,6 +66,9 @@ struct iommu_table {
> >>>>>>     	unsigned long  it_halfpoint; /* Breaking point for small/large allocs */
> >>>>>>     	spinlock_t     it_lock;      /* Protects it_map */
> >>>>>>     	unsigned long *it_map;       /* A simple allocation bitmap for now */
> >>>>>> +#ifdef CONFIG_IOMMU_API
> >>>>>> +	struct iommu_group *it_group;
> >>>>>> +#endif
> >>>>>>     };
> >>>>>
> >>>>> This seems to only be valid when vfio_iommu_spapr_tce is loaded, which
> >>>>> is a bit misleading.
> >>>>>
> >>>>>>
> >>>>>>     struct scatterlist;
> >>>>>> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> >>>>>> index 3bd9fff..19cf2d9 100644
> >>>>>> --- a/drivers/iommu/Kconfig
> >>>>>> +++ b/drivers/iommu/Kconfig
> >>>>>> @@ -162,4 +162,12 @@ config TEGRA_IOMMU_SMMU
> >>>>>>     	  space through the SMMU (System Memory Management Unit)
> >>>>>>     	  hardware included on Tegra SoCs.
> >>>>>>
> >>>>>> +config SPAPR_TCE_IOMMU
> >>>>>> +	bool "sPAPR TCE IOMMU Support"
> >>>>>> +	depends on PPC_PSERIES
> >>>>>> +	select IOMMU_API
> >>>>>> +	help
> >>>>>> +	  Enables bits of IOMMU API required by VFIO. The iommu_ops is
> >>>>>> +	  still not implemented.
> >>>>>> +
> >>>>>>     endif # IOMMU_SUPPORT
> >>>>>> diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
> >>>>>> index 7cd5dec..b464687 100644
> >>>>>> --- a/drivers/vfio/Kconfig
> >>>>>> +++ b/drivers/vfio/Kconfig
> >>>>>> @@ -3,10 +3,16 @@ config VFIO_IOMMU_TYPE1
> >>>>>>     	depends on VFIO
> >>>>>>     	default n
> >>>>>>
> >>>>>> +config VFIO_IOMMU_SPAPR_TCE
> >>>>>> +	tristate
> >>>>>> +	depends on VFIO && SPAPR_TCE_IOMMU
> >>>>>> +	default n
> >>>>>> +
> >>>>>>     menuconfig VFIO
> >>>>>>     	tristate "VFIO Non-Privileged userspace driver framework"
> >>>>>>     	depends on IOMMU_API
> >>>>>>     	select VFIO_IOMMU_TYPE1 if X86
> >>>>>> +	select VFIO_IOMMU_SPAPR_TCE if PPC_POWERNV
> >>>>>>     	help
> >>>>>>     	  VFIO provides a framework for secure userspace device drivers.
> >>>>>>     	  See Documentation/vfio.txt for more details.
> >>>>>> diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
> >>>>>> index 2398d4a..72bfabc 100644
> >>>>>> --- a/drivers/vfio/Makefile
> >>>>>> +++ b/drivers/vfio/Makefile
> >>>>>> @@ -1,3 +1,4 @@
> >>>>>>     obj-$(CONFIG_VFIO) += vfio.o
> >>>>>>     obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
> >>>>>> +obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
> >>>>>>     obj-$(CONFIG_VFIO_PCI) += pci/
> >>>>>> diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c
> >>>>>> new file mode 100644
> >>>>>> index 0000000..21f1909
> >>>>>> --- /dev/null
> >>>>>> +++ b/drivers/vfio/vfio_iommu_spapr_tce.c
> >>>>>> @@ -0,0 +1,440 @@
> >>>>>> +/*
> >>>>>> + * VFIO: IOMMU DMA mapping support for TCE on POWER
> >>>>>> + *
> >>>>>> + * Copyright (C) 2012 IBM Corp.  All rights reserved.
> >>>>>> + *     Author: Alexey Kardashevskiy <aik@ozlabs.ru>
> >>>>>> + *
> >>>>>> + * This program is free software; you can redistribute it and/or modify
> >>>>>> + * it under the terms of the GNU General Public License version 2 as
> >>>>>> + * published by the Free Software Foundation.
> >>>>>> + *
> >>>>>> + * Derived from original vfio_iommu_x86.c:
> >>>>>
> >>>>> Should this be _type1?  Only the mail archives are going to remember
> >>>>> there was a _x86, so the renamed version is probably a better reference.
> >>>>>
> >>>>>> + * Copyright (C) 2012 Red Hat, Inc.  All rights reserved.
> >>>>>> + *     Author: Alex Williamson <alex.williamson@redhat.com>
> >>>>>> + */
> >>>>>> +
> >>>>>> +#include <linux/module.h>
> >>>>>> +#include <linux/pci.h>
> >>>>>> +#include <linux/slab.h>
> >>>>>> +#include <linux/uaccess.h>
> >>>>>> +#include <linux/err.h>
> >>>>>> +#include <linux/vfio.h>
> >>>>>> +#include <linux/spinlock.h>
> >>>>>> +#include <asm/iommu.h>
> >>>>>> +
> >>>>>> +#define DRIVER_VERSION  "0.1"
> >>>>>> +#define DRIVER_AUTHOR   "aik@ozlabs.ru"
> >>>>>> +#define DRIVER_DESC     "VFIO IOMMU SPAPR TCE"
> >>>>>> +
> >>>>>> +
> >>>>>> +/*
> >>>>>> + * SPAPR TCE API
> >>>>>> + */
> >>>>>> +static void tce_free(struct iommu_table *tbl, unsigned long entry,
> >>>>>> +		unsigned long tce)
> >>>>>> +{
> >>>>>> +	struct page *page = pfn_to_page(tce >> PAGE_SHIFT);
> >>>>>> +
> >>>>>> +	WARN_ON(!page);
> >>>>>> +	if (page) {
> >>>>>> +		if (tce & VFIO_SPAPR_TCE_WRITE)
> >>>>>> +			SetPageDirty(page);
> >>>>>> +		put_page(page);
> >>>>>> +	}
> >>>>>> +	ppc_md.tce_free(tbl, entry, 1);
> >>>>>> +}
> >>>>>> +
> >>>>>> +static long tce_put(struct iommu_table *tbl,
> >>>>>> +		unsigned long entry, uint64_t tce, uint32_t flags)
> >>>>>> +{
> >>>>>> +	int ret;
> >>>>>> +	unsigned long oldtce, kva, offset;
> >>>>>> +	struct page *page = NULL;
> >>>>>> +	enum dma_data_direction direction = DMA_NONE;
> >>>>>> +
> >>>>>> +	switch (flags & VFIO_SPAPR_TCE_PUT_MASK) {
> >>>>>> +	case VFIO_SPAPR_TCE_READ:
> >>>>>> +		direction = DMA_TO_DEVICE;
> >>>>>> +		break;
> >>>>>> +	case VFIO_SPAPR_TCE_WRITE:
> >>>>>> +		direction = DMA_FROM_DEVICE;
> >>>>>> +		break;
> >>>>>> +	case VFIO_SPAPR_TCE_BIDIRECTIONAL:
> >>>>>> +		direction = DMA_BIDIRECTIONAL;
> >>>>>> +		break;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	oldtce = ppc_md.tce_get(tbl, entry);
> >>>>>> +
> >>>>>> +	/* Free page if still allocated */
> >>>>>> +	if (oldtce & VFIO_SPAPR_TCE_PUT_MASK)
> >>>>>> +		tce_free(tbl, entry, oldtce);
> >>>>>> +
> >>>>>> +	/* Map new TCE */
> >>>>>> +	if (direction != DMA_NONE) {
> >>>>>> +		offset = (tce & IOMMU_PAGE_MASK) - (tce & PAGE_MASK);
> >>>>>> +		ret = get_user_pages_fast(tce & PAGE_MASK, 1,
> >>>>>> +				direction != DMA_TO_DEVICE, &page);
> >>>>>> +		BUG_ON(ret > 1);
> >>>>>
> >>>>> Can this happen?
> >>>>>
> >>>>>> +		if (ret < 1) {
> >>>>>> +			printk(KERN_ERR "tce_vfio: get_user_pages_fast failed "
> >>>>>> +					"tce=%llx ioba=%lx ret=%d\n",
> >>>>>> +					tce, entry << IOMMU_PAGE_SHIFT, ret);
> >>>>>> +			if (!ret)
> >>>>>> +				ret = -EFAULT;
> >>>>>> +			goto unlock_exit;
> >>>>>> +		}
> >>>>>> +
> >>>>>> +		kva = (unsigned long) page_address(page);
> >>>>>> +		kva += offset;
> >>>>>> +		BUG_ON(!kva);
> >>>>>
> >>>>> Same here, can it happen?  If so, should it BUG or catch the below
> >>>>> EINVAL?
> >>>>>
> >>>>>> +		if (WARN_ON(kva & ~IOMMU_PAGE_MASK))
> >>>>>> +			return -EINVAL;
> >>>>>
> >>>>> Page leak?  Don't we want to do a put_page(), which means we probably
> >>>>> want a goto exit here.
> >>>>>
> >>>>>> +
> >>>>>> +		/* Preserve access bits */
> >>>>>> +		kva |= flags & VFIO_SPAPR_TCE_PUT_MASK;
> >>>>>> +
> >>>>>> +		/* tce_build receives a virtual address */
> >>>>>> +		entry += tbl->it_offset;	/* Offset into real TCE table */
> >>>>>> +		ret = ppc_md.tce_build(tbl, entry, 1, kva, direction, NULL);
> >>>>>> +
> >>>>>> +		/* tce_build() only returns non-zero for transient errors */
> >>>>>> +		if (unlikely(ret)) {
> >>>>>> +			printk(KERN_ERR "tce_vfio: Failed to add TCE\n");
> >>>>>> +			ret = -EIO;
> >>>>>> +			goto unlock_exit;
> >>>>>> +		}
> >>>>>> +	}
> >>>>>> +	/* Flush/invalidate TLB caches if necessary */
> >>>>>> +	if (ppc_md.tce_flush)
> >>>>>> +		ppc_md.tce_flush(tbl);
> >>>>>> +
> >>>>>> +	/* Make sure updates are seen by hardware */
> >>>>>> +	mb();
> >>>>>> +
> >>>>>> +unlock_exit:
> >>>>>
> >>>>> unlock seems wrong here, I had to go re-read the code looking for the
> >>>>> lock.
> >>>>>
> >>>>>> +	if (ret && page)
> >>>>>> +		put_page(page);
> >>>>>> +
> >>>>>> +	if (ret)
> >>>>>> +		printk(KERN_ERR "tce_vfio: tce_put failed on tce=%llx "
> >>>>>> +				"ioba=%lx kva=%lx\n", tce,
> >>>>>> +				entry << IOMMU_PAGE_SHIFT, kva);
> >>>>>> +	return ret;
> >>>>>> +}
> >>>>>> +
> >>>>>> +/*
> >>>>>> + * VFIO IOMMU fd for SPAPR_TCE IOMMU implementation
> >>>>>> + */
> >>>>>> +
> >>>>>> +/*
> >>>>>> + * The container descriptor supports only a single group per container.
> >>>>>> + * Required by the API as the container is not supplied with the IOMMU group
> >>>>>> + * at the moment of initialization.
> >>>>>> + */
> >>>>>> +struct tce_container {
> >>>>>> +	struct iommu_table *tbl;
> >>>>>> +};
> >>>>>> +
> >>>>>> +static void *tce_iommu_open(unsigned long arg)
> >>>>>> +{
> >>>>>> +	struct tce_container *container;
> >>>>>> +
> >>>>>> +	if (arg != VFIO_SPAPR_TCE_IOMMU) {
> >>>>>> +		printk(KERN_ERR "tce_vfio: Wrong IOMMU type\n");
> >>>>>> +		return ERR_PTR(-EINVAL);
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	container = kzalloc(sizeof(*container), GFP_KERNEL);
> >>>>>> +	if (!container)
> >>>>>> +		return ERR_PTR(-ENOMEM);
> >>>>>> +
> >>>>>> +	return container;
> >>>>>> +}
> >>>>>> +
> >>>>>> +static void tce_iommu_release(void *iommu_data)
> >>>>>> +{
> >>>>>> +	struct tce_container *container = iommu_data;
> >>>>>> +	struct iommu_table *tbl = container->tbl;
> >>>>>> +	unsigned long i, tce;
> >>>>>> +
> >>>>>
> >>>>> This will segfault if releasing a container that never had an a device
> >>>>> attached.
> >>>>>
> >>>>>> +	/* Unmap leftovers */
> >>>>>> +	spin_lock_irq(&tbl->it_lock);
> >>>>>> +	for (i = tbl->it_offset; i < tbl->it_offset + tbl->it_size; ++i) {
> >>>>>> +		tce = ppc_md.tce_get(tbl, i);
> >>>>>> +		if (tce & VFIO_SPAPR_TCE_PUT_MASK)
> >>>>>> +			tce_free(tbl, i, tce);
> >>>>>> +	}
> >>>>>> +	/* Flush/invalidate TLB caches if necessary */
> >>>>>> +	if (ppc_md.tce_flush)
> >>>>>> +		ppc_md.tce_flush(tbl);
> >>>>>> +
> >>>>>> +	/* Make sure updates are seen by hardware */
> >>>>>> +	mb();
> >>>>>> +
> >>>>>> +	spin_unlock_irq(&tbl->it_lock);
> >>>>>> +
> >>>>>> +	kfree(container);
> >>>>>> +}
> >>>>>> +
> >>>>>> +static long tce_iommu_ioctl(void *iommu_data,
> >>>>>> +				 unsigned int cmd, unsigned long arg)
> >>>>>> +{
> >>>>>> +	struct tce_container *container = iommu_data;
> >>>>>> +	unsigned long minsz;
> >>>>>> +	long ret;
> >>>>>> +
> >>>>>> +	switch (cmd) {
> >>>>>> +	case VFIO_CHECK_EXTENSION: {
> >>>>>> +		return (arg == VFIO_SPAPR_TCE_IOMMU) ? 1 : 0;
> >>>>>> +	}
> >>>>>> +	case VFIO_IOMMU_SPAPR_TCE_GET_INFO: {
> >>>>>> +		struct vfio_iommu_spapr_tce_info info;
> >>>>>> +		struct iommu_table *tbl = container->tbl;
> >>>>>> +
> >>>>>> +		minsz = offsetofend(struct vfio_iommu_spapr_tce_info,
> >>>>>> +				dma64_window_size);
> >>>>>> +
> >>>>>> +		if (copy_from_user(&info, (void __user *)arg, minsz))
> >>>>>> +			return -EFAULT;
> >>>>>> +
> >>>>>> +		if (info.argsz < minsz)
> >>>>>> +			return -EINVAL;
> >>>>>> +
> >>>>>> +		if (!tbl)
> >>>>>> +			return -ENXIO;
> >>>>>
> >>>>> nit: why not check this earlier?
> >>>>>
> >>>>>> +
> >>>>>> +		info.dma32_window_start = tbl->it_offset << IOMMU_PAGE_SHIFT;
> >>>>>> +		info.dma32_window_size = tbl->it_size << IOMMU_PAGE_SHIFT;
> >>>>>> +		info.dma64_window_start = 0;
> >>>>>> +		info.dma64_window_size = 0;
> >>>>>> +		info.flags = 0;
> >>>>>> +
> >>>>>> +		return copy_to_user((void __user *)arg, &info, minsz);
> >>>>>> +	}
> >>>>>> +	case VFIO_IOMMU_SPAPR_TCE_PUT: {
> >>>>>> +		struct vfio_iommu_spapr_tce_put par;
> >>>>>> +		struct iommu_table *tbl = container->tbl;
> >>>>>> +
> >>>>>> +		minsz = offsetofend(struct vfio_iommu_spapr_tce_put, tce);
> >>>>>> +
> >>>>>> +		if (copy_from_user(&par, (void __user *)arg, minsz))
> >>>>>> +			return -EFAULT;
> >>>>>> +
> >>>>>> +		if (par.argsz < minsz)
> >>>>>> +			return -EINVAL;
> >>>>>> +
> >>>>>> +		if (!tbl) {
> >>>>>> +			return -ENXIO;
> >>>>>> +		}
> >>>>>
> >>>>> Same, plus drop the braces.
> >>>>>
> >>>>>> +
> >>>>>> +		spin_lock_irq(&tbl->it_lock);
> >>>>>> +		ret = tce_put(tbl, par.ioba >> IOMMU_PAGE_SHIFT,
> >>>>>> +				par.tce, par.flags);
> >>>>>> +		spin_unlock_irq(&tbl->it_lock);
> >>>>>> +
> >>>>>> +		return ret;
> >>>>>> +	}
> >>>>>
> >>>>> Is "PUT" really the name we want for this?
> >>>>
> >>>>
> >>>> Yes, it is a single H_PUT_TCE hypercall from POWER architecture spec.
> >>>
> >>> Ok, if it makes sense on your arch, I won't complain (too much) about
> >>> it.
> >>>
> >>>>>> +	default:
> >>>>>> +		printk(KERN_WARNING "tce_vfio: unexpected cmd %x\n", cmd);
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	return -ENOTTY;
> >>>>>> +}
> >>>>>> +
> >>>>>> +static int tce_iommu_attach_group(void *iommu_data,
> >>>>>> +		struct iommu_group *iommu_group)
> >>>>>> +{
> >>>>>> +	struct tce_container *container = iommu_data;
> >>>>>> +	struct iommu_table *tbl = iommu_group_get_iommudata(iommu_group);
> >>>>>> +
> >>>>>> +	printk(KERN_DEBUG "tce_vfio: Attaching group #%u to iommu %p\n",
> >>>>>> +			iommu_group_id(iommu_group), iommu_group);
> >>>>>
> >>>>> Let's use pr_debug() and friends throughout.
> >>>>>
> >>>>>> +	if (container->tbl) {
> >>>>>> +		printk(KERN_WARNING "tce_vfio: Only one group per IOMMU "
> >>>>>> +				"container is allowed, "
> >>>>>> +				"existing id=%d, attaching id=%d\n",
> >>>>>> +				iommu_group_id(container->tbl->it_group),
> >>>>>> +				iommu_group_id(iommu_group));
> >>>>>> +		return -EBUSY;
> >>>>>> +	}
> >>>>>> +
> >>>>>
> >>>>> _type1 has a lock to avoid races here, I think you might need one too.
> >>>>>
> >>>>>> +	container->tbl = tbl;
> >>>>>> +
> >>>>>> +	return 0;
> >>>>>> +}
> >>>>>> +
> >>>>>> +static void tce_iommu_detach_group(void *iommu_data,
> >>>>>> +		struct iommu_group *iommu_group)
> >>>>>> +{
> >>>>>> +	struct tce_container *container = iommu_data;
> >>>>>> +	struct iommu_table *tbl = iommu_group_get_iommudata(iommu_group);
> >>>>>> +
> >>>>>> +	BUG_ON(!tbl);
> >>>>>
> >>>>> Needed?  If so, why is there no check on attach?
> >>>>
> >>>> Added to attach() :)
> >>>>
> >>>>
> >>>>>
> >>>>>> +	if (tbl != container->tbl) {
> >>>>>> +		printk(KERN_WARNING "tce_vfio: detaching group #%u, expected "
> >>>>>> +				"group is #%u\n", iommu_group_id(iommu_group),
> >>>>>> +				iommu_group_id(tbl->it_group));
> >>>>>> +		return;
> >>>>>> +	}
> >>>>>> +	printk(KERN_DEBUG "tce_vfio: detaching group #%u from iommu %p\n",
> >>>>>> +			iommu_group_id(iommu_group), iommu_group);
> >>>>>
> >>>>> container->tbl = NULL?
> >>>>
> >>>>
> >>>> Then I won't be able to release pages in tce_iommu_release().
> >>>> Releasing pages in tce_iommu_detach_group() caused some other problems,
> >>>> cannot recall now which ones.
> >>>
> >>> What happens if you hot unplug a group from one VM and add it to
> >>> another?  ie. we've detached it from one container and add it to another
> >>> in a different instance.  Does it cause problems here?
> >>
> >>
> >> Then the container will be released as just one group per container is
> >> supported at the moment, no? Cannot check though as we do not support
> >> hotplug yet.
> >
> > But you still have a race where the group is detached, but the container
> > is not yet released and can be attached to another container in a
> > different instance.
> 
> 
> Yeah... Moved cleanup to detach(), trying to reproduce the issue I had 
> before but to no avail.
> 
> 
> >>>>>> +}
> >>>>>> +
> >>>>>> +const struct vfio_iommu_driver_ops tce_iommu_driver_ops = {
> >>>>>> +	.name		= "iommu-vfio-powerpc",
> >>>>>> +	.owner		= THIS_MODULE,
> >>>>>> +	.open		= tce_iommu_open,
> >>>>>> +	.release	= tce_iommu_release,
> >>>>>> +	.ioctl		= tce_iommu_ioctl,
> >>>>>> +	.attach_group	= tce_iommu_attach_group,
> >>>>>> +	.detach_group	= tce_iommu_detach_group,
> >>>>>> +};
> >>>>>> +
> >>>>>> +/*
> >>>>>> + * Add/delete devices support (hotplug, module_init, module_exit)
> >>>>>> + */
> >>>>>> +static int add_device(struct device *dev)
> >>>>>> +{
> >>>>>> +	struct iommu_table *tbl;
> >>>>>> +	int ret = 0;
> >>>>>> +
> >>>>>> +	if (dev->iommu_group) {
> >>>>>> +		printk(KERN_WARNING "tce_vfio: device %s is already in iommu "
> >>>>>> +				"group %d, skipping\n", dev->kobj.name,
> >>>>>
> >>>>> Watch line wrapping on strings.
> >>>>
> >>>> Pardon?
> >>>
> >>> Just suggesting that you try to wrap lines so that strings are
> >>> searchable.  For instance, can I search cscope for "is already in iommu
> >>> group".  It's generally accepted that printks can break 80 cols for
> >>> this.
> >>
> >> Aaaa. Did not know that this is accepted but was always annoyed to wrap
> >> this way, thanks :)
> >>
> >>
> >>>>>> +				iommu_group_id(dev->iommu_group));
> >>>>>> +		return -EBUSY;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	tbl = get_iommu_table_base(dev);
> >>>>>> +	if (!tbl) {
> >>>>>> +		printk(KERN_DEBUG "tce_vfio: skipping device %s with no tbl\n",
> >>>>>> +				dev->kobj.name);
> >>>>>> +		return 0;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	printk(KERN_DEBUG "tce_vfio: adding %s to iommu group %d\n",
> >>>>>> +			dev->kobj.name, iommu_group_id(tbl->it_group));
> >>>>>> +
> >>>>>> +	ret = iommu_group_add_device(tbl->it_group, dev);
> >>>>>> +	if (ret < 0)
> >>>>>> +		printk(KERN_ERR "tce_vfio: %s has not been added, ret=%d\n",
> >>>>>> +				dev->kobj.name, ret);
> >>>>>> +
> >>>>>> +	return ret;
> >>>>>> +}
> >>>>>> +
> >>>>>> +static void del_device(struct device *dev)
> >>>>>> +{
> >>>>>> +	iommu_group_remove_device(dev);
> >>>>>> +}
> >>>>>> +
> >>>>>> +static int iommu_bus_notifier(struct notifier_block *nb,
> >>>>>> +			      unsigned long action, void *data)
> >>>>>> +{
> >>>>>> +	struct device *dev = data;
> >>>>>> +
> >>>>>> +	switch (action) {
> >>>>>> +	case BUS_NOTIFY_ADD_DEVICE:
> >>>>>> +		return add_device(dev);
> >>>>>> +	case BUS_NOTIFY_DEL_DEVICE:
> >>>>>> +		del_device(dev);
> >>>>>> +		return 0;
> >>>>>> +	default:
> >>>>>> +		return 0;
> >>>>>> +	}
> >>>>>> +}
> >>>>>> +
> >>>>>> +static struct notifier_block tce_iommu_bus_nb = {
> >>>>>> +	.notifier_call = iommu_bus_notifier,
> >>>>>> +};
> >>>>>> +
> >>>>>> +void group_release(void *iommu_data)
> >>>>>> +{
> >>>>>> +	struct iommu_table *tbl = iommu_data;
> >>>>>> +	tbl->it_group = NULL;
> >>>>>> +}
> >>>>>> +
> >>>>>> +static int __init tce_iommu_init(void)
> >>>>>> +{
> >>>>>> +	struct pci_dev *pdev = NULL;
> >>>>>> +	struct iommu_table *tbl;
> >>>>>> +	struct iommu_group *grp;
> >>>>>> +
> >>>>>> +	/* If the current platform does not support tce_get
> >>>>>> +	   we are unable to clean TCE table properly and
> >>>>>> +	   therefore it is better not to touch it at all */
> >>>>>> +	if (!ppc_md.tce_get) {
> >>>>>> +		printk(KERN_ERR "tce_vfio: ppc_md.tce_get isn't implemented\n");
> >>>>>> +		return -EOPNOTSUPP;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
> >>>>>> +
> >>>>>> +	/* Allocate and initialize VFIO groups */
> >>>>>
> >>>>> s/VFIO groups/IOMMU groups/
> >>>>>
> >>>>>> +	for_each_pci_dev(pdev) {
> >>>>>> +		tbl = get_iommu_table_base(&pdev->dev);
> >>>>>> +		if (!tbl)
> >>>>>> +			continue;
> >>>>>> +
> >>>>>> +		/* Skip already initialized */
> >>>>>> +		if (tbl->it_group)
> >>>>>> +			continue;
> >>>>>> +
> >>>>>> +		grp = iommu_group_alloc();
> >>>>>> +		if (IS_ERR(grp)) {
> >>>>>> +			printk(KERN_INFO "tce_vfio: cannot create "
> >>>>>> +					"new IOMMU group, ret=%ld\n",
> >>>>>> +					PTR_ERR(grp));
> >>>>>> +			return -EFAULT;
> >>>>>> +		}
> >>>>>> +		tbl->it_group = grp;
> >>>>>> +		iommu_group_set_iommudata(grp, tbl, group_release);
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	/* Add PCI devices to VFIO groups */
> >>>>>> +	for_each_pci_dev(pdev)
> >>>>>> +		add_device(&pdev->dev);
> >>>>>> +
> >>>>>> +	return vfio_register_iommu_driver(&tce_iommu_driver_ops);
> >>>>>> +}
> >>>>>> +
> >>>>>> +static void __exit tce_iommu_cleanup(void)
> >>>>>> +{
> >>>>>> +	struct pci_dev *pdev = NULL;
> >>>>>> +	struct iommu_table *tbl;
> >>>>>> +	struct iommu_group *grp = NULL;
> >>>>>> +
> >>>>>> +	bus_unregister_notifier(&pci_bus_type, &tce_iommu_bus_nb);
> >>>>>> +
> >>>>>> +	/* Delete PCI devices from VFIO groups */
> >>>>>> +	for_each_pci_dev(pdev)
> >>>>>> +		del_device(&pdev->dev);
> >>>>>> +
> >>>>>> +	/* Release VFIO groups */
> >>>>>> +	for_each_pci_dev(pdev) {
> >>>>>> +		tbl = get_iommu_table_base(&pdev->dev);
> >>>>>> +		if (!tbl)
> >>>>>> +			continue;
> >>>>>> +		grp = tbl->it_group;
> >>>>>> +
> >>>>>> +		/* Skip (already) uninitialized */
> >>>>>> +		if (!grp)
> >>>>>> +			continue;
> >>>>>> +
> >>>>>> +		/* Do actual release, group_release() is expected to work */
> >>>>>> +		iommu_group_put(grp);
> >>>>>> +		BUG_ON(tbl->it_group);
> >>>>>> +	}
> >>>>>> +
> >>>>>
> >>>>>
> >>>>> It troubles me a bit that you're using the vfio driver to initialize and
> >>>>> tear down IOMMU groups on your platform.
> >>>>
> >>>>
> >>>> I am not following you here. Could you please explain a bit?
> >>>
> >>> IOMMU groups are theoretically not just for VFIO.  They expose DMA
> >>> dependencies between devices for anyone who cares to know about it.
> >>> VFIO happens to care very much about that, but is hopefully not the only
> >>> consumer.  So it's a little bit like writing a driver for a device on a
> >>> new bus and incorporating the bus topology handling code into the device
> >>> driver.  IOMMU groups should be created and managed independent of VFIO.
> >>
> >> Do you mean that we create groups only for PCI devices? Well, moving groups
> >> creation where the actual powerpc groups are allocated (pci scan) is
> >> problematic right now as iommu_init() is called too late.
> >
> > I mean IOMMU group creation should be independent of VFIO.  I'm not sure
> > how to make that ordering work on POWER, but integrating them into your
> > VFIO driver is contrary to many of the arguments that were made for
> > making IOMMU groups part of the base device model.
> 
> 
> I still do not get it. The creation code itself does not depend on VFIO.
> And yes, I would like to create groups from the platform code when the 
> actual IOMMU tables are created, the only problem is that iommu_init() is 
> called too late - after PCI scan (subsys_initcall(pcibios_init) from 
> arch/powerpc/kernel/pci_64.c), iommu_init is subsys_initcall as well.
> I could move tce_iommu_init/tce_iommu_cleanup as a module somewhere in 
> arch/powerpc but moving iommu_init() earlier looks better, then I would 
> create IOMMU groups exactly when their POWER counterparts are created.

That sounds like a better integration of IOMMU groups into POWER than
only enabling them for VFIO.

> >>>>> VFIO makes use of IOMMU groups
> >>>>> and is the only user so far, but they're hopefully useful beyond this.
> >>>>> In fact, VFIO used to manage assembling all groups from data provided by
> >>>>> the IOMMU but David wanted to see IOMMU groups be a more universally
> >>>>> available feature, so it's odd to see POWER implementing it this way.
> >>>>
> >>>>
> >>>> David, help! :)
> >>>>
> >>>>
> >>>>>> +	vfio_unregister_iommu_driver(&tce_iommu_driver_ops);
> >>>>>> +}
> >>>>>> +
> >>>>>> +module_init(tce_iommu_init);
> >>>>>> +module_exit(tce_iommu_cleanup);
> >>>>>> +
> >>>>>> +MODULE_VERSION(DRIVER_VERSION);
> >>>>>> +MODULE_LICENSE("GPL v2");
> >>>>>> +MODULE_AUTHOR(DRIVER_AUTHOR);
> >>>>>> +MODULE_DESCRIPTION(DRIVER_DESC);
> >>>>>> +
> >>>>>> diff --git a/include/linux/vfio.h b/include/linux/vfio.h
> >>>>>> index 0a4f180..2c0a927 100644
> >>>>>> --- a/include/linux/vfio.h
> >>>>>> +++ b/include/linux/vfio.h
> >>>>>> @@ -99,6 +99,7 @@ extern void vfio_unregister_iommu_driver(
> >>>>>>     /* Extensions */
> >>>>>>
> >>>>>>     #define VFIO_TYPE1_IOMMU		1
> >>>>>> +#define VFIO_SPAPR_TCE_IOMMU		2
> >>>>>>
> >>>>>>     /*
> >>>>>>      * The IOCTL interface is designed for extensibility by embedding the
> >>>>>> @@ -442,4 +443,32 @@ struct vfio_iommu_type1_dma_unmap {
> >>>>>>
> >>>>>>     #define VFIO_IOMMU_UNMAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 14)
> >>>>>>
> >>>>>> +/* -------- API for SPAPR TCE (Server POWERPC) IOMMU -------- */
> >>>>>> +
> >>>>>> +struct vfio_iommu_spapr_tce_info {
> >>>>>> +	__u32 argsz;
> >>>>>> +	__u32 flags;
> >>>>>> +	__u32 dma32_window_start;
> >>>>>> +	__u32 dma32_window_size;
> >>>>>> +	__u64 dma64_window_start;
> >>>>>> +	__u64 dma64_window_size;
> >>>>>> +};
> >>>>>> +
> >>>>>> +#define VFIO_IOMMU_SPAPR_TCE_GET_INFO	_IO(VFIO_TYPE, VFIO_BASE + 12)
> >>>>>> +
> >>>>>> +struct vfio_iommu_spapr_tce_put {
> >>>>>> +	__u32 argsz;
> >>>>>> +	__u32 flags;
> >>>>>> +#define VFIO_SPAPR_TCE_READ		1
> >>>>>> +#define VFIO_SPAPR_TCE_WRITE		2
> >>>>>> +#define VFIO_SPAPR_TCE_BIDIRECTIONAL	(VFIO_SPAPR_TCE_READ|VFIO_SPAPR_TCE_WRITE)
> >>>>>> +#define VFIO_SPAPR_TCE_PUT_MASK		VFIO_SPAPR_TCE_BIDIRECTIONAL
> >>>>>> +	__u64 ioba;
> >>>>>> +	__u64 tce;
> >>>>>> +};
> >>>>>
> >>>>> Ok, so if READ & WRITE are both clear and ioba is set, that's an
> >>>>> "unmap"?  This is exactly why _type1 has a MAP and UNMAP, to make it
> >>>>> clear which fields are necessary for which call.  I think we should
> >>>>> probably do the same here.  Besides, _put makes me think there should be
> >>>>> a _get; do these have some unique meaning in POWER?
> >>>>
> >>>>
> >>>> It is a single H_PUT_TCE for putting a record into TCE table. The guest
> >>>> calls H_PUT_TCE, QEMU replaces the address and simply forwards the call to
> >>>> the host. Calling them map/unmap makes it less clear for powerpc people :)
> >>>
> >>> In the unmap case we take an ioba and lookup a tce to clear, in the map
> >>> case we take an ioba and tce and insert them into the table.  It's valid
> >>> to document this and use a single ioctl, but I've opted on x86 to have
> >>> separate ioctls because the documentation falls out cleaner when there
> >>> aren't fields that are only used in certain conditions.  Do you really
> >>> want any userspace driver making use of this to know about powerpc
> >>> H_PUT_TCE or would it make more sense to have a MAP and UNMAP call?  I
> >>> think it would be better for the VFIO API if we had some consistency in
> >>> the mapping ioctls where possible.
> >>
> >>
> >> I would think that passing through "as is" as much as possible is the best
> >> thing here as the aim is KVM. May be one day we will implement H_PUT_TCE in
> >> the kernel, so splitting H_PUT_TCE to map+unmap and then combining it back
> >> in the kernel (because we will have H_PUT_TCE handler) is a bit ugly.
> >
> > No, KVM is a use case for VFIO, we shouldn't be assume it's _the_ use
> > case.  Exposing it "as is" means anyone trying to write a VFIO userspace
> > driver needs to know about the implementation of H_PUT_TCE to make the
> > driver work on POWER.  The fact that the same hypercall is made for a
> > map or unmap is really irrelevant to the VFIO API.
> >
> >>>>>> +#define VFIO_IOMMU_SPAPR_TCE_PUT	_IO(VFIO_TYPE, VFIO_BASE + 13)
> >>>>>> +
> >>>>>
> >>>>> Please document what all of the above means.  Thanks,
> >>>>
> >>>>
> >>>> Something like this?
> >>>> /*
> >>>>     * The VFIO_IOMMU_SPAPR_TCE_PUT is implemented as the H_PUT_TCE hypercall.
> >>>>     * ioba - I/O Bus Address for indexing into TCE table
> >>>>     * tce - logical address of storage
> >>>>     *
> >>>>     * The non-zero flags means adding new page into the table.
> >>>>     * The zero flags means releasing the existing page and clearing the
> >>>>     * TCE table entry.
> >>>>     */
> >>>
> >>> Do you only want VFIO drivers to work on POWER if they're written by
> >>> POWER people?  Ideally there are a few simple concepts: a) devices have
> >>> an I/O virtual address space.  On x86 we call this the iova and it's
> >>> effectively a zero-based, 64bit (not really, but close enough) address
> >>> space.  You seem to have two smaller windows, one in 32bit space,
> >>> another in 64bit space (maybe we could name these more consistently).
> >>> b) Userspace has a buffer that they want to map and unmap to an iova,
> >>> potentially with some access flags.  That's all you need to know to use
> >>> the x86 _type1 VFIO IOMMU API.
> >>
> >>
> >> Do not you have to map entire RAM to PCI bus? You use listener which
> >> purpose is not very clear. This is an extra knowledge beyond qemu-to-host
> >> interface which the user space program should know.
> >
> > In the x86 case, the buffer we want to map is all of guest RAM.  Some of
> > that changes dynamically, so we have a listener setup to make updates.
> > The only thing magic about doing that is that the device is then able to
> > DMA to any part of guest RAM and therefore the guest doesn't need to
> > know the IOMMU exists.  Device assignment is therefore transparent on
> > x86.
> 
> >>> Why do I need to know about H_PUT_TCE to
> >>> use this interface?  Let's assume there might be some VFIO drivers some
> >>> day that aren't written by POWER people.  Thanks,
> >>
> >> Example of such a driver? My imagination is weak :)
> >
> > See Tom Lyon's original user level drivers:
> >
> > https://github.com/pugs/vfio-user-level-drivers
> >
> > These are against the original version of VFIO so no longer work, but
> > he's got drivers for common devices like Intel 82576 & 82599 SR-IOV
> > NICs.  There are special use cases and special devices where it makes
> > sense to have a driver in userspace.  Ideally a VFIO driver for a NIC
> > would work with fairly minimal IOMMU abstractions between x86 and POWER,
> > but if you design the SPAPR VFIO IOMMU API so that users need to
> > understand how H_PUT_TCE works to port their driver to POWER, you might
> > find it more difficult to leverage such drivers.  Thanks,
> 
> A user space driver needs to know the DMA window if it wants to work on 
> POWER because this is how PHB is configured. So it needs to know something 
> about POWER.

No, it only needs to know the window.

>  It could be fixed easily - we stop using IOMMU types and make 
> map/unmap/info independent from the IOMMU type.

Exactly, try to implement map/unmap/info and where possible, try to use
similar parameters to the existing iommu backends so we have some
consistency.  Adding a window is a trivial addition and doesn't require
the user to know anything about H_PUT_TCE.

> You'll have to implement 
> DMA window properties (which is entire RAM) and then we'll put to the spec 
> that VFIO users have to call DMA map/unmap only for addresses within the 
> returned DMA window boundaries. I thought this is what we wanted to avoid...

Yes, now you've gone too far.  Trying to define a single interface to
support any possible IOMMU is an exercise in madness.  We've tried it
before.  What I would like to agree on is simply that info, map, and
unmap should exist for all IOMMUs and should use similar parameters
where possible.  Your info needs to describe windows, mine doesn't,
that's fine.  Is there any reason your map or unmap needs to be
different?  If we limit the differences to only those necessary we'll
make it much easier for userspace drivers to share code.

> Or implement third type of IOMMU - "VFIO user space driver" (and implement 
> dma_alloc() which would allocate an address for DMA on PCI bus) and name 
> the first twos as "TYPE1 KVM" and "SPAPR TCE KVM".

And this 3rd type just offloads userspace by managing the iova window
allocations itself?  I would think this would be best to leave to a
userspace library and made easy to write by using consistent interfaces.
Thanks,

Alex

^ permalink raw reply

* [RFC][PATCH] perf: Add a few generic stalled-cycles events
From: Sukadev Bhattiprolu @ 2012-10-12  1:28 UTC (permalink / raw)
  To: acme, mingo, peterz, eranian, robert.richter, asharma
  Cc: mpjohn, Anton Blanchard, paulus, linux-kernel, linuxppc-dev


>From 89cb6a25b9f714e55a379467a832ee015014ed11 Mon Sep 17 00:00:00 2001
From: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Date: Tue, 18 Sep 2012 10:59:01 -0700
Subject: [PATCH] perf: Add a few generic stalled-cycles events

The existing generic event 'stalled-cycles-backend' corresponds to
PM_CMPLU_STALL event in Power7. While this event is useful, detailed
performance analysis often requires us to find more specific reasons
for the stalled cycle. For instance, stalled cycles in Power7 can
occur due to, among others:

	- instruction fetch unit (IFU),
	- Load-store-unit (LSU),
	- Fixed point unit (FXU)
	- Branch unit (BRU)

While it is possible to use raw codes to monitor these events, it quickly
becomes cumbersome with performance analysis frequently requiring mapping
the raw event codes in reports to their symbolic names.

This patch is a proposal to try and generalize such perf events. Since
the code changes are quite simple, I bunched all the 4 events together.

I am not familiar with how readily these events would map to other
architectures. Here is some information on the events for Power7:

	stalled-cycles-fixed-point (PM_CMPLU_STALL_FXU)

		Following a completion stall, the last instruction to finish
		before completion resumes was from the Fixed Point Unit.

		Completion stall is any period when no groups completed and
		the completion table was not empty for that thread.

	stalled-cycles-load-store (PM_CMPLU_STALL_LSU)

		Following a completion stall, the last instruction to finish
		before completion resumes was from the Load-Store Unit.

	stalled-cycles-instruction-fetch (PM_CMPLU_STALL_IFU)

		Following a completion stall, the last instruction to finish
		before completion resumes was from the Instruction Fetch Unit.

	stalled-cycles-branch (PM_CMPLU_STALL_BRU)

		Following a completion stall, the last instruction to finish
		before completion resumes was from the Branch Unit.

Looking for feedback on this approach and if this can be further extended.
Power7 has 530 events[2] out of which a "CPI stack analysis"[1] uses about 26
events.


[1] CPI Stack analysis
	https://www.power.org/documentation/commonly-used-metrics-for-performance-analysis

[2] Power7 events:
	https://www.power.org/documentation/comprehensive-pmu-event-reference-power7/

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
 arch/powerpc/perf/power7-pmu.c |    4 ++++
 include/linux/perf_event.h     |    4 ++++
 tools/perf/builtin-stat.c      |    4 ++++
 tools/perf/util/evsel.c        |    4 ++++
 tools/perf/util/parse-events.l |    4 ++++
 tools/perf/util/python.c       |    4 ++++
 6 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c
index 1251e4d..813e7c7 100644
--- a/arch/powerpc/perf/power7-pmu.c
+++ b/arch/powerpc/perf/power7-pmu.c
@@ -304,6 +304,10 @@ static int power7_generic_events[] = {
 	[PERF_COUNT_HW_CACHE_MISSES] = 0x400f0,		/* LD_MISS_L1	*/
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x10068,	/* BRU_FIN	*/
 	[PERF_COUNT_HW_BRANCH_MISSES] = 0x400f6,	/* BR_MPRED	*/
+	[PERF_COUNT_HW_STALLED_CYCLES_FIXED_POINT] = 0x20014,/* CMPLU_STALL_FXU */
+	[PERF_COUNT_HW_STALLED_CYCLES_LOAD_STORE] = 0x20012,/* CMPLU_STALL_LSU */
+	[PERF_COUNT_HW_STALLED_CYCLES_INSTRUCTION_FETCH] = 0x4004c,/* CMPLU_STALL_IFU */
+	[PERF_COUNT_HW_STALLED_CYCLES_BRANCH] = 0x4004e,/* CMPLU_STALL_BRU */
 };
 
 #define C(x)	PERF_COUNT_HW_CACHE_##x
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index bdb4161..ff9f0a6 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -55,6 +55,10 @@ enum perf_hw_id {
 	PERF_COUNT_HW_STALLED_CYCLES_FRONTEND	= 7,
 	PERF_COUNT_HW_STALLED_CYCLES_BACKEND	= 8,
 	PERF_COUNT_HW_REF_CPU_CYCLES		= 9,
+	PERF_COUNT_HW_STALLED_CYCLES_FIXED_POINT = 10,
+	PERF_COUNT_HW_STALLED_CYCLES_LOAD_STORE	= 11,
+	PERF_COUNT_HW_STALLED_CYCLES_INSTRUCTION_FETCH = 12,
+	PERF_COUNT_HW_STALLED_CYCLES_BRANCH	= 13,
 
 	PERF_COUNT_HW_MAX,			/* non-ABI */
 };
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 861f0ae..6275dbb 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -77,6 +77,10 @@ static struct perf_event_attr default_attrs[] = {
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS		},
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS	},
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES		},
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FIXED_POINT },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_LOAD_STORE },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_INSTRUCTION_FETCH },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BRANCH },
 
 };
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 2eaae14..17e3190 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -77,6 +77,10 @@ static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
 	"stalled-cycles-frontend",
 	"stalled-cycles-backend",
 	"ref-cycles",
+	"stalled-cycles-fixed-point",
+	"stalled-cycles-load-store",
+	"stalled-cycles-instruction-fetch",
+	"stalled-cycles-branch",
 };
 
 static const char *__perf_evsel__hw_name(u64 config)
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 384ca74..0c49c05 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -102,6 +102,10 @@ branch-instructions|branches			{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_
 branch-misses					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
 bus-cycles					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
 ref-cycles					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
+stalled-cycles-fixed-point			{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FIXED_POINT); }
+stalled-cycles-load-store			{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_LOAD_STORE); }
+stalled-cycles-instruction-fetch		{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_INSTRUCTION_FETCH); }
+stalled-cycles-branch				{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BRANCH); }
 cpu-clock					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
 task-clock					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
 page-faults|faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 0688bfb..c563b30 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -952,6 +952,10 @@ static struct {
 
 	{ "COUNT_HW_STALLED_CYCLES_FRONTEND",	  PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
 	{ "COUNT_HW_STALLED_CYCLES_BACKEND",	  PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
+	{ "COUNT_HW_STALLED_CYCLES_FIXED_POINT",  PERF_COUNT_HW_STALLED_CYCLES_FIXED_POINT },
+	{ "COUNT_HW_STALLED_CYCLES_LOAD_STORE",  PERF_COUNT_HW_STALLED_CYCLES_LOAD_STORE },
+	{ "COUNT_HW_STALLED_CYCLES_INSTRUCTION_FETCH",  PERF_COUNT_HW_STALLED_CYCLES_INSTRUCTION_FETCH },
+	{ "COUNT_HW_STALLED_CYCLES_BRANCH",  PERF_COUNT_HW_STALLED_CYCLES_BRANCH },
 
 	{ "COUNT_SW_CPU_CLOCK",	       PERF_COUNT_SW_CPU_CLOCK },
 	{ "COUNT_SW_TASK_CLOCK",       PERF_COUNT_SW_TASK_CLOCK },
-- 
1.7.1

^ permalink raw reply related

* linux-next: manual merge of the kvm-ppc tree with the kvm tree
From: Stephen Rothwell @ 2012-10-12  2:12 UTC (permalink / raw)
  To: Alexander Graf
  Cc: Marcelo Tosatti, linux-kernel, Avi Kivity, linux-next,
	Paul Mackerras, linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 671 bytes --]

Hi Alexander,

Today's linux-next merge of the kvm-ppc tree got a conflict in
arch/powerpc/kvm/44x_emulate.c between commits from the kvm tree and
the same patches plus another commit from the kvm-ppc tree.

I just used the kvm-ppc tree version.

This happened because
	1) you rebased/rewrote your tree before it was merged into the kvm tree
	2) left the old version in your kvm-ppc-next branch
	3) added some more commits to your kvm-ppc-next branch

Don't do that!

Unfortunately, the best thing you can do now is to rebase your
kvm-ppc-next branch on top of the kvm tree.  :-(

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Xilinx Temac
From: Guillaume Dargaud @ 2012-10-12 12:56 UTC (permalink / raw)
  To: linuxppc-dev

Hello all,
I'm upgrading the kernel on an embedded system and the network driver I 
was using seems to have changed and the new one doesn't seem to work:

My working config, from 2.6.38 (I believe):
$ grep "NET\|MII\|TEMAC\|MARVELL" ../linux-2.6-xlnx-CodalemaC/.config | 
grep -v "^#"
CONFIG_NET=y
CONFIG_INET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
CONFIG_NETDEVICES=y
CONFIG_NETDEV_1000=y
CONFIG_XILINX_LLTEMAC=y
CONFIG_XILINX_LLTEMAC_MARVELL_88E1111_MII=y
CONFIG_NET_DMA=y
CONFIG_NETWORK_FILESYSTEMS=y

And the new one:
$ grep "NET\|MII\|TEMAC\|MARVELL" .config | grep -v "^#"
CONFIG_NET=y
CONFIG_INET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
CONFIG_OF_NET=y
CONFIG_NETDEVICES=y
CONFIG_NET_CORE=y
CONFIG_ETHERNET=y
CONFIG_NET_VENDOR_MARVELL=y
CONFIG_NET_VENDOR_XILINX=y
CONFIG_XILINX_LL_TEMAC=y
CONFIG_NET_DMA=y

On boot the device gets probed, but not activated:
# dmesg | grep -i "net\|mac"
[    0.017515] NET: Registered protocol family 16
[    0.102621] device class 'net': registering
[    0.241017] NET: Registered protocol family 2
[    0.249435] NET: Registered protocol family 1
[    5.098813] device: 'xps-ll-temac.1': device_add
[    5.098984] bus: 'platform': add device xps-ll-temac.1
[    5.101050] device: '81880000.ethernet': device_add
[    5.101221] bus: 'platform': add device 81880000.ethernet
[    5.484077] bus: 'platform': add driver xilinx_temac
[    5.484491] bus: 'platform': driver_probe_device: matched device 
81880000.ethernet with driver xilinx_temac
[    5.484726] bus: 'platform': really_probe: probing driver 
xilinx_temac with device 81880000.ethernet
[    5.487175] Xilinx TEMAC MDIO: probed
[    5.495719] driver: '81880000.ethernet': driver_bound: bound to 
device 'xilinx_temac'
[    5.495827] bus: 'platform': really_probe: bound device 
81880000.ethernet to driver xilinx_temac
[    5.530592] NET: Registered protocol family 17

Is there something I'm missing about this LLTEMAC to LL_TEMAC change ?
Thanks
-- 
Guillaume Dargaud
http://www.gdargaud.net/

^ permalink raw reply

* [PATCH] powerpc, dma: move bestcomm driver from arch/powerpc/sysdev to drivers/dma
From: Philippe De Muyter @ 2012-10-12 14:32 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: Philippe De Muyter

The bestcomm dma hardware, and some of its users like the FEC ethernet
component, is used in different FreeScale parts, including non-powerpc
parts like the ColdFire MCF547x & MCF548x families.  Don't keep the
driver hidden in arch/powerpc where it is inaccessible for other arches.
.c files are moved to arch/drivers/dma/bestcomm, while
.h files are moved to include/linux/fsl/bestcomm.  Makefiles, Kconfigs
and #include directives are updated for the new file locations.

Tested by recompiling for MPC5200 with all bestcomm users enabled.

Signed-off-by: Philippe De Muyter <phdm@macqel.be>
---
 arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c      |    6 +-
 arch/powerpc/platforms/Kconfig                     |    2 -
 arch/powerpc/sysdev/Makefile                       |    1 -
 arch/powerpc/sysdev/bestcomm/Kconfig               |   36 --
 arch/powerpc/sysdev/bestcomm/Makefile              |   14 -
 arch/powerpc/sysdev/bestcomm/ata.c                 |  157 ------
 arch/powerpc/sysdev/bestcomm/ata.h                 |   30 --
 arch/powerpc/sysdev/bestcomm/bcom_ata_task.c       |   67 ---
 arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c    |   78 ---
 arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c    |   91 ----
 arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c |   63 ---
 arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c |   69 ---
 arch/powerpc/sysdev/bestcomm/bestcomm.c            |  532 --------------------
 arch/powerpc/sysdev/bestcomm/bestcomm.h            |  213 --------
 arch/powerpc/sysdev/bestcomm/bestcomm_priv.h       |  350 -------------
 arch/powerpc/sysdev/bestcomm/fec.c                 |  270 ----------
 arch/powerpc/sysdev/bestcomm/fec.h                 |   61 ---
 arch/powerpc/sysdev/bestcomm/gen_bd.c              |  354 -------------
 arch/powerpc/sysdev/bestcomm/gen_bd.h              |   53 --
 arch/powerpc/sysdev/bestcomm/sram.c                |  178 -------
 arch/powerpc/sysdev/bestcomm/sram.h                |   54 --
 drivers/Makefile                                   |    2 +-
 drivers/ata/pata_mpc52xx.c                         |    6 +-
 drivers/dma/Kconfig                                |    2 +
 drivers/dma/Makefile                               |    1 +
 drivers/dma/bestcomm/Kconfig                       |   36 ++
 drivers/dma/bestcomm/Makefile                      |   14 +
 drivers/dma/bestcomm/ata.c                         |  157 ++++++
 drivers/dma/bestcomm/bcom_ata_task.c               |   67 +++
 drivers/dma/bestcomm/bcom_fec_rx_task.c            |   78 +++
 drivers/dma/bestcomm/bcom_fec_tx_task.c            |   91 ++++
 drivers/dma/bestcomm/bcom_gen_bd_rx_task.c         |   63 +++
 drivers/dma/bestcomm/bcom_gen_bd_tx_task.c         |   69 +++
 drivers/dma/bestcomm/bestcomm.c                    |  532 ++++++++++++++++++++
 drivers/dma/bestcomm/fec.c                         |  270 ++++++++++
 drivers/dma/bestcomm/gen_bd.c                      |  354 +++++++++++++
 drivers/dma/bestcomm/sram.c                        |  178 +++++++
 drivers/net/ethernet/freescale/fec_mpc52xx.c       |    4 +-
 include/linux/fsl/bestcomm/ata.h                   |   30 ++
 include/linux/fsl/bestcomm/bestcomm.h              |  213 ++++++++
 include/linux/fsl/bestcomm/bestcomm_priv.h         |  350 +++++++++++++
 include/linux/fsl/bestcomm/fec.h                   |   61 +++
 include/linux/fsl/bestcomm/gen_bd.h                |   53 ++
 include/linux/fsl/bestcomm/sram.h                  |   54 ++
 sound/soc/fsl/mpc5200_dma.c                        |    4 +-
 45 files changed, 2684 insertions(+), 2684 deletions(-)
 delete mode 100644 arch/powerpc/sysdev/bestcomm/Kconfig
 delete mode 100644 arch/powerpc/sysdev/bestcomm/Makefile
 delete mode 100644 arch/powerpc/sysdev/bestcomm/ata.c
 delete mode 100644 arch/powerpc/sysdev/bestcomm/ata.h
 delete mode 100644 arch/powerpc/sysdev/bestcomm/bcom_ata_task.c
 delete mode 100644 arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c
 delete mode 100644 arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c
 delete mode 100644 arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c
 delete mode 100644 arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c
 delete mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm.c
 delete mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm.h
 delete mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
 delete mode 100644 arch/powerpc/sysdev/bestcomm/fec.c
 delete mode 100644 arch/powerpc/sysdev/bestcomm/fec.h
 delete mode 100644 arch/powerpc/sysdev/bestcomm/gen_bd.c
 delete mode 100644 arch/powerpc/sysdev/bestcomm/gen_bd.h
 delete mode 100644 arch/powerpc/sysdev/bestcomm/sram.c
 delete mode 100644 arch/powerpc/sysdev/bestcomm/sram.h
 create mode 100644 drivers/dma/bestcomm/Kconfig
 create mode 100644 drivers/dma/bestcomm/Makefile
 create mode 100644 drivers/dma/bestcomm/ata.c
 create mode 100644 drivers/dma/bestcomm/bcom_ata_task.c
 create mode 100644 drivers/dma/bestcomm/bcom_fec_rx_task.c
 create mode 100644 drivers/dma/bestcomm/bcom_fec_tx_task.c
 create mode 100644 drivers/dma/bestcomm/bcom_gen_bd_rx_task.c
 create mode 100644 drivers/dma/bestcomm/bcom_gen_bd_tx_task.c
 create mode 100644 drivers/dma/bestcomm/bestcomm.c
 create mode 100644 drivers/dma/bestcomm/fec.c
 create mode 100644 drivers/dma/bestcomm/gen_bd.c
 create mode 100644 drivers/dma/bestcomm/sram.c
 create mode 100644 include/linux/fsl/bestcomm/ata.h
 create mode 100644 include/linux/fsl/bestcomm/bestcomm.h
 create mode 100644 include/linux/fsl/bestcomm/bestcomm_priv.h
 create mode 100644 include/linux/fsl/bestcomm/fec.h
 create mode 100644 include/linux/fsl/bestcomm/gen_bd.h
 create mode 100644 include/linux/fsl/bestcomm/sram.h

diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
index 2351f9e..089e665 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
@@ -20,9 +20,9 @@
 #include <asm/mpc52xx.h>
 #include <asm/time.h>
 
-#include <sysdev/bestcomm/bestcomm.h>
-#include <sysdev/bestcomm/bestcomm_priv.h>
-#include <sysdev/bestcomm/gen_bd.h>
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/bestcomm_priv.h>
+#include <linux/fsl/bestcomm/gen_bd.h>
 
 MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
 MODULE_DESCRIPTION("MPC5200 LocalPlus FIFO device driver");
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index e7a896a..405f763 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -351,8 +351,6 @@ config OF_RTC
 	  Uses information from the OF or flattened device tree to instantiate
 	  platform devices for direct mapped RTC chips like the DS1742 or DS1743.
 
-source "arch/powerpc/sysdev/bestcomm/Kconfig"
-
 config SIMPLE_GPIO
 	bool "Support for simple, memory-mapped GPIO controllers"
 	depends on PPC
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index a57600b..3884776 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -26,7 +26,6 @@ obj-$(CONFIG_SIMPLE_GPIO)	+= simple_gpio.o
 obj-$(CONFIG_FSL_RIO)		+= fsl_rio.o fsl_rmu.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
-obj-$(CONFIG_PPC_BESTCOMM)	+= bestcomm/
 mv64x60-$(CONFIG_PCI)		+= mv64x60_pci.o
 obj-$(CONFIG_MV64X60)		+= $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o \
 				   mv64x60_udbg.o
diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/arch/powerpc/sysdev/bestcomm/Kconfig
deleted file mode 100644
index 29e4270..0000000
--- a/arch/powerpc/sysdev/bestcomm/Kconfig
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Kconfig options for Bestcomm
-#
-
-config PPC_BESTCOMM
-	tristate "Bestcomm DMA engine support"
-	depends on PPC_MPC52xx
-	default n
-	select PPC_LIB_RHEAP
-	help
-	  BestComm is the name of the communication coprocessor found
-	  on the Freescale MPC5200 family of processor.  Its usage is
-	  optional for some drivers (like ATA), but required for
-	  others (like FEC).
-
-	  If you want to use drivers that require DMA operations,
-	  answer Y or M. Otherwise say N.
-
-config PPC_BESTCOMM_ATA
-	tristate
-	depends on PPC_BESTCOMM
-	help
-	  This option enables the support for the ATA task.
-
-config PPC_BESTCOMM_FEC
-	tristate
-	depends on PPC_BESTCOMM
-	help
-	  This option enables the support for the FEC tasks.
-
-config PPC_BESTCOMM_GEN_BD
-	tristate
-	depends on PPC_BESTCOMM
-	help
-	  This option enables the support for the GenBD tasks.
-
diff --git a/arch/powerpc/sysdev/bestcomm/Makefile b/arch/powerpc/sysdev/bestcomm/Makefile
deleted file mode 100644
index aed2df2..0000000
--- a/arch/powerpc/sysdev/bestcomm/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile for BestComm & co
-#
-
-bestcomm-core-objs	:= bestcomm.o sram.o
-bestcomm-ata-objs	:= ata.o bcom_ata_task.o
-bestcomm-fec-objs	:= fec.o bcom_fec_rx_task.o bcom_fec_tx_task.o
-bestcomm-gen-bd-objs	:= gen_bd.o bcom_gen_bd_rx_task.o bcom_gen_bd_tx_task.o
-
-obj-$(CONFIG_PPC_BESTCOMM)		+= bestcomm-core.o
-obj-$(CONFIG_PPC_BESTCOMM_ATA)		+= bestcomm-ata.o
-obj-$(CONFIG_PPC_BESTCOMM_FEC)		+= bestcomm-fec.o
-obj-$(CONFIG_PPC_BESTCOMM_GEN_BD)	+= bestcomm-gen-bd.o
- 
diff --git a/arch/powerpc/sysdev/bestcomm/ata.c b/arch/powerpc/sysdev/bestcomm/ata.c
deleted file mode 100644
index 901c9f9..0000000
--- a/arch/powerpc/sysdev/bestcomm/ata.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Bestcomm ATA task driver
- *
- *
- * Patterned after bestcomm/fec.c by Dale Farnsworth <dfarnsworth@mvista.com>
- *                                   2003-2004 (c) MontaVista, Software, Inc.
- *
- * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2006      Freescale - John Rigby
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/io.h>
-
-#include "bestcomm.h"
-#include "bestcomm_priv.h"
-#include "ata.h"
-
-
-/* ======================================================================== */
-/* Task image/var/inc                                                       */
-/* ======================================================================== */
-
-/* ata task image */
-extern u32 bcom_ata_task[];
-
-/* ata task vars that need to be set before enabling the task */
-struct bcom_ata_var {
-	u32 enable;		/* (u16*) address of task's control register */
-	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
-	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
-	u32 bd_start;		/* (struct bcom_bd*) current bd */
-	u32 buffer_size;	/* size of receive buffer */
-};
-
-/* ata task incs that need to be set before enabling the task */
-struct bcom_ata_inc {
-	u16 pad0;
-	s16 incr_bytes;
-	u16 pad1;
-	s16 incr_dst;
-	u16 pad2;
-	s16 incr_src;
-};
-
-
-/* ======================================================================== */
-/* Task support code                                                        */
-/* ======================================================================== */
-
-struct bcom_task *
-bcom_ata_init(int queue_len, int maxbufsize)
-{
-	struct bcom_task *tsk;
-	struct bcom_ata_var *var;
-	struct bcom_ata_inc *inc;
-
-	/* Prefetch breaks ATA DMA.  Turn it off for ATA DMA */
-	bcom_disable_prefetch();
-
-	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_ata_bd), 0);
-	if (!tsk)
-		return NULL;
-
-	tsk->flags = BCOM_FLAGS_NONE;
-
-	bcom_ata_reset_bd(tsk);
-
-	var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum);
-	inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
-
-	if (bcom_load_image(tsk->tasknum, bcom_ata_task)) {
-		bcom_task_free(tsk);
-		return NULL;
-	}
-
-	var->enable	= bcom_eng->regs_base +
-				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
-	var->bd_base	= tsk->bd_pa;
-	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
-	var->bd_start	= tsk->bd_pa;
-	var->buffer_size = maxbufsize;
-
-	/* Configure some stuff */
-	bcom_set_task_pragma(tsk->tasknum, BCOM_ATA_PRAGMA);
-	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
-
-	out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ATA_RX], BCOM_IPR_ATA_RX);
-	out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ATA_TX], BCOM_IPR_ATA_TX);
-
-	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
-
-	return tsk;
-}
-EXPORT_SYMBOL_GPL(bcom_ata_init);
-
-void bcom_ata_rx_prepare(struct bcom_task *tsk)
-{
-	struct bcom_ata_inc *inc;
-
-	inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
-
-	inc->incr_bytes	= -(s16)sizeof(u32);
-	inc->incr_src	= 0;
-	inc->incr_dst	= sizeof(u32);
-
-	bcom_set_initiator(tsk->tasknum, BCOM_INITIATOR_ATA_RX);
-}
-EXPORT_SYMBOL_GPL(bcom_ata_rx_prepare);
-
-void bcom_ata_tx_prepare(struct bcom_task *tsk)
-{
-	struct bcom_ata_inc *inc;
-
-	inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
-
-	inc->incr_bytes	= -(s16)sizeof(u32);
-	inc->incr_src	= sizeof(u32);
-	inc->incr_dst	= 0;
-
-	bcom_set_initiator(tsk->tasknum, BCOM_INITIATOR_ATA_TX);
-}
-EXPORT_SYMBOL_GPL(bcom_ata_tx_prepare);
-
-void bcom_ata_reset_bd(struct bcom_task *tsk)
-{
-	struct bcom_ata_var *var;
-
-	/* Reset all BD */
-	memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
-
-	tsk->index = 0;
-	tsk->outdex = 0;
-
-	var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum);
-	var->bd_start = var->bd_base;
-}
-EXPORT_SYMBOL_GPL(bcom_ata_reset_bd);
-
-void bcom_ata_release(struct bcom_task *tsk)
-{
-	/* Nothing special for the ATA tasks */
-	bcom_task_free(tsk);
-}
-EXPORT_SYMBOL_GPL(bcom_ata_release);
-
-
-MODULE_DESCRIPTION("BestComm ATA task driver");
-MODULE_AUTHOR("John Rigby");
-MODULE_LICENSE("GPL v2");
-
diff --git a/arch/powerpc/sysdev/bestcomm/ata.h b/arch/powerpc/sysdev/bestcomm/ata.h
deleted file mode 100644
index 0b23718..0000000
--- a/arch/powerpc/sysdev/bestcomm/ata.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Header for Bestcomm ATA task driver
- *
- *
- * Copyright (C) 2006 Freescale - John Rigby
- * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#ifndef __BESTCOMM_ATA_H__
-#define __BESTCOMM_ATA_H__
-
-
-struct bcom_ata_bd {
-	u32	status;
-	u32	src_pa;
-	u32	dst_pa;
-};
-
-extern struct bcom_task * bcom_ata_init(int queue_len, int maxbufsize);
-extern void bcom_ata_rx_prepare(struct bcom_task *tsk);
-extern void bcom_ata_tx_prepare(struct bcom_task *tsk);
-extern void bcom_ata_reset_bd(struct bcom_task *tsk);
-extern void bcom_ata_release(struct bcom_task *tsk);
-
-#endif /* __BESTCOMM_ATA_H__ */
-
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_ata_task.c b/arch/powerpc/sysdev/bestcomm/bcom_ata_task.c
deleted file mode 100644
index cc6049a..0000000
--- a/arch/powerpc/sysdev/bestcomm/bcom_ata_task.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Bestcomm ATA task microcode
- *
- * Copyright (c) 2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * Created based on bestcom/code_dma/image_rtos1/dma_image.hex
- */
-
-#include <asm/types.h>
-
-/*
- * The header consists of the following fields:
- *	u32	magic;
- *	u8	desc_size;
- *	u8	var_size;
- *	u8	inc_size;
- *	u8	first_var;
- *	u8	reserved[8];
- *
- * The size fields contain the number of 32-bit words.
- */
-
-u32 bcom_ata_task[] = {
-	/* header */
-	0x4243544b,
-	0x0e060709,
-	0x00000000,
-	0x00000000,
-
-	/* Task descriptors */
-	0x8198009b, /* LCD: idx0 = var3; idx0 <= var2; idx0 += inc3 */
-	0x13e00c08, /*   DRD1A: var3 = var1; FN=0 MORE init=31 WS=0 RS=0 */
-	0xb8000264, /*   LCD: idx1 = *idx0, idx2 = var0; idx1 < var9; idx1 += inc4, idx2 += inc4 */
-	0x10000f00, /*     DRD1A: var3 = idx0; FN=0 MORE init=0 WS=0 RS=0 */
-	0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
-	0x0c8cfc8a, /*     DRD2B1: *idx2 = EU3(); EU3(*idx2,var10)  */
-	0xd8988240, /*   LCDEXT: idx1 = idx1; idx1 > var9; idx1 += inc0 */
-	0xf845e011, /*   LCDEXT: idx2 = *(idx0 + var00000015); ; idx2 += inc2 */
-	0xb845e00a, /*   LCD: idx3 = *(idx0 + var00000019); ; idx3 += inc1 */
-	0x0bfecf90, /*     DRD1A: *idx3 = *idx2; FN=0 TFD init=31 WS=3 RS=3 */
-	0x9898802d, /*   LCD: idx1 = idx1; idx1 once var0; idx1 += inc5 */
-	0x64000005, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 INT EXT init=0 WS=0 RS=0 */
-	0x0c0cf849, /*     DRD2B1: *idx0 = EU3(); EU3(idx1,var9)  */
-	0x000001f8, /* NOP */
-
-	/* VAR[9]-VAR[14] */
-	0x40000000,
-	0x7fff7fff,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-
-	/* INC[0]-INC[6] */
-	0x40000000,
-	0xe0000000,
-	0xe0000000,
-	0xa000000c,
-	0x20000000,
-	0x00000000,
-	0x00000000,
-};
-
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c
deleted file mode 100644
index a1ad6a0..0000000
--- a/arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Bestcomm FEC RX task microcode
- *
- * Copyright (c) 2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
- * on Tue Mar 22 11:19:38 2005 GMT
- */
-
-#include <asm/types.h>
-
-/*
- * The header consists of the following fields:
- *	u32	magic;
- *	u8	desc_size;
- *	u8	var_size;
- *	u8	inc_size;
- *	u8	first_var;
- *	u8	reserved[8];
- *
- * The size fields contain the number of 32-bit words.
- */
-
-u32 bcom_fec_rx_task[] = {
-	/* header */
-	0x4243544b,
-	0x18060709,
-	0x00000000,
-	0x00000000,
-
-	/* Task descriptors */
-	0x808220e3, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
-	0x10601010, /*   DRD1A: var4 = var2; FN=0 MORE init=3 WS=0 RS=0 */
-	0xb8800264, /*   LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc4, idx3 += inc4 */
-	0x10001308, /*     DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
-	0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
-	0x0cccfcca, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var10)  */
-	0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
-	0xb8c58029, /*   LCD: idx3 = *(idx1 + var00000015); idx3 once var0; idx3 += inc5 */
-	0x60000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=0 RS=0 */
-	0x088cf8cc, /*     DRD2B1: idx2 = EU3(); EU3(idx3,var12)  */
-	0x991982f2, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var11; idx2 += inc6, idx3 += inc2 */
-	0x006acf80, /*     DRD1A: *idx3 = *idx0; FN=0 init=3 WS=1 RS=1 */
-	0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
-	0x9999802d, /*   LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
-	0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
-	0x034cfc4e, /*     DRD2B1: var13 = EU3(); EU3(*idx1,var14)  */
-	0x00008868, /*     DRD1A: idx2 = var13; FN=0 init=0 WS=0 RS=0 */
-	0x99198341, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var13; idx2 += inc0, idx3 += inc1 */
-	0x007ecf80, /*     DRD1A: *idx3 = *idx0; FN=0 init=3 WS=3 RS=3 */
-	0x99198272, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc6, idx3 += inc2 */
-	0x046acf80, /*     DRD1A: *idx3 = *idx0; FN=0 INT init=3 WS=1 RS=1 */
-	0x9819002d, /*   LCD: idx2 = idx0; idx2 once var0; idx2 += inc5 */
-	0x0060c790, /*     DRD1A: *idx1 = *idx2; FN=0 init=3 WS=0 RS=0 */
-	0x000001f8, /*   NOP */
-
-	/* VAR[9]-VAR[14] */
-	0x40000000,
-	0x7fff7fff,
-	0x00000000,
-	0x00000003,
-	0x40000008,
-	0x43ffffff,
-
-	/* INC[0]-INC[6] */
-	0x40000000,
-	0xe0000000,
-	0xe0000000,
-	0xa0000008,
-	0x20000000,
-	0x00000000,
-	0x4000ffff,
-};
-
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c
deleted file mode 100644
index b1c495c..0000000
--- a/arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Bestcomm FEC TX task microcode
- *
- * Copyright (c) 2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
- * on Tue Mar 22 11:19:29 2005 GMT
- */
-
-#include <asm/types.h>
-
-/*
- * The header consists of the following fields:
- *	u32	magic;
- *	u8	desc_size;
- *	u8	var_size;
- *	u8	inc_size;
- *	u8	first_var;
- *	u8	reserved[8];
- *
- * The size fields contain the number of 32-bit words.
- */
-
-u32 bcom_fec_tx_task[] = {
-	/* header */
-	0x4243544b,
-	0x2407070d,
-	0x00000000,
-	0x00000000,
-
-	/* Task descriptors */
-	0x8018001b, /* LCD: idx0 = var0; idx0 <= var0; idx0 += inc3 */
-	0x60000005, /*   DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
-	0x01ccfc0d, /*   DRD2B1: var7 = EU3(); EU3(*idx0,var13)  */
-	0x8082a123, /* LCD: idx0 = var1, idx1 = var5; idx1 <= var4; idx0 += inc4, idx1 += inc3 */
-	0x10801418, /*   DRD1A: var5 = var3; FN=0 MORE init=4 WS=0 RS=0 */
-	0xf88103a4, /*   LCDEXT: idx2 = *idx1, idx3 = var2; idx2 < var14; idx2 += inc4, idx3 += inc4 */
-	0x801a6024, /*   LCD: idx4 = var0; ; idx4 += inc4 */
-	0x10001708, /*     DRD1A: var5 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
-	0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
-	0x0cccfccf, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var15)  */
-	0x991a002c, /*   LCD: idx2 = idx2, idx3 = idx4; idx2 once var0; idx2 += inc5, idx3 += inc4 */
-	0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
-	0x024cfc4d, /*     DRD2B1: var9 = EU3(); EU3(*idx1,var13)  */
-	0x60000003, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=3 EXT init=0 WS=0 RS=0 */
-	0x0cccf247, /*     DRD2B1: *idx3 = EU3(); EU3(var9,var7)  */
-	0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
-	0xb8c80029, /*   LCD: idx3 = *(idx1 + var0000001a); idx3 once var0; idx3 += inc5 */
-	0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
-	0x088cf8d1, /*     DRD2B1: idx2 = EU3(); EU3(idx3,var17)  */
-	0x00002f10, /*     DRD1A: var11 = idx2; FN=0 init=0 WS=0 RS=0 */
-	0x99198432, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var16; idx2 += inc6, idx3 += inc2 */
-	0x008ac398, /*     DRD1A: *idx0 = *idx3; FN=0 init=4 WS=1 RS=1 */
-	0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
-	0x9999802d, /*   LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
-	0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
-	0x048cfc53, /*     DRD2B1: var18 = EU3(); EU3(*idx1,var19)  */
-	0x60000008, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=8 EXT init=0 WS=0 RS=0 */
-	0x088cf48b, /*     DRD2B1: idx2 = EU3(); EU3(var18,var11)  */
-	0x99198481, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var18; idx2 += inc0, idx3 += inc1 */
-	0x009ec398, /*     DRD1A: *idx0 = *idx3; FN=0 init=4 WS=3 RS=3 */
-	0x991983b2, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var14; idx2 += inc6, idx3 += inc2 */
-	0x088ac398, /*     DRD1A: *idx0 = *idx3; FN=0 TFD init=4 WS=1 RS=1 */
-	0x9919002d, /*   LCD: idx2 = idx2; idx2 once var0; idx2 += inc5 */
-	0x60000005, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
-	0x0c4cf88e, /*     DRD2B1: *idx1 = EU3(); EU3(idx2,var14)  */
-	0x000001f8, /*   NOP */
-
-	/* VAR[13]-VAR[19] */
-	0x0c000000,
-	0x40000000,
-	0x7fff7fff,
-	0x00000000,
-	0x00000003,
-	0x40000004,
-	0x43ffffff,
-
-	/* INC[0]-INC[6] */
-	0x40000000,
-	0xe0000000,
-	0xe0000000,
-	0xa0000008,
-	0x20000000,
-	0x00000000,
-	0x4000ffff,
-};
-
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c
deleted file mode 100644
index efee022..0000000
--- a/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Bestcomm GenBD RX task microcode
- *
- * Copyright (C) 2006 AppSpec Computer Technologies Corp.
- *                    Jeff Gibbons <jeff.gibbons@appspec.com>
- * Copyright (c) 2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * Based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
- * on Tue Mar 4 10:14:12 2006 GMT
- *
- */
-
-#include <asm/types.h>
-
-/*
- * The header consists of the following fields:
- *	u32	magic;
- *	u8	desc_size;
- *	u8	var_size;
- *	u8	inc_size;
- *	u8	first_var;
- *	u8	reserved[8];
- *
- * The size fields contain the number of 32-bit words.
- */
-
-u32 bcom_gen_bd_rx_task[] = {
-	/* header */
-	0x4243544b,
-	0x0d020409,
-	0x00000000,
-	0x00000000,
-
-	/* Task descriptors */
-	0x808220da, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc3, idx1 += inc2 */
-	0x13e01010, /*   DRD1A: var4 = var2; FN=0 MORE init=31 WS=0 RS=0 */
-	0xb880025b, /*   LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc3, idx3 += inc3 */
-	0x10001308, /*     DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
-	0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
-	0x0cccfcca, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var10)  */
-	0xd9190240, /*   LCDEXT: idx2 = idx2; idx2 > var9; idx2 += inc0 */
-	0xb8c5e009, /*   LCD: idx3 = *(idx1 + var00000015); ; idx3 += inc1 */
-	0x07fecf80, /*     DRD1A: *idx3 = *idx0; FN=0 INT init=31 WS=3 RS=3 */
-	0x99190024, /*   LCD: idx2 = idx2; idx2 once var0; idx2 += inc4 */
-	0x60000005, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
-	0x0c4cf889, /*     DRD2B1: *idx1 = EU3(); EU3(idx2,var9)  */
-	0x000001f8, /*   NOP */
-
-	/* VAR[9]-VAR[10] */
-	0x40000000,
-	0x7fff7fff,
-
-	/* INC[0]-INC[3] */
-	0x40000000,
-	0xe0000000,
-	0xa0000008,
-	0x20000000,
-};
-
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c
deleted file mode 100644
index c605aa4..0000000
--- a/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Bestcomm GenBD TX task microcode
- *
- * Copyright (C) 2006 AppSpec Computer Technologies Corp.
- *                    Jeff Gibbons <jeff.gibbons@appspec.com>
- * Copyright (c) 2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * Based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
- * on Tue Mar 4 10:14:12 2006 GMT
- *
- */
-
-#include <asm/types.h>
-
-/*
- * The header consists of the following fields:
- *	u32	magic;
- *	u8	desc_size;
- *	u8	var_size;
- *	u8	inc_size;
- *	u8	first_var;
- *	u8	reserved[8];
- *
- * The size fields contain the number of 32-bit words.
- */
-
-u32 bcom_gen_bd_tx_task[] = {
-	/* header */
-	0x4243544b,
-	0x0f040609,
-	0x00000000,
-	0x00000000,
-
-	/* Task descriptors */
-	0x800220e3, /* LCD: idx0 = var0, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
-	0x13e01010, /*   DRD1A: var4 = var2; FN=0 MORE init=31 WS=0 RS=0 */
-	0xb8808264, /*   LCD: idx2 = *idx1, idx3 = var1; idx2 < var9; idx2 += inc4, idx3 += inc4 */
-	0x10001308, /*     DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
-	0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
-	0x0cccfcca, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var10)  */
-	0xd9190300, /*   LCDEXT: idx2 = idx2; idx2 > var12; idx2 += inc0 */
-	0xb8c5e009, /*   LCD: idx3 = *(idx1 + var00000015); ; idx3 += inc1 */
-	0x03fec398, /*     DRD1A: *idx0 = *idx3; FN=0 init=31 WS=3 RS=3 */
-	0x9919826a, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc5, idx3 += inc2 */
-	0x0feac398, /*     DRD1A: *idx0 = *idx3; FN=0 TFD INT init=31 WS=1 RS=1 */
-	0x99190036, /*   LCD: idx2 = idx2; idx2 once var0; idx2 += inc6 */
-	0x60000005, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
-	0x0c4cf889, /*     DRD2B1: *idx1 = EU3(); EU3(idx2,var9)  */
-	0x000001f8, /*   NOP */
-
-	/* VAR[9]-VAR[12] */
-	0x40000000,
-	0x7fff7fff,
-	0x00000000,
-	0x40000004,
-
-	/* INC[0]-INC[5] */
-	0x40000000,
-	0xe0000000,
-	0xe0000000,
-	0xa0000008,
-	0x20000000,
-	0x4000ffff,
-};
-
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c
deleted file mode 100644
index b3fbb27..0000000
--- a/arch/powerpc/sysdev/bestcomm/bestcomm.c
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * Driver for MPC52xx processor BestComm peripheral controller
- *
- *
- * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2005      Varma Electronics Oy,
- *                         ( by Andrey Volkov <avolkov@varma-el.com> )
- * Copyright (C) 2003-2004 MontaVista, Software, Inc.
- *                         ( by Dale Farnsworth <dfarnsworth@mvista.com> )
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mpc52xx.h>
-
-#include "sram.h"
-#include "bestcomm_priv.h"
-#include "bestcomm.h"
-
-#define DRIVER_NAME "bestcomm-core"
-
-/* MPC5200 device tree match tables */
-static struct of_device_id mpc52xx_sram_ids[] __devinitdata = {
-	{ .compatible = "fsl,mpc5200-sram", },
-	{ .compatible = "mpc5200-sram", },
-	{}
-};
-
-
-struct bcom_engine *bcom_eng = NULL;
-EXPORT_SYMBOL_GPL(bcom_eng);	/* needed for inline functions */
-
-/* ======================================================================== */
-/* Public and private API                                                   */
-/* ======================================================================== */
-
-/* Private API */
-
-struct bcom_task *
-bcom_task_alloc(int bd_count, int bd_size, int priv_size)
-{
-	int i, tasknum = -1;
-	struct bcom_task *tsk;
-
-	/* Don't try to do anything if bestcomm init failed */
-	if (!bcom_eng)
-		return NULL;
-
-	/* Get and reserve a task num */
-	spin_lock(&bcom_eng->lock);
-
-	for (i=0; i<BCOM_MAX_TASKS; i++)
-		if (!bcom_eng->tdt[i].stop) {	/* we use stop as a marker */
-			bcom_eng->tdt[i].stop = 0xfffffffful; /* dummy addr */
-			tasknum = i;
-			break;
-		}
-
-	spin_unlock(&bcom_eng->lock);
-
-	if (tasknum < 0)
-		return NULL;
-
-	/* Allocate our structure */
-	tsk = kzalloc(sizeof(struct bcom_task) + priv_size, GFP_KERNEL);
-	if (!tsk)
-		goto error;
-
-	tsk->tasknum = tasknum;
-	if (priv_size)
-		tsk->priv = (void*)tsk + sizeof(struct bcom_task);
-
-	/* Get IRQ of that task */
-	tsk->irq = irq_of_parse_and_map(bcom_eng->ofnode, tsk->tasknum);
-	if (tsk->irq == NO_IRQ)
-		goto error;
-
-	/* Init the BDs, if needed */
-	if (bd_count) {
-		tsk->cookie = kmalloc(sizeof(void*) * bd_count, GFP_KERNEL);
-		if (!tsk->cookie)
-			goto error;
-
-		tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa);
-		if (!tsk->bd)
-			goto error;
-		memset(tsk->bd, 0x00, bd_count * bd_size);
-
-		tsk->num_bd = bd_count;
-		tsk->bd_size = bd_size;
-	}
-
-	return tsk;
-
-error:
-	if (tsk) {
-		if (tsk->irq != NO_IRQ)
-			irq_dispose_mapping(tsk->irq);
-		bcom_sram_free(tsk->bd);
-		kfree(tsk->cookie);
-		kfree(tsk);
-	}
-
-	bcom_eng->tdt[tasknum].stop = 0;
-
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(bcom_task_alloc);
-
-void
-bcom_task_free(struct bcom_task *tsk)
-{
-	/* Stop the task */
-	bcom_disable_task(tsk->tasknum);
-
-	/* Clear TDT */
-	bcom_eng->tdt[tsk->tasknum].start = 0;
-	bcom_eng->tdt[tsk->tasknum].stop  = 0;
-
-	/* Free everything */
-	irq_dispose_mapping(tsk->irq);
-	bcom_sram_free(tsk->bd);
-	kfree(tsk->cookie);
-	kfree(tsk);
-}
-EXPORT_SYMBOL_GPL(bcom_task_free);
-
-int
-bcom_load_image(int task, u32 *task_image)
-{
-	struct bcom_task_header *hdr = (struct bcom_task_header *)task_image;
-	struct bcom_tdt *tdt;
-	u32 *desc, *var, *inc;
-	u32 *desc_src, *var_src, *inc_src;
-
-	/* Safety checks */
-	if (hdr->magic != BCOM_TASK_MAGIC) {
-		printk(KERN_ERR DRIVER_NAME
-			": Trying to load invalid microcode\n");
-		return -EINVAL;
-	}
-
-	if ((task < 0) || (task >= BCOM_MAX_TASKS)) {
-		printk(KERN_ERR DRIVER_NAME
-			": Trying to load invalid task %d\n", task);
-		return -EINVAL;
-	}
-
-	/* Initial load or reload */
-	tdt = &bcom_eng->tdt[task];
-
-	if (tdt->start) {
-		desc = bcom_task_desc(task);
-		if (hdr->desc_size != bcom_task_num_descs(task)) {
-			printk(KERN_ERR DRIVER_NAME
-				": Trying to reload wrong task image "
-				"(%d size %d/%d)!\n",
-				task,
-				hdr->desc_size,
-				bcom_task_num_descs(task));
-			return -EINVAL;
-		}
-	} else {
-		phys_addr_t start_pa;
-
-		desc = bcom_sram_alloc(hdr->desc_size * sizeof(u32), 4, &start_pa);
-		if (!desc)
-			return -ENOMEM;
-
-		tdt->start = start_pa;
-		tdt->stop = start_pa + ((hdr->desc_size-1) * sizeof(u32));
-	}
-
-	var = bcom_task_var(task);
-	inc = bcom_task_inc(task);
-
-	/* Clear & copy */
-	memset(var, 0x00, BCOM_VAR_SIZE);
-	memset(inc, 0x00, BCOM_INC_SIZE);
-
-	desc_src = (u32 *)(hdr + 1);
-	var_src = desc_src + hdr->desc_size;
-	inc_src = var_src + hdr->var_size;
-
-	memcpy(desc, desc_src, hdr->desc_size * sizeof(u32));
-	memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
-	memcpy(inc, inc_src, hdr->inc_size * sizeof(u32));
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(bcom_load_image);
-
-void
-bcom_set_initiator(int task, int initiator)
-{
-	int i;
-	int num_descs;
-	u32 *desc;
-	int next_drd_has_initiator;
-
-	bcom_set_tcr_initiator(task, initiator);
-
-	/* Just setting tcr is apparently not enough due to some problem */
-	/* with it. So we just go thru all the microcode and replace in  */
-	/* the DRD directly */
-
-	desc = bcom_task_desc(task);
-	next_drd_has_initiator = 1;
-	num_descs = bcom_task_num_descs(task);
-
-	for (i=0; i<num_descs; i++, desc++) {
-		if (!bcom_desc_is_drd(*desc))
-			continue;
-		if (next_drd_has_initiator)
-			if (bcom_desc_initiator(*desc) != BCOM_INITIATOR_ALWAYS)
-				bcom_set_desc_initiator(desc, initiator);
-		next_drd_has_initiator = !bcom_drd_is_extended(*desc);
-	}
-}
-EXPORT_SYMBOL_GPL(bcom_set_initiator);
-
-
-/* Public API */
-
-void
-bcom_enable(struct bcom_task *tsk)
-{
-	bcom_enable_task(tsk->tasknum);
-}
-EXPORT_SYMBOL_GPL(bcom_enable);
-
-void
-bcom_disable(struct bcom_task *tsk)
-{
-	bcom_disable_task(tsk->tasknum);
-}
-EXPORT_SYMBOL_GPL(bcom_disable);
-
-
-/* ======================================================================== */
-/* Engine init/cleanup                                                      */
-/* ======================================================================== */
-
-/* Function Descriptor table */
-/* this will need to be updated if Freescale changes their task code FDT */
-static u32 fdt_ops[] = {
-	0xa0045670,	/* FDT[48] - load_acc()	  */
-	0x80045670,	/* FDT[49] - unload_acc() */
-	0x21800000,	/* FDT[50] - and()        */
-	0x21e00000,	/* FDT[51] - or()         */
-	0x21500000,	/* FDT[52] - xor()        */
-	0x21400000,	/* FDT[53] - andn()       */
-	0x21500000,	/* FDT[54] - not()        */
-	0x20400000,	/* FDT[55] - add()        */
-	0x20500000,	/* FDT[56] - sub()        */
-	0x20800000,	/* FDT[57] - lsh()        */
-	0x20a00000,	/* FDT[58] - rsh()        */
-	0xc0170000,	/* FDT[59] - crc8()       */
-	0xc0145670,	/* FDT[60] - crc16()      */
-	0xc0345670,	/* FDT[61] - crc32()      */
-	0xa0076540,	/* FDT[62] - endian32()   */
-	0xa0000760,	/* FDT[63] - endian16()   */
-};
-
-
-static int __devinit
-bcom_engine_init(void)
-{
-	int task;
-	phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
-	unsigned int tdt_size, ctx_size, var_size, fdt_size;
-
-	/* Allocate & clear SRAM zones for FDT, TDTs, contexts and vars/incs */
-	tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt);
-	ctx_size = BCOM_MAX_TASKS * BCOM_CTX_SIZE;
-	var_size = BCOM_MAX_TASKS * (BCOM_VAR_SIZE + BCOM_INC_SIZE);
-	fdt_size = BCOM_FDT_SIZE;
-
-	bcom_eng->tdt = bcom_sram_alloc(tdt_size, sizeof(u32), &tdt_pa);
-	bcom_eng->ctx = bcom_sram_alloc(ctx_size, BCOM_CTX_ALIGN, &ctx_pa);
-	bcom_eng->var = bcom_sram_alloc(var_size, BCOM_VAR_ALIGN, &var_pa);
-	bcom_eng->fdt = bcom_sram_alloc(fdt_size, BCOM_FDT_ALIGN, &fdt_pa);
-
-	if (!bcom_eng->tdt || !bcom_eng->ctx || !bcom_eng->var || !bcom_eng->fdt) {
-		printk(KERN_ERR "DMA: SRAM alloc failed in engine init !\n");
-
-		bcom_sram_free(bcom_eng->tdt);
-		bcom_sram_free(bcom_eng->ctx);
-		bcom_sram_free(bcom_eng->var);
-		bcom_sram_free(bcom_eng->fdt);
-
-		return -ENOMEM;
-	}
-
-	memset(bcom_eng->tdt, 0x00, tdt_size);
-	memset(bcom_eng->ctx, 0x00, ctx_size);
-	memset(bcom_eng->var, 0x00, var_size);
-	memset(bcom_eng->fdt, 0x00, fdt_size);
-
-	/* Copy the FDT for the EU#3 */
-	memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
-
-	/* Initialize Task base structure */
-	for (task=0; task<BCOM_MAX_TASKS; task++)
-	{
-		out_be16(&bcom_eng->regs->tcr[task], 0);
-		out_8(&bcom_eng->regs->ipr[task], 0);
-
-		bcom_eng->tdt[task].context	= ctx_pa;
-		bcom_eng->tdt[task].var	= var_pa;
-		bcom_eng->tdt[task].fdt	= fdt_pa;
-
-		var_pa += BCOM_VAR_SIZE + BCOM_INC_SIZE;
-		ctx_pa += BCOM_CTX_SIZE;
-	}
-
-	out_be32(&bcom_eng->regs->taskBar, tdt_pa);
-
-	/* Init 'always' initiator */
-	out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
-
-	/* Disable COMM Bus Prefetch on the original 5200; it's broken */
-	if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR)
-		bcom_disable_prefetch();
-
-	/* Init lock */
-	spin_lock_init(&bcom_eng->lock);
-
-	return 0;
-}
-
-static void
-bcom_engine_cleanup(void)
-{
-	int task;
-
-	/* Stop all tasks */
-	for (task=0; task<BCOM_MAX_TASKS; task++)
-	{
-		out_be16(&bcom_eng->regs->tcr[task], 0);
-		out_8(&bcom_eng->regs->ipr[task], 0);
-	}
-
-	out_be32(&bcom_eng->regs->taskBar, 0ul);
-
-	/* Release the SRAM zones */
-	bcom_sram_free(bcom_eng->tdt);
-	bcom_sram_free(bcom_eng->ctx);
-	bcom_sram_free(bcom_eng->var);
-	bcom_sram_free(bcom_eng->fdt);
-}
-
-
-/* ======================================================================== */
-/* OF platform driver                                                       */
-/* ======================================================================== */
-
-static int __devinit mpc52xx_bcom_probe(struct platform_device *op)
-{
-	struct device_node *ofn_sram;
-	struct resource res_bcom;
-
-	int rv;
-
-	/* Inform user we're ok so far */
-	printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
-
-	/* Get the bestcomm node */
-	of_node_get(op->dev.of_node);
-
-	/* Prepare SRAM */
-	ofn_sram = of_find_matching_node(NULL, mpc52xx_sram_ids);
-	if (!ofn_sram) {
-		printk(KERN_ERR DRIVER_NAME ": "
-			"No SRAM found in device tree\n");
-		rv = -ENODEV;
-		goto error_ofput;
-	}
-	rv = bcom_sram_init(ofn_sram, DRIVER_NAME);
-	of_node_put(ofn_sram);
-
-	if (rv) {
-		printk(KERN_ERR DRIVER_NAME ": "
-			"Error in SRAM init\n");
-		goto error_ofput;
-	}
-
-	/* Get a clean struct */
-	bcom_eng = kzalloc(sizeof(struct bcom_engine), GFP_KERNEL);
-	if (!bcom_eng) {
-		printk(KERN_ERR DRIVER_NAME ": "
-			"Can't allocate state structure\n");
-		rv = -ENOMEM;
-		goto error_sramclean;
-	}
-
-	/* Save the node */
-	bcom_eng->ofnode = op->dev.of_node;
-
-	/* Get, reserve & map io */
-	if (of_address_to_resource(op->dev.of_node, 0, &res_bcom)) {
-		printk(KERN_ERR DRIVER_NAME ": "
-			"Can't get resource\n");
-		rv = -EINVAL;
-		goto error_sramclean;
-	}
-
-	if (!request_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma),
-				DRIVER_NAME)) {
-		printk(KERN_ERR DRIVER_NAME ": "
-			"Can't request registers region\n");
-		rv = -EBUSY;
-		goto error_sramclean;
-	}
-
-	bcom_eng->regs_base = res_bcom.start;
-	bcom_eng->regs = ioremap(res_bcom.start, sizeof(struct mpc52xx_sdma));
-	if (!bcom_eng->regs) {
-		printk(KERN_ERR DRIVER_NAME ": "
-			"Can't map registers\n");
-		rv = -ENOMEM;
-		goto error_release;
-	}
-
-	/* Now, do the real init */
-	rv = bcom_engine_init();
-	if (rv)
-		goto error_unmap;
-
-	/* Done ! */
-	printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n",
-		(long)bcom_eng->regs_base);
-
-	return 0;
-
-	/* Error path */
-error_unmap:
-	iounmap(bcom_eng->regs);
-error_release:
-	release_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma));
-error_sramclean:
-	kfree(bcom_eng);
-	bcom_sram_cleanup();
-error_ofput:
-	of_node_put(op->dev.of_node);
-
-	printk(KERN_ERR "DMA: MPC52xx BestComm init failed !\n");
-
-	return rv;
-}
-
-
-static int mpc52xx_bcom_remove(struct platform_device *op)
-{
-	/* Clean up the engine */
-	bcom_engine_cleanup();
-
-	/* Cleanup SRAM */
-	bcom_sram_cleanup();
-
-	/* Release regs */
-	iounmap(bcom_eng->regs);
-	release_mem_region(bcom_eng->regs_base, sizeof(struct mpc52xx_sdma));
-
-	/* Release the node */
-	of_node_put(bcom_eng->ofnode);
-
-	/* Release memory */
-	kfree(bcom_eng);
-	bcom_eng = NULL;
-
-	return 0;
-}
-
-static struct of_device_id mpc52xx_bcom_of_match[] = {
-	{ .compatible = "fsl,mpc5200-bestcomm", },
-	{ .compatible = "mpc5200-bestcomm", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
-
-
-static struct platform_driver mpc52xx_bcom_of_platform_driver = {
-	.probe		= mpc52xx_bcom_probe,
-	.remove		= mpc52xx_bcom_remove,
-	.driver = {
-		.name = DRIVER_NAME,
-		.owner = THIS_MODULE,
-		.of_match_table = mpc52xx_bcom_of_match,
-	},
-};
-
-
-/* ======================================================================== */
-/* Module                                                                   */
-/* ======================================================================== */
-
-static int __init
-mpc52xx_bcom_init(void)
-{
-	return platform_driver_register(&mpc52xx_bcom_of_platform_driver);
-}
-
-static void __exit
-mpc52xx_bcom_exit(void)
-{
-	platform_driver_unregister(&mpc52xx_bcom_of_platform_driver);
-}
-
-/* If we're not a module, we must make sure everything is setup before  */
-/* anyone tries to use us ... that's why we use subsys_initcall instead */
-/* of module_init. */
-subsys_initcall(mpc52xx_bcom_init);
-module_exit(mpc52xx_bcom_exit);
-
-MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
-MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
-MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
-MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
-MODULE_LICENSE("GPL v2");
-
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.h b/arch/powerpc/sysdev/bestcomm/bestcomm.h
deleted file mode 100644
index a0e2e6b..0000000
--- a/arch/powerpc/sysdev/bestcomm/bestcomm.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Public header for the MPC52xx processor BestComm driver
- *
- *
- * Copyright (C) 2006      Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2005      Varma Electronics Oy,
- *                         ( by Andrey Volkov <avolkov@varma-el.com> )
- * Copyright (C) 2003-2004 MontaVista, Software, Inc.
- *                         ( by Dale Farnsworth <dfarnsworth@mvista.com> )
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#ifndef __BESTCOMM_H__
-#define __BESTCOMM_H__
-
-/**
- * struct bcom_bd - Structure describing a generic BestComm buffer descriptor
- * @status: The current status of this buffer. Exact meaning depends on the
- *          task type
- * @data: An array of u32 extra data.  Size of array is task dependent.
- *
- * Note: Don't dereference a bcom_bd pointer as an array.  The size of the
- *       bcom_bd is variable.  Use bcom_get_bd() instead.
- */
-struct bcom_bd {
-	u32	status;
-	u32	data[0];	/* variable payload size */
-};
-
-/* ======================================================================== */
-/* Generic task management                                                   */
-/* ======================================================================== */
-
-/**
- * struct bcom_task - Structure describing a loaded BestComm task
- *
- * This structure is never built by the driver it self. It's built and
- * filled the intermediate layer of the BestComm API, the task dependent
- * support code.
- *
- * Most likely you don't need to poke around inside this structure. The
- * fields are exposed in the header just for the sake of inline functions
- */
-struct bcom_task {
-	unsigned int	tasknum;
-	unsigned int	flags;
-	int		irq;
-
-	struct bcom_bd	*bd;
-	phys_addr_t	bd_pa;
-	void		**cookie;
-	unsigned short	index;
-	unsigned short	outdex;
-	unsigned int	num_bd;
-	unsigned int	bd_size;
-
-	void*		priv;
-};
-
-#define BCOM_FLAGS_NONE         0x00000000ul
-#define BCOM_FLAGS_ENABLE_TASK  (1ul <<  0)
-
-/**
- * bcom_enable - Enable a BestComm task
- * @tsk: The BestComm task structure
- *
- * This function makes sure the given task is enabled and can be run
- * by the BestComm engine as needed
- */
-extern void bcom_enable(struct bcom_task *tsk);
-
-/**
- * bcom_disable - Disable a BestComm task
- * @tsk: The BestComm task structure
- *
- * This function disable a given task, making sure it's not executed
- * by the BestComm engine.
- */
-extern void bcom_disable(struct bcom_task *tsk);
-
-
-/**
- * bcom_get_task_irq - Returns the irq number of a BestComm task
- * @tsk: The BestComm task structure
- */
-static inline int
-bcom_get_task_irq(struct bcom_task *tsk) {
-	return tsk->irq;
-}
-
-/* ======================================================================== */
-/* BD based tasks helpers                                                   */
-/* ======================================================================== */
-
-#define BCOM_BD_READY	0x40000000ul
-
-/** _bcom_next_index - Get next input index.
- * @tsk: pointer to task structure
- *
- * Support function; Device drivers should not call this
- */
-static inline int
-_bcom_next_index(struct bcom_task *tsk)
-{
-	return ((tsk->index + 1) == tsk->num_bd) ? 0 : tsk->index + 1;
-}
-
-/** _bcom_next_outdex - Get next output index.
- * @tsk: pointer to task structure
- *
- * Support function; Device drivers should not call this
- */
-static inline int
-_bcom_next_outdex(struct bcom_task *tsk)
-{
-	return ((tsk->outdex + 1) == tsk->num_bd) ? 0 : tsk->outdex + 1;
-}
-
-/**
- * bcom_queue_empty - Checks if a BestComm task BD queue is empty
- * @tsk: The BestComm task structure
- */
-static inline int
-bcom_queue_empty(struct bcom_task *tsk)
-{
-	return tsk->index == tsk->outdex;
-}
-
-/**
- * bcom_queue_full - Checks if a BestComm task BD queue is full
- * @tsk: The BestComm task structure
- */
-static inline int
-bcom_queue_full(struct bcom_task *tsk)
-{
-	return tsk->outdex == _bcom_next_index(tsk);
-}
-
-/**
- * bcom_get_bd - Get a BD from the queue
- * @tsk: The BestComm task structure
- * index: Index of the BD to fetch
- */
-static inline struct bcom_bd
-*bcom_get_bd(struct bcom_task *tsk, unsigned int index)
-{
-	/* A cast to (void*) so the address can be incremented by the
-	 * real size instead of by sizeof(struct bcom_bd) */
-	return ((void *)tsk->bd) + (index * tsk->bd_size);
-}
-
-/**
- * bcom_buffer_done - Checks if a BestComm 
- * @tsk: The BestComm task structure
- */
-static inline int
-bcom_buffer_done(struct bcom_task *tsk)
-{
-	struct bcom_bd *bd;
-	if (bcom_queue_empty(tsk))
-		return 0;
-
-	bd = bcom_get_bd(tsk, tsk->outdex);
-	return !(bd->status & BCOM_BD_READY);
-}
-
-/**
- * bcom_prepare_next_buffer - clear status of next available buffer.
- * @tsk: The BestComm task structure
- *
- * Returns pointer to next buffer descriptor
- */
-static inline struct bcom_bd *
-bcom_prepare_next_buffer(struct bcom_task *tsk)
-{
-	struct bcom_bd *bd;
-
-	bd = bcom_get_bd(tsk, tsk->index);
-	bd->status = 0;	/* cleanup last status */
-	return bd;
-}
-
-static inline void
-bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie)
-{
-	struct bcom_bd *bd = bcom_get_bd(tsk, tsk->index);
-
-	tsk->cookie[tsk->index] = cookie;
-	mb();	/* ensure the bd is really up-to-date */
-	bd->status |= BCOM_BD_READY;
-	tsk->index = _bcom_next_index(tsk);
-	if (tsk->flags & BCOM_FLAGS_ENABLE_TASK)
-		bcom_enable(tsk);
-}
-
-static inline void *
-bcom_retrieve_buffer(struct bcom_task *tsk, u32 *p_status, struct bcom_bd **p_bd)
-{
-	void *cookie = tsk->cookie[tsk->outdex];
-	struct bcom_bd *bd = bcom_get_bd(tsk, tsk->outdex);
-
-	if (p_status)
-		*p_status = bd->status;
-	if (p_bd)
-		*p_bd = bd;
-	tsk->outdex = _bcom_next_outdex(tsk);
-	return cookie;
-}
-
-#endif /* __BESTCOMM_H__ */
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
deleted file mode 100644
index 3b52f3f..0000000
--- a/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Private header for the MPC52xx processor BestComm driver
- *
- * By private, we mean that driver should not use it directly. It's meant
- * to be used by the BestComm engine driver itself and by the intermediate
- * layer between the core and the drivers.
- *
- * Copyright (C) 2006      Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2005      Varma Electronics Oy,
- *                         ( by Andrey Volkov <avolkov@varma-el.com> )
- * Copyright (C) 2003-2004 MontaVista, Software, Inc.
- *                         ( by Dale Farnsworth <dfarnsworth@mvista.com> )
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#ifndef __BESTCOMM_PRIV_H__
-#define __BESTCOMM_PRIV_H__
-
-#include <linux/spinlock.h>
-#include <linux/of.h>
-#include <asm/io.h>
-#include <asm/mpc52xx.h>
-
-#include "sram.h"
-
-
-/* ======================================================================== */
-/* Engine related stuff                                                     */
-/* ======================================================================== */
-
-/* Zones sizes and needed alignments */
-#define BCOM_MAX_TASKS		16
-#define BCOM_MAX_VAR		24
-#define BCOM_MAX_INC		8
-#define BCOM_MAX_FDT		64
-#define BCOM_MAX_CTX		20
-#define BCOM_CTX_SIZE		(BCOM_MAX_CTX * sizeof(u32))
-#define BCOM_CTX_ALIGN		0x100
-#define BCOM_VAR_SIZE		(BCOM_MAX_VAR * sizeof(u32))
-#define BCOM_INC_SIZE		(BCOM_MAX_INC * sizeof(u32))
-#define BCOM_VAR_ALIGN		0x80
-#define BCOM_FDT_SIZE		(BCOM_MAX_FDT * sizeof(u32))
-#define BCOM_FDT_ALIGN		0x100
-
-/**
- * struct bcom_tdt - Task Descriptor Table Entry
- *
- */
-struct bcom_tdt {
-	u32 start;
-	u32 stop;
-	u32 var;
-	u32 fdt;
-	u32 exec_status;	/* used internally by BestComm engine */
-	u32 mvtp;		/* used internally by BestComm engine */
-	u32 context;
-	u32 litbase;
-};
-
-/**
- * struct bcom_engine
- *
- * This holds all info needed globaly to handle the engine
- */
-struct bcom_engine {
-	struct device_node		*ofnode;
-	struct mpc52xx_sdma __iomem     *regs;
-	phys_addr_t                      regs_base;
-
-	struct bcom_tdt			*tdt;
-	u32				*ctx;
-	u32				*var;
-	u32				*fdt;
-
-	spinlock_t			lock;
-};
-
-extern struct bcom_engine *bcom_eng;
-
-
-/* ======================================================================== */
-/* Tasks related stuff                                                      */
-/* ======================================================================== */
-
-/* Tasks image header */
-#define BCOM_TASK_MAGIC		0x4243544B	/* 'BCTK' */
-
-struct bcom_task_header {
-	u32	magic;
-	u8	desc_size;	/* the size fields     */
-	u8	var_size;	/* are given in number */
-	u8	inc_size;	/* of 32-bits words    */
-	u8	first_var;
-	u8	reserved[8];
-};
-
-/* Descriptors structure & co */
-#define BCOM_DESC_NOP		0x000001f8
-#define BCOM_LCD_MASK		0x80000000
-#define BCOM_DRD_EXTENDED	0x40000000
-#define BCOM_DRD_INITIATOR_SHIFT	21
-
-/* Tasks pragma */
-#define BCOM_PRAGMA_BIT_RSV		7	/* reserved pragma bit */
-#define BCOM_PRAGMA_BIT_PRECISE_INC	6	/* increment 0=when possible, */
-						/*           1=iter end */
-#define BCOM_PRAGMA_BIT_RST_ERROR_NO	5	/* don't reset errors on */
-						/* task enable */
-#define BCOM_PRAGMA_BIT_PACK		4	/* pack data enable */
-#define BCOM_PRAGMA_BIT_INTEGER		3	/* data alignment */
-						/* 0=frac(msb), 1=int(lsb) */
-#define BCOM_PRAGMA_BIT_SPECREAD	2	/* XLB speculative read */
-#define BCOM_PRAGMA_BIT_CW		1	/* write line buffer enable */
-#define BCOM_PRAGMA_BIT_RL		0	/* read line buffer enable */
-
-	/* Looks like XLB speculative read generates XLB errors when a buffer
-	 * is at the end of the physical memory. i.e. when accessing the
-	 * lasts words, the engine tries to prefetch the next but there is no
-	 * next ...
-	 */
-#define BCOM_STD_PRAGMA		((0 << BCOM_PRAGMA_BIT_RSV)		| \
-				 (0 << BCOM_PRAGMA_BIT_PRECISE_INC)	| \
-				 (0 << BCOM_PRAGMA_BIT_RST_ERROR_NO)	| \
-				 (0 << BCOM_PRAGMA_BIT_PACK)		| \
-				 (0 << BCOM_PRAGMA_BIT_INTEGER)		| \
-				 (0 << BCOM_PRAGMA_BIT_SPECREAD)	| \
-				 (1 << BCOM_PRAGMA_BIT_CW)		| \
-				 (1 << BCOM_PRAGMA_BIT_RL))
-
-#define BCOM_PCI_PRAGMA		((0 << BCOM_PRAGMA_BIT_RSV)		| \
-				 (0 << BCOM_PRAGMA_BIT_PRECISE_INC)	| \
-				 (0 << BCOM_PRAGMA_BIT_RST_ERROR_NO)	| \
-				 (0 << BCOM_PRAGMA_BIT_PACK)		| \
-				 (1 << BCOM_PRAGMA_BIT_INTEGER)		| \
-				 (0 << BCOM_PRAGMA_BIT_SPECREAD)	| \
-				 (1 << BCOM_PRAGMA_BIT_CW)		| \
-				 (1 << BCOM_PRAGMA_BIT_RL))
-
-#define BCOM_ATA_PRAGMA		BCOM_STD_PRAGMA
-#define BCOM_CRC16_DP_0_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_CRC16_DP_1_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_FEC_RX_BD_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_FEC_TX_BD_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_GEN_DP_0_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_GEN_DP_1_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_GEN_DP_2_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_GEN_DP_3_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_GEN_DP_BD_0_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_GEN_DP_BD_1_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_GEN_RX_BD_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_GEN_TX_BD_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_GEN_LPC_PRAGMA	BCOM_STD_PRAGMA
-#define BCOM_PCI_RX_PRAGMA	BCOM_PCI_PRAGMA
-#define BCOM_PCI_TX_PRAGMA	BCOM_PCI_PRAGMA
-
-/* Initiators number */
-#define BCOM_INITIATOR_ALWAYS	 0
-#define BCOM_INITIATOR_SCTMR_0	 1
-#define BCOM_INITIATOR_SCTMR_1	 2
-#define BCOM_INITIATOR_FEC_RX	 3
-#define BCOM_INITIATOR_FEC_TX	 4
-#define BCOM_INITIATOR_ATA_RX	 5
-#define BCOM_INITIATOR_ATA_TX	 6
-#define BCOM_INITIATOR_SCPCI_RX	 7
-#define BCOM_INITIATOR_SCPCI_TX	 8
-#define BCOM_INITIATOR_PSC3_RX	 9
-#define BCOM_INITIATOR_PSC3_TX	10
-#define BCOM_INITIATOR_PSC2_RX	11
-#define BCOM_INITIATOR_PSC2_TX	12
-#define BCOM_INITIATOR_PSC1_RX	13
-#define BCOM_INITIATOR_PSC1_TX	14
-#define BCOM_INITIATOR_SCTMR_2	15
-#define BCOM_INITIATOR_SCLPC	16
-#define BCOM_INITIATOR_PSC5_RX	17
-#define BCOM_INITIATOR_PSC5_TX	18
-#define BCOM_INITIATOR_PSC4_RX	19
-#define BCOM_INITIATOR_PSC4_TX	20
-#define BCOM_INITIATOR_I2C2_RX	21
-#define BCOM_INITIATOR_I2C2_TX	22
-#define BCOM_INITIATOR_I2C1_RX	23
-#define BCOM_INITIATOR_I2C1_TX	24
-#define BCOM_INITIATOR_PSC6_RX	25
-#define BCOM_INITIATOR_PSC6_TX	26
-#define BCOM_INITIATOR_IRDA_RX	25
-#define BCOM_INITIATOR_IRDA_TX	26
-#define BCOM_INITIATOR_SCTMR_3	27
-#define BCOM_INITIATOR_SCTMR_4	28
-#define BCOM_INITIATOR_SCTMR_5	29
-#define BCOM_INITIATOR_SCTMR_6	30
-#define BCOM_INITIATOR_SCTMR_7	31
-
-/* Initiators priorities */
-#define BCOM_IPR_ALWAYS		7
-#define BCOM_IPR_SCTMR_0	2
-#define BCOM_IPR_SCTMR_1	2
-#define BCOM_IPR_FEC_RX		6
-#define BCOM_IPR_FEC_TX		5
-#define BCOM_IPR_ATA_RX		7
-#define BCOM_IPR_ATA_TX		7
-#define BCOM_IPR_SCPCI_RX	2
-#define BCOM_IPR_SCPCI_TX	2
-#define BCOM_IPR_PSC3_RX	2
-#define BCOM_IPR_PSC3_TX	2
-#define BCOM_IPR_PSC2_RX	2
-#define BCOM_IPR_PSC2_TX	2
-#define BCOM_IPR_PSC1_RX	2
-#define BCOM_IPR_PSC1_TX	2
-#define BCOM_IPR_SCTMR_2	2
-#define BCOM_IPR_SCLPC		2
-#define BCOM_IPR_PSC5_RX	2
-#define BCOM_IPR_PSC5_TX	2
-#define BCOM_IPR_PSC4_RX	2
-#define BCOM_IPR_PSC4_TX	2
-#define BCOM_IPR_I2C2_RX	2
-#define BCOM_IPR_I2C2_TX	2
-#define BCOM_IPR_I2C1_RX	2
-#define BCOM_IPR_I2C1_TX	2
-#define BCOM_IPR_PSC6_RX	2
-#define BCOM_IPR_PSC6_TX	2
-#define BCOM_IPR_IRDA_RX	2
-#define BCOM_IPR_IRDA_TX	2
-#define BCOM_IPR_SCTMR_3	2
-#define BCOM_IPR_SCTMR_4	2
-#define BCOM_IPR_SCTMR_5	2
-#define BCOM_IPR_SCTMR_6	2
-#define BCOM_IPR_SCTMR_7	2
-
-
-/* ======================================================================== */
-/* API                                                                      */
-/* ======================================================================== */
-
-extern struct bcom_task *bcom_task_alloc(int bd_count, int bd_size, int priv_size);
-extern void bcom_task_free(struct bcom_task *tsk);
-extern int bcom_load_image(int task, u32 *task_image);
-extern void bcom_set_initiator(int task, int initiator);
-
-
-#define TASK_ENABLE             0x8000
-
-/**
- * bcom_disable_prefetch - Hook to disable bus prefetching
- *
- * ATA DMA and the original MPC5200 need this due to silicon bugs.  At the
- * moment disabling prefetch is a one-way street.  There is no mechanism
- * in place to turn prefetch back on after it has been disabled.  There is
- * no reason it couldn't be done, it would just be more complex to implement.
- */
-static inline void bcom_disable_prefetch(void)
-{
-	u16 regval;
-
-	regval = in_be16(&bcom_eng->regs->PtdCntrl);
-	out_be16(&bcom_eng->regs->PtdCntrl, regval | 1);
-};
-
-static inline void
-bcom_enable_task(int task)
-{
-        u16 reg;
-        reg = in_be16(&bcom_eng->regs->tcr[task]);
-        out_be16(&bcom_eng->regs->tcr[task],  reg | TASK_ENABLE);
-}
-
-static inline void
-bcom_disable_task(int task)
-{
-        u16 reg = in_be16(&bcom_eng->regs->tcr[task]);
-        out_be16(&bcom_eng->regs->tcr[task], reg & ~TASK_ENABLE);
-}
-
-
-static inline u32 *
-bcom_task_desc(int task)
-{
-	return bcom_sram_pa2va(bcom_eng->tdt[task].start);
-}
-
-static inline int
-bcom_task_num_descs(int task)
-{
-	return (bcom_eng->tdt[task].stop - bcom_eng->tdt[task].start)/sizeof(u32) + 1;
-}
-
-static inline u32 *
-bcom_task_var(int task)
-{
-	return bcom_sram_pa2va(bcom_eng->tdt[task].var);
-}
-
-static inline u32 *
-bcom_task_inc(int task)
-{
-	return &bcom_task_var(task)[BCOM_MAX_VAR];
-}
-
-
-static inline int
-bcom_drd_is_extended(u32 desc)
-{
-	return (desc) & BCOM_DRD_EXTENDED;
-}
-
-static inline int
-bcom_desc_is_drd(u32 desc)
-{
-	return !(desc & BCOM_LCD_MASK) && desc != BCOM_DESC_NOP;
-}
-
-static inline int
-bcom_desc_initiator(u32 desc)
-{
-	return (desc >> BCOM_DRD_INITIATOR_SHIFT) & 0x1f;
-}
-
-static inline void
-bcom_set_desc_initiator(u32 *desc, int initiator)
-{
-	*desc = (*desc & ~(0x1f << BCOM_DRD_INITIATOR_SHIFT)) |
-			((initiator & 0x1f) << BCOM_DRD_INITIATOR_SHIFT);
-}
-
-
-static inline void
-bcom_set_task_pragma(int task, int pragma)
-{
-	u32 *fdt = &bcom_eng->tdt[task].fdt;
-	*fdt = (*fdt & ~0xff) | pragma;
-}
-
-static inline void
-bcom_set_task_auto_start(int task, int next_task)
-{
-	u16 __iomem *tcr = &bcom_eng->regs->tcr[task];
-	out_be16(tcr, (in_be16(tcr) & ~0xff) | 0x00c0 | next_task);
-}
-
-static inline void
-bcom_set_tcr_initiator(int task, int initiator)
-{
-	u16 __iomem *tcr = &bcom_eng->regs->tcr[task];
-	out_be16(tcr, (in_be16(tcr) & ~0x1f00) | ((initiator & 0x1f) << 8));
-}
-
-
-#endif /* __BESTCOMM_PRIV_H__ */
-
diff --git a/arch/powerpc/sysdev/bestcomm/fec.c b/arch/powerpc/sysdev/bestcomm/fec.c
deleted file mode 100644
index 957a988..0000000
--- a/arch/powerpc/sysdev/bestcomm/fec.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Bestcomm FEC tasks driver
- *
- *
- * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2003-2004 MontaVista, Software, Inc.
- *                         ( by Dale Farnsworth <dfarnsworth@mvista.com> )
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/io.h>
-
-#include "bestcomm.h"
-#include "bestcomm_priv.h"
-#include "fec.h"
-
-
-/* ======================================================================== */
-/* Task image/var/inc                                                       */
-/* ======================================================================== */
-
-/* fec tasks images */
-extern u32 bcom_fec_rx_task[];
-extern u32 bcom_fec_tx_task[];
-
-/* rx task vars that need to be set before enabling the task */
-struct bcom_fec_rx_var {
-	u32 enable;		/* (u16*) address of task's control register */
-	u32 fifo;		/* (u32*) address of fec's fifo */
-	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
-	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
-	u32 bd_start;		/* (struct bcom_bd*) current bd */
-	u32 buffer_size;	/* size of receive buffer */
-};
-
-/* rx task incs that need to be set before enabling the task */
-struct bcom_fec_rx_inc {
-	u16 pad0;
-	s16 incr_bytes;
-	u16 pad1;
-	s16 incr_dst;
-	u16 pad2;
-	s16 incr_dst_ma;
-};
-
-/* tx task vars that need to be set before enabling the task */
-struct bcom_fec_tx_var {
-	u32 DRD;		/* (u32*) address of self-modified DRD */
-	u32 fifo;		/* (u32*) address of fec's fifo */
-	u32 enable;		/* (u16*) address of task's control register */
-	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
-	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
-	u32 bd_start;		/* (struct bcom_bd*) current bd */
-	u32 buffer_size;	/* set by uCode for each packet */
-};
-
-/* tx task incs that need to be set before enabling the task */
-struct bcom_fec_tx_inc {
-	u16 pad0;
-	s16 incr_bytes;
-	u16 pad1;
-	s16 incr_src;
-	u16 pad2;
-	s16 incr_src_ma;
-};
-
-/* private structure in the task */
-struct bcom_fec_priv {
-	phys_addr_t	fifo;
-	int		maxbufsize;
-};
-
-
-/* ======================================================================== */
-/* Task support code                                                        */
-/* ======================================================================== */
-
-struct bcom_task *
-bcom_fec_rx_init(int queue_len, phys_addr_t fifo, int maxbufsize)
-{
-	struct bcom_task *tsk;
-	struct bcom_fec_priv *priv;
-
-	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_fec_bd),
-				sizeof(struct bcom_fec_priv));
-	if (!tsk)
-		return NULL;
-
-	tsk->flags = BCOM_FLAGS_NONE;
-
-	priv = tsk->priv;
-	priv->fifo = fifo;
-	priv->maxbufsize = maxbufsize;
-
-	if (bcom_fec_rx_reset(tsk)) {
-		bcom_task_free(tsk);
-		return NULL;
-	}
-
-	return tsk;
-}
-EXPORT_SYMBOL_GPL(bcom_fec_rx_init);
-
-int
-bcom_fec_rx_reset(struct bcom_task *tsk)
-{
-	struct bcom_fec_priv *priv = tsk->priv;
-	struct bcom_fec_rx_var *var;
-	struct bcom_fec_rx_inc *inc;
-
-	/* Shutdown the task */
-	bcom_disable_task(tsk->tasknum);
-
-	/* Reset the microcode */
-	var = (struct bcom_fec_rx_var *) bcom_task_var(tsk->tasknum);
-	inc = (struct bcom_fec_rx_inc *) bcom_task_inc(tsk->tasknum);
-
-	if (bcom_load_image(tsk->tasknum, bcom_fec_rx_task))
-		return -1;
-
-	var->enable	= bcom_eng->regs_base +
-				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
-	var->fifo	= (u32) priv->fifo;
-	var->bd_base	= tsk->bd_pa;
-	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
-	var->bd_start	= tsk->bd_pa;
-	var->buffer_size = priv->maxbufsize;
-
-	inc->incr_bytes	= -(s16)sizeof(u32);	/* These should be in the   */
-	inc->incr_dst	= sizeof(u32);		/* task image, but we stick */
-	inc->incr_dst_ma= sizeof(u8);		/* to the official ones     */
-
-	/* Reset the BDs */
-	tsk->index = 0;
-	tsk->outdex = 0;
-
-	memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
-
-	/* Configure some stuff */
-	bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_RX_BD_PRAGMA);
-	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
-
-	out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_FEC_RX], BCOM_IPR_FEC_RX);
-
-	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(bcom_fec_rx_reset);
-
-void
-bcom_fec_rx_release(struct bcom_task *tsk)
-{
-	/* Nothing special for the FEC tasks */
-	bcom_task_free(tsk);
-}
-EXPORT_SYMBOL_GPL(bcom_fec_rx_release);
-
-
-
-	/* Return 2nd to last DRD */
-	/* This is an ugly hack, but at least it's only done
-	   once at initialization */
-static u32 *self_modified_drd(int tasknum)
-{
-	u32 *desc;
-	int num_descs;
-	int drd_count;
-	int i;
-
-	num_descs = bcom_task_num_descs(tasknum);
-	desc = bcom_task_desc(tasknum) + num_descs - 1;
-	drd_count = 0;
-	for (i=0; i<num_descs; i++, desc--)
-		if (bcom_desc_is_drd(*desc) && ++drd_count == 3)
-			break;
-	return desc;
-}
-
-struct bcom_task *
-bcom_fec_tx_init(int queue_len, phys_addr_t fifo)
-{
-	struct bcom_task *tsk;
-	struct bcom_fec_priv *priv;
-
-	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_fec_bd),
-				sizeof(struct bcom_fec_priv));
-	if (!tsk)
-		return NULL;
-
-	tsk->flags = BCOM_FLAGS_ENABLE_TASK;
-
-	priv = tsk->priv;
-	priv->fifo = fifo;
-
-	if (bcom_fec_tx_reset(tsk)) {
-		bcom_task_free(tsk);
-		return NULL;
-	}
-
-	return tsk;
-}
-EXPORT_SYMBOL_GPL(bcom_fec_tx_init);
-
-int
-bcom_fec_tx_reset(struct bcom_task *tsk)
-{
-	struct bcom_fec_priv *priv = tsk->priv;
-	struct bcom_fec_tx_var *var;
-	struct bcom_fec_tx_inc *inc;
-
-	/* Shutdown the task */
-	bcom_disable_task(tsk->tasknum);
-
-	/* Reset the microcode */
-	var = (struct bcom_fec_tx_var *) bcom_task_var(tsk->tasknum);
-	inc = (struct bcom_fec_tx_inc *) bcom_task_inc(tsk->tasknum);
-
-	if (bcom_load_image(tsk->tasknum, bcom_fec_tx_task))
-		return -1;
-
-	var->enable	= bcom_eng->regs_base +
-				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
-	var->fifo	= (u32) priv->fifo;
-	var->DRD	= bcom_sram_va2pa(self_modified_drd(tsk->tasknum));
-	var->bd_base	= tsk->bd_pa;
-	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
-	var->bd_start	= tsk->bd_pa;
-
-	inc->incr_bytes	= -(s16)sizeof(u32);	/* These should be in the   */
-	inc->incr_src	= sizeof(u32);		/* task image, but we stick */
-	inc->incr_src_ma= sizeof(u8);		/* to the official ones     */
-
-	/* Reset the BDs */
-	tsk->index = 0;
-	tsk->outdex = 0;
-
-	memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
-
-	/* Configure some stuff */
-	bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_TX_BD_PRAGMA);
-	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
-
-	out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_FEC_TX], BCOM_IPR_FEC_TX);
-
-	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(bcom_fec_tx_reset);
-
-void
-bcom_fec_tx_release(struct bcom_task *tsk)
-{
-	/* Nothing special for the FEC tasks */
-	bcom_task_free(tsk);
-}
-EXPORT_SYMBOL_GPL(bcom_fec_tx_release);
-
-
-MODULE_DESCRIPTION("BestComm FEC tasks driver");
-MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
-MODULE_LICENSE("GPL v2");
-
diff --git a/arch/powerpc/sysdev/bestcomm/fec.h b/arch/powerpc/sysdev/bestcomm/fec.h
deleted file mode 100644
index ee565d9..0000000
--- a/arch/powerpc/sysdev/bestcomm/fec.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Header for Bestcomm FEC tasks driver
- *
- *
- * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2003-2004 MontaVista, Software, Inc.
- *                         ( by Dale Farnsworth <dfarnsworth@mvista.com> )
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#ifndef __BESTCOMM_FEC_H__
-#define __BESTCOMM_FEC_H__
-
-
-struct bcom_fec_bd {
-	u32	status;
-	u32	skb_pa;
-};
-
-#define BCOM_FEC_TX_BD_TFD	0x08000000ul	/* transmit frame done */
-#define BCOM_FEC_TX_BD_TC	0x04000000ul	/* transmit CRC */
-#define BCOM_FEC_TX_BD_ABC	0x02000000ul	/* append bad CRC */
-
-#define BCOM_FEC_RX_BD_L	0x08000000ul	/* buffer is last in frame */
-#define BCOM_FEC_RX_BD_BC	0x00800000ul	/* DA is broadcast */
-#define BCOM_FEC_RX_BD_MC	0x00400000ul	/* DA is multicast and not broadcast */
-#define BCOM_FEC_RX_BD_LG	0x00200000ul	/* Rx frame length violation */
-#define BCOM_FEC_RX_BD_NO	0x00100000ul	/* Rx non-octet aligned frame */
-#define BCOM_FEC_RX_BD_CR	0x00040000ul	/* Rx CRC error */
-#define BCOM_FEC_RX_BD_OV	0x00020000ul	/* overrun */
-#define BCOM_FEC_RX_BD_TR	0x00010000ul	/* Rx frame truncated */
-#define BCOM_FEC_RX_BD_LEN_MASK	0x000007fful	/* mask for length of received frame */
-#define BCOM_FEC_RX_BD_ERRORS	(BCOM_FEC_RX_BD_LG | BCOM_FEC_RX_BD_NO | \
-		BCOM_FEC_RX_BD_CR | BCOM_FEC_RX_BD_OV | BCOM_FEC_RX_BD_TR)
-
-
-extern struct bcom_task *
-bcom_fec_rx_init(int queue_len, phys_addr_t fifo, int maxbufsize);
-
-extern int
-bcom_fec_rx_reset(struct bcom_task *tsk);
-
-extern void
-bcom_fec_rx_release(struct bcom_task *tsk);
-
-
-extern struct bcom_task *
-bcom_fec_tx_init(int queue_len, phys_addr_t fifo);
-
-extern int
-bcom_fec_tx_reset(struct bcom_task *tsk);
-
-extern void
-bcom_fec_tx_release(struct bcom_task *tsk);
-
-
-#endif /* __BESTCOMM_FEC_H__ */
-
diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.c b/arch/powerpc/sysdev/bestcomm/gen_bd.c
deleted file mode 100644
index e0a53e3..0000000
--- a/arch/powerpc/sysdev/bestcomm/gen_bd.c
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Driver for MPC52xx processor BestComm General Buffer Descriptor
- *
- * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2006 AppSpec Computer Technologies Corp.
- *                    Jeff Gibbons <jeff.gibbons@appspec.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-
-#include <asm/mpc52xx.h>
-#include <asm/mpc52xx_psc.h>
-
-#include "bestcomm.h"
-#include "bestcomm_priv.h"
-#include "gen_bd.h"
-
-
-/* ======================================================================== */
-/* Task image/var/inc                                                       */
-/* ======================================================================== */
-
-/* gen_bd tasks images */
-extern u32 bcom_gen_bd_rx_task[];
-extern u32 bcom_gen_bd_tx_task[];
-
-/* rx task vars that need to be set before enabling the task */
-struct bcom_gen_bd_rx_var {
-	u32 enable;		/* (u16*) address of task's control register */
-	u32 fifo;		/* (u32*) address of gen_bd's fifo */
-	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
-	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
-	u32 bd_start;		/* (struct bcom_bd*) current bd */
-	u32 buffer_size;	/* size of receive buffer */
-};
-
-/* rx task incs that need to be set before enabling the task */
-struct bcom_gen_bd_rx_inc {
-	u16 pad0;
-	s16 incr_bytes;
-	u16 pad1;
-	s16 incr_dst;
-};
-
-/* tx task vars that need to be set before enabling the task */
-struct bcom_gen_bd_tx_var {
-	u32 fifo;		/* (u32*) address of gen_bd's fifo */
-	u32 enable;		/* (u16*) address of task's control register */
-	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
-	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
-	u32 bd_start;		/* (struct bcom_bd*) current bd */
-	u32 buffer_size;	/* set by uCode for each packet */
-};
-
-/* tx task incs that need to be set before enabling the task */
-struct bcom_gen_bd_tx_inc {
-	u16 pad0;
-	s16 incr_bytes;
-	u16 pad1;
-	s16 incr_src;
-	u16 pad2;
-	s16 incr_src_ma;
-};
-
-/* private structure */
-struct bcom_gen_bd_priv {
-	phys_addr_t	fifo;
-	int		initiator;
-	int		ipr;
-	int		maxbufsize;
-};
-
-
-/* ======================================================================== */
-/* Task support code                                                        */
-/* ======================================================================== */
-
-struct bcom_task *
-bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
-			int initiator, int ipr, int maxbufsize)
-{
-	struct bcom_task *tsk;
-	struct bcom_gen_bd_priv *priv;
-
-	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
-			sizeof(struct bcom_gen_bd_priv));
-	if (!tsk)
-		return NULL;
-
-	tsk->flags = BCOM_FLAGS_NONE;
-
-	priv = tsk->priv;
-	priv->fifo	= fifo;
-	priv->initiator	= initiator;
-	priv->ipr	= ipr;
-	priv->maxbufsize = maxbufsize;
-
-	if (bcom_gen_bd_rx_reset(tsk)) {
-		bcom_task_free(tsk);
-		return NULL;
-	}
-
-	return tsk;
-}
-EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_init);
-
-int
-bcom_gen_bd_rx_reset(struct bcom_task *tsk)
-{
-	struct bcom_gen_bd_priv *priv = tsk->priv;
-	struct bcom_gen_bd_rx_var *var;
-	struct bcom_gen_bd_rx_inc *inc;
-
-	/* Shutdown the task */
-	bcom_disable_task(tsk->tasknum);
-
-	/* Reset the microcode */
-	var = (struct bcom_gen_bd_rx_var *) bcom_task_var(tsk->tasknum);
-	inc = (struct bcom_gen_bd_rx_inc *) bcom_task_inc(tsk->tasknum);
-
-	if (bcom_load_image(tsk->tasknum, bcom_gen_bd_rx_task))
-		return -1;
-
-	var->enable	= bcom_eng->regs_base +
-				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
-	var->fifo	= (u32) priv->fifo;
-	var->bd_base	= tsk->bd_pa;
-	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
-	var->bd_start	= tsk->bd_pa;
-	var->buffer_size = priv->maxbufsize;
-
-	inc->incr_bytes	= -(s16)sizeof(u32);
-	inc->incr_dst	= sizeof(u32);
-
-	/* Reset the BDs */
-	tsk->index = 0;
-	tsk->outdex = 0;
-
-	memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
-
-	/* Configure some stuff */
-	bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA);
-	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
-
-	out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
-	bcom_set_initiator(tsk->tasknum, priv->initiator);
-
-	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_reset);
-
-void
-bcom_gen_bd_rx_release(struct bcom_task *tsk)
-{
-	/* Nothing special for the GenBD tasks */
-	bcom_task_free(tsk);
-}
-EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_release);
-
-
-extern struct bcom_task *
-bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
-			int initiator, int ipr)
-{
-	struct bcom_task *tsk;
-	struct bcom_gen_bd_priv *priv;
-
-	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
-			sizeof(struct bcom_gen_bd_priv));
-	if (!tsk)
-		return NULL;
-
-	tsk->flags = BCOM_FLAGS_NONE;
-
-	priv = tsk->priv;
-	priv->fifo	= fifo;
-	priv->initiator	= initiator;
-	priv->ipr	= ipr;
-
-	if (bcom_gen_bd_tx_reset(tsk)) {
-		bcom_task_free(tsk);
-		return NULL;
-	}
-
-	return tsk;
-}
-EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_init);
-
-int
-bcom_gen_bd_tx_reset(struct bcom_task *tsk)
-{
-	struct bcom_gen_bd_priv *priv = tsk->priv;
-	struct bcom_gen_bd_tx_var *var;
-	struct bcom_gen_bd_tx_inc *inc;
-
-	/* Shutdown the task */
-	bcom_disable_task(tsk->tasknum);
-
-	/* Reset the microcode */
-	var = (struct bcom_gen_bd_tx_var *) bcom_task_var(tsk->tasknum);
-	inc = (struct bcom_gen_bd_tx_inc *) bcom_task_inc(tsk->tasknum);
-
-	if (bcom_load_image(tsk->tasknum, bcom_gen_bd_tx_task))
-		return -1;
-
-	var->enable	= bcom_eng->regs_base +
-				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
-	var->fifo	= (u32) priv->fifo;
-	var->bd_base	= tsk->bd_pa;
-	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
-	var->bd_start	= tsk->bd_pa;
-
-	inc->incr_bytes	= -(s16)sizeof(u32);
-	inc->incr_src	= sizeof(u32);
-	inc->incr_src_ma = sizeof(u8);
-
-	/* Reset the BDs */
-	tsk->index = 0;
-	tsk->outdex = 0;
-
-	memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
-
-	/* Configure some stuff */
-	bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA);
-	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
-
-	out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
-	bcom_set_initiator(tsk->tasknum, priv->initiator);
-
-	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_reset);
-
-void
-bcom_gen_bd_tx_release(struct bcom_task *tsk)
-{
-	/* Nothing special for the GenBD tasks */
-	bcom_task_free(tsk);
-}
-EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release);
-
-/* ---------------------------------------------------------------------
- * PSC support code
- */
-
-/**
- * bcom_psc_parameters - Bestcomm initialization value table for PSC devices
- *
- * This structure is only used internally.  It is a lookup table for PSC
- * specific parameters to bestcomm tasks.
- */
-static struct bcom_psc_params {
-	int rx_initiator;
-	int rx_ipr;
-	int tx_initiator;
-	int tx_ipr;
-} bcom_psc_params[] = {
-	[0] = {
-		.rx_initiator = BCOM_INITIATOR_PSC1_RX,
-		.rx_ipr = BCOM_IPR_PSC1_RX,
-		.tx_initiator = BCOM_INITIATOR_PSC1_TX,
-		.tx_ipr = BCOM_IPR_PSC1_TX,
-	},
-	[1] = {
-		.rx_initiator = BCOM_INITIATOR_PSC2_RX,
-		.rx_ipr = BCOM_IPR_PSC2_RX,
-		.tx_initiator = BCOM_INITIATOR_PSC2_TX,
-		.tx_ipr = BCOM_IPR_PSC2_TX,
-	},
-	[2] = {
-		.rx_initiator = BCOM_INITIATOR_PSC3_RX,
-		.rx_ipr = BCOM_IPR_PSC3_RX,
-		.tx_initiator = BCOM_INITIATOR_PSC3_TX,
-		.tx_ipr = BCOM_IPR_PSC3_TX,
-	},
-	[3] = {
-		.rx_initiator = BCOM_INITIATOR_PSC4_RX,
-		.rx_ipr = BCOM_IPR_PSC4_RX,
-		.tx_initiator = BCOM_INITIATOR_PSC4_TX,
-		.tx_ipr = BCOM_IPR_PSC4_TX,
-	},
-	[4] = {
-		.rx_initiator = BCOM_INITIATOR_PSC5_RX,
-		.rx_ipr = BCOM_IPR_PSC5_RX,
-		.tx_initiator = BCOM_INITIATOR_PSC5_TX,
-		.tx_ipr = BCOM_IPR_PSC5_TX,
-	},
-	[5] = {
-		.rx_initiator = BCOM_INITIATOR_PSC6_RX,
-		.rx_ipr = BCOM_IPR_PSC6_RX,
-		.tx_initiator = BCOM_INITIATOR_PSC6_TX,
-		.tx_ipr = BCOM_IPR_PSC6_TX,
-	},
-};
-
-/**
- * bcom_psc_gen_bd_rx_init - Allocate a receive bcom_task for a PSC port
- * @psc_num:	Number of the PSC to allocate a task for
- * @queue_len:	number of buffer descriptors to allocate for the task
- * @fifo:	physical address of FIFO register
- * @maxbufsize:	Maximum receive data size in bytes.
- *
- * Allocate a bestcomm task structure for receiving data from a PSC.
- */
-struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
-					   phys_addr_t fifo, int maxbufsize)
-{
-	if (psc_num >= MPC52xx_PSC_MAXNUM)
-		return NULL;
-
-	return bcom_gen_bd_rx_init(queue_len, fifo,
-				   bcom_psc_params[psc_num].rx_initiator,
-				   bcom_psc_params[psc_num].rx_ipr,
-				   maxbufsize);
-}
-EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_rx_init);
-
-/**
- * bcom_psc_gen_bd_tx_init - Allocate a transmit bcom_task for a PSC port
- * @psc_num:	Number of the PSC to allocate a task for
- * @queue_len:	number of buffer descriptors to allocate for the task
- * @fifo:	physical address of FIFO register
- *
- * Allocate a bestcomm task structure for transmitting data to a PSC.
- */
-struct bcom_task *
-bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, phys_addr_t fifo)
-{
-	struct psc;
-	return bcom_gen_bd_tx_init(queue_len, fifo,
-				   bcom_psc_params[psc_num].tx_initiator,
-				   bcom_psc_params[psc_num].tx_ipr);
-}
-EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init);
-
-
-MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
-MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>");
-MODULE_LICENSE("GPL v2");
-
diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.h b/arch/powerpc/sysdev/bestcomm/gen_bd.h
deleted file mode 100644
index de47260..0000000
--- a/arch/powerpc/sysdev/bestcomm/gen_bd.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Header for Bestcomm General Buffer Descriptor tasks driver
- *
- *
- * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2006 AppSpec Computer Technologies Corp.
- *                    Jeff Gibbons <jeff.gibbons@appspec.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- *
- */
-
-#ifndef __BESTCOMM_GEN_BD_H__
-#define __BESTCOMM_GEN_BD_H__
-
-struct bcom_gen_bd {
-	u32	status;
-	u32	buf_pa;
-};
-
-
-extern struct bcom_task *
-bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
-			int initiator, int ipr, int maxbufsize);
-
-extern int
-bcom_gen_bd_rx_reset(struct bcom_task *tsk);
-
-extern void
-bcom_gen_bd_rx_release(struct bcom_task *tsk);
-
-
-extern struct bcom_task *
-bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
-			int initiator, int ipr);
-
-extern int
-bcom_gen_bd_tx_reset(struct bcom_task *tsk);
-
-extern void
-bcom_gen_bd_tx_release(struct bcom_task *tsk);
-
-
-/* PSC support utility wrappers */
-struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
-					   phys_addr_t fifo, int maxbufsize);
-struct bcom_task * bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len,
-					   phys_addr_t fifo);
-#endif  /* __BESTCOMM_GEN_BD_H__ */
-
diff --git a/arch/powerpc/sysdev/bestcomm/sram.c b/arch/powerpc/sysdev/bestcomm/sram.c
deleted file mode 100644
index b6db23e..0000000
--- a/arch/powerpc/sysdev/bestcomm/sram.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Simple memory allocator for on-board SRAM
- *
- *
- * Maintainer : Sylvain Munaut <tnt@246tNt.com>
- *
- * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/of.h>
-
-#include <asm/io.h>
-#include <asm/mmu.h>
-
-#include "sram.h"
-
-
-/* Struct keeping our 'state' */
-struct bcom_sram *bcom_sram = NULL;
-EXPORT_SYMBOL_GPL(bcom_sram);	/* needed for inline functions */
-
-
-/* ======================================================================== */
-/* Public API                                                               */
-/* ======================================================================== */
-/* DO NOT USE in interrupts, if needed in irq handler, we should use the
-   _irqsave version of the spin_locks */
-
-int bcom_sram_init(struct device_node *sram_node, char *owner)
-{
-	int rv;
-	const u32 *regaddr_p;
-	u64 regaddr64, size64;
-	unsigned int psize;
-
-	/* Create our state struct */
-	if (bcom_sram) {
-		printk(KERN_ERR "%s: bcom_sram_init: "
-			"Already initialized !\n", owner);
-		return -EBUSY;
-	}
-
-	bcom_sram = kmalloc(sizeof(struct bcom_sram), GFP_KERNEL);
-	if (!bcom_sram) {
-		printk(KERN_ERR "%s: bcom_sram_init: "
-			"Couldn't allocate internal state !\n", owner);
-		return -ENOMEM;
-	}
-
-	/* Get address and size of the sram */
-	regaddr_p = of_get_address(sram_node, 0, &size64, NULL);
-	if (!regaddr_p) {
-		printk(KERN_ERR "%s: bcom_sram_init: "
-			"Invalid device node !\n", owner);
-		rv = -EINVAL;
-		goto error_free;
-	}
-
-	regaddr64 = of_translate_address(sram_node, regaddr_p);
-
-	bcom_sram->base_phys = (phys_addr_t) regaddr64;
-	bcom_sram->size = (unsigned int) size64;
-
-	/* Request region */
-	if (!request_mem_region(bcom_sram->base_phys, bcom_sram->size, owner)) {
-		printk(KERN_ERR "%s: bcom_sram_init: "
-			"Couldn't request region !\n", owner);
-		rv = -EBUSY;
-		goto error_free;
-	}
-
-	/* Map SRAM */
-		/* sram is not really __iomem */
-	bcom_sram->base_virt = (void*) ioremap(bcom_sram->base_phys, bcom_sram->size);
-
-	if (!bcom_sram->base_virt) {
-		printk(KERN_ERR "%s: bcom_sram_init: "
-			"Map error SRAM zone 0x%08lx (0x%0x)!\n",
-			owner, (long)bcom_sram->base_phys, bcom_sram->size );
-		rv = -ENOMEM;
-		goto error_release;
-	}
-
-	/* Create an rheap (defaults to 32 bits word alignment) */
-	bcom_sram->rh = rh_create(4);
-
-	/* Attach the free zones */
-#if 0
-	/* Currently disabled ... for future use only */
-	reg_addr_p = of_get_property(sram_node, "available", &psize);
-#else
-	regaddr_p = NULL;
-	psize = 0;
-#endif
-
-	if (!regaddr_p || !psize) {
-		/* Attach the whole zone */
-		rh_attach_region(bcom_sram->rh, 0, bcom_sram->size);
-	} else {
-		/* Attach each zone independently */
-		while (psize >= 2 * sizeof(u32)) {
-			phys_addr_t zbase = of_translate_address(sram_node, regaddr_p);
-			rh_attach_region(bcom_sram->rh, zbase - bcom_sram->base_phys, regaddr_p[1]);
-			regaddr_p += 2;
-			psize -= 2 * sizeof(u32);
-		}
-	}
-
-	/* Init our spinlock */
-	spin_lock_init(&bcom_sram->lock);
-
-	return 0;
-
-error_release:
-	release_mem_region(bcom_sram->base_phys, bcom_sram->size);
-error_free:
-	kfree(bcom_sram);
-	bcom_sram = NULL;
-
-	return rv;
-}
-EXPORT_SYMBOL_GPL(bcom_sram_init);
-
-void bcom_sram_cleanup(void)
-{
-	/* Free resources */
-	if (bcom_sram) {
-		rh_destroy(bcom_sram->rh);
-		iounmap((void __iomem *)bcom_sram->base_virt);
-		release_mem_region(bcom_sram->base_phys, bcom_sram->size);
-		kfree(bcom_sram);
-		bcom_sram = NULL;
-	}
-}
-EXPORT_SYMBOL_GPL(bcom_sram_cleanup);
-
-void* bcom_sram_alloc(int size, int align, phys_addr_t *phys)
-{
-	unsigned long offset;
-
-	spin_lock(&bcom_sram->lock);
-	offset = rh_alloc_align(bcom_sram->rh, size, align, NULL);
-	spin_unlock(&bcom_sram->lock);
-
-	if (IS_ERR_VALUE(offset))
-		return NULL;
-
-	*phys = bcom_sram->base_phys + offset;
-	return bcom_sram->base_virt + offset;
-}
-EXPORT_SYMBOL_GPL(bcom_sram_alloc);
-
-void bcom_sram_free(void *ptr)
-{
-	unsigned long offset;
-
-	if (!ptr)
-		return;
-
-	offset = ptr - bcom_sram->base_virt;
-
-	spin_lock(&bcom_sram->lock);
-	rh_free(bcom_sram->rh, offset);
-	spin_unlock(&bcom_sram->lock);
-}
-EXPORT_SYMBOL_GPL(bcom_sram_free);
-
diff --git a/arch/powerpc/sysdev/bestcomm/sram.h b/arch/powerpc/sysdev/bestcomm/sram.h
deleted file mode 100644
index b6d6689..0000000
--- a/arch/powerpc/sysdev/bestcomm/sram.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Handling of a sram zone for bestcomm
- *
- *
- * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#ifndef __BESTCOMM_SRAM_H__
-#define __BESTCOMM_SRAM_H__
-
-#include <asm/rheap.h>
-#include <asm/mmu.h>
-#include <linux/spinlock.h>
-
-
-/* Structure used internally */
-	/* The internals are here for the inline functions
-	 * sake, certainly not for the user to mess with !
-	 */
-struct bcom_sram {
-	phys_addr_t		 base_phys;
-	void 			*base_virt;
-	unsigned int		 size;
-	rh_info_t		*rh;
-	spinlock_t		 lock;
-};
-
-extern struct bcom_sram *bcom_sram;
-
-
-/* Public API */
-extern int  bcom_sram_init(struct device_node *sram_node, char *owner);
-extern void bcom_sram_cleanup(void);
-
-extern void* bcom_sram_alloc(int size, int align, phys_addr_t *phys);
-extern void  bcom_sram_free(void *ptr);
-
-static inline phys_addr_t bcom_sram_va2pa(void *va) {
-	return bcom_sram->base_phys +
-		(unsigned long)(va - bcom_sram->base_virt);
-}
-
-static inline void *bcom_sram_pa2va(phys_addr_t pa) {
-	return bcom_sram->base_virt +
-		(unsigned long)(pa - bcom_sram->base_phys);
-}
-
-
-#endif  /* __BESTCOMM_SRAM_H__ */
-
diff --git a/drivers/Makefile b/drivers/Makefile
index 03da5b6..b69189e 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -25,7 +25,7 @@ obj-$(CONFIG_PNP)		+= pnp/
 obj-y				+= amba/
 # Many drivers will want to use DMA so this has to be made available
 # really early.
-obj-$(CONFIG_DMA_ENGINE)	+= dma/
+obj-$(CONFIG_DMADEVICES)	+= dma/
 
 obj-$(CONFIG_VIRTIO)		+= virtio/
 obj-$(CONFIG_XEN)		+= xen/
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index d2c102f..3d0d4d2 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -26,9 +26,9 @@
 #include <asm/prom.h>
 #include <asm/mpc52xx.h>
 
-#include <sysdev/bestcomm/bestcomm.h>
-#include <sysdev/bestcomm/bestcomm_priv.h>
-#include <sysdev/bestcomm/ata.h>
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/bestcomm_priv.h>
+#include <linux/fsl/bestcomm/ata.h>
 
 #define DRV_NAME	"mpc52xx_ata"
 
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 677cd6e..464050b 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -114,6 +114,8 @@ config MPC512X_DMA
 	---help---
 	  Enable support for the Freescale MPC512x built-in DMA engine.
 
+source "drivers/dma/bestcomm/Kconfig"
+
 config MV_XOR
 	bool "Marvell XOR engine support"
 	depends on PLAT_ORION
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 7428fea..642d967 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
 obj-$(CONFIG_FSL_DMA) += fsldma.o
 obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
+obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
 obj-$(CONFIG_MV_XOR) += mv_xor.o
 obj-$(CONFIG_DW_DMAC) += dw_dmac.o
 obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
diff --git a/drivers/dma/bestcomm/Kconfig b/drivers/dma/bestcomm/Kconfig
new file mode 100644
index 0000000..29e4270
--- /dev/null
+++ b/drivers/dma/bestcomm/Kconfig
@@ -0,0 +1,36 @@
+#
+# Kconfig options for Bestcomm
+#
+
+config PPC_BESTCOMM
+	tristate "Bestcomm DMA engine support"
+	depends on PPC_MPC52xx
+	default n
+	select PPC_LIB_RHEAP
+	help
+	  BestComm is the name of the communication coprocessor found
+	  on the Freescale MPC5200 family of processor.  Its usage is
+	  optional for some drivers (like ATA), but required for
+	  others (like FEC).
+
+	  If you want to use drivers that require DMA operations,
+	  answer Y or M. Otherwise say N.
+
+config PPC_BESTCOMM_ATA
+	tristate
+	depends on PPC_BESTCOMM
+	help
+	  This option enables the support for the ATA task.
+
+config PPC_BESTCOMM_FEC
+	tristate
+	depends on PPC_BESTCOMM
+	help
+	  This option enables the support for the FEC tasks.
+
+config PPC_BESTCOMM_GEN_BD
+	tristate
+	depends on PPC_BESTCOMM
+	help
+	  This option enables the support for the GenBD tasks.
+
diff --git a/drivers/dma/bestcomm/Makefile b/drivers/dma/bestcomm/Makefile
new file mode 100644
index 0000000..aed2df2
--- /dev/null
+++ b/drivers/dma/bestcomm/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for BestComm & co
+#
+
+bestcomm-core-objs	:= bestcomm.o sram.o
+bestcomm-ata-objs	:= ata.o bcom_ata_task.o
+bestcomm-fec-objs	:= fec.o bcom_fec_rx_task.o bcom_fec_tx_task.o
+bestcomm-gen-bd-objs	:= gen_bd.o bcom_gen_bd_rx_task.o bcom_gen_bd_tx_task.o
+
+obj-$(CONFIG_PPC_BESTCOMM)		+= bestcomm-core.o
+obj-$(CONFIG_PPC_BESTCOMM_ATA)		+= bestcomm-ata.o
+obj-$(CONFIG_PPC_BESTCOMM_FEC)		+= bestcomm-fec.o
+obj-$(CONFIG_PPC_BESTCOMM_GEN_BD)	+= bestcomm-gen-bd.o
+ 
diff --git a/drivers/dma/bestcomm/ata.c b/drivers/dma/bestcomm/ata.c
new file mode 100644
index 0000000..2fd87f8
--- /dev/null
+++ b/drivers/dma/bestcomm/ata.c
@@ -0,0 +1,157 @@
+/*
+ * Bestcomm ATA task driver
+ *
+ *
+ * Patterned after bestcomm/fec.c by Dale Farnsworth <dfarnsworth@mvista.com>
+ *                                   2003-2004 (c) MontaVista, Software, Inc.
+ *
+ * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2006      Freescale - John Rigby
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/bestcomm_priv.h>
+#include <linux/fsl/bestcomm/ata.h>
+
+
+/* ======================================================================== */
+/* Task image/var/inc                                                       */
+/* ======================================================================== */
+
+/* ata task image */
+extern u32 bcom_ata_task[];
+
+/* ata task vars that need to be set before enabling the task */
+struct bcom_ata_var {
+	u32 enable;		/* (u16*) address of task's control register */
+	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
+	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
+	u32 bd_start;		/* (struct bcom_bd*) current bd */
+	u32 buffer_size;	/* size of receive buffer */
+};
+
+/* ata task incs that need to be set before enabling the task */
+struct bcom_ata_inc {
+	u16 pad0;
+	s16 incr_bytes;
+	u16 pad1;
+	s16 incr_dst;
+	u16 pad2;
+	s16 incr_src;
+};
+
+
+/* ======================================================================== */
+/* Task support code                                                        */
+/* ======================================================================== */
+
+struct bcom_task *
+bcom_ata_init(int queue_len, int maxbufsize)
+{
+	struct bcom_task *tsk;
+	struct bcom_ata_var *var;
+	struct bcom_ata_inc *inc;
+
+	/* Prefetch breaks ATA DMA.  Turn it off for ATA DMA */
+	bcom_disable_prefetch();
+
+	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_ata_bd), 0);
+	if (!tsk)
+		return NULL;
+
+	tsk->flags = BCOM_FLAGS_NONE;
+
+	bcom_ata_reset_bd(tsk);
+
+	var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum);
+	inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
+
+	if (bcom_load_image(tsk->tasknum, bcom_ata_task)) {
+		bcom_task_free(tsk);
+		return NULL;
+	}
+
+	var->enable	= bcom_eng->regs_base +
+				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
+	var->bd_base	= tsk->bd_pa;
+	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
+	var->bd_start	= tsk->bd_pa;
+	var->buffer_size = maxbufsize;
+
+	/* Configure some stuff */
+	bcom_set_task_pragma(tsk->tasknum, BCOM_ATA_PRAGMA);
+	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
+
+	out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ATA_RX], BCOM_IPR_ATA_RX);
+	out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ATA_TX], BCOM_IPR_ATA_TX);
+
+	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
+
+	return tsk;
+}
+EXPORT_SYMBOL_GPL(bcom_ata_init);
+
+void bcom_ata_rx_prepare(struct bcom_task *tsk)
+{
+	struct bcom_ata_inc *inc;
+
+	inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
+
+	inc->incr_bytes	= -(s16)sizeof(u32);
+	inc->incr_src	= 0;
+	inc->incr_dst	= sizeof(u32);
+
+	bcom_set_initiator(tsk->tasknum, BCOM_INITIATOR_ATA_RX);
+}
+EXPORT_SYMBOL_GPL(bcom_ata_rx_prepare);
+
+void bcom_ata_tx_prepare(struct bcom_task *tsk)
+{
+	struct bcom_ata_inc *inc;
+
+	inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
+
+	inc->incr_bytes	= -(s16)sizeof(u32);
+	inc->incr_src	= sizeof(u32);
+	inc->incr_dst	= 0;
+
+	bcom_set_initiator(tsk->tasknum, BCOM_INITIATOR_ATA_TX);
+}
+EXPORT_SYMBOL_GPL(bcom_ata_tx_prepare);
+
+void bcom_ata_reset_bd(struct bcom_task *tsk)
+{
+	struct bcom_ata_var *var;
+
+	/* Reset all BD */
+	memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+
+	tsk->index = 0;
+	tsk->outdex = 0;
+
+	var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum);
+	var->bd_start = var->bd_base;
+}
+EXPORT_SYMBOL_GPL(bcom_ata_reset_bd);
+
+void bcom_ata_release(struct bcom_task *tsk)
+{
+	/* Nothing special for the ATA tasks */
+	bcom_task_free(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_ata_release);
+
+
+MODULE_DESCRIPTION("BestComm ATA task driver");
+MODULE_AUTHOR("John Rigby");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/dma/bestcomm/bcom_ata_task.c b/drivers/dma/bestcomm/bcom_ata_task.c
new file mode 100644
index 0000000..cc6049a
--- /dev/null
+++ b/drivers/dma/bestcomm/bcom_ata_task.c
@@ -0,0 +1,67 @@
+/*
+ * Bestcomm ATA task microcode
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Created based on bestcom/code_dma/image_rtos1/dma_image.hex
+ */
+
+#include <asm/types.h>
+
+/*
+ * The header consists of the following fields:
+ *	u32	magic;
+ *	u8	desc_size;
+ *	u8	var_size;
+ *	u8	inc_size;
+ *	u8	first_var;
+ *	u8	reserved[8];
+ *
+ * The size fields contain the number of 32-bit words.
+ */
+
+u32 bcom_ata_task[] = {
+	/* header */
+	0x4243544b,
+	0x0e060709,
+	0x00000000,
+	0x00000000,
+
+	/* Task descriptors */
+	0x8198009b, /* LCD: idx0 = var3; idx0 <= var2; idx0 += inc3 */
+	0x13e00c08, /*   DRD1A: var3 = var1; FN=0 MORE init=31 WS=0 RS=0 */
+	0xb8000264, /*   LCD: idx1 = *idx0, idx2 = var0; idx1 < var9; idx1 += inc4, idx2 += inc4 */
+	0x10000f00, /*     DRD1A: var3 = idx0; FN=0 MORE init=0 WS=0 RS=0 */
+	0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
+	0x0c8cfc8a, /*     DRD2B1: *idx2 = EU3(); EU3(*idx2,var10)  */
+	0xd8988240, /*   LCDEXT: idx1 = idx1; idx1 > var9; idx1 += inc0 */
+	0xf845e011, /*   LCDEXT: idx2 = *(idx0 + var00000015); ; idx2 += inc2 */
+	0xb845e00a, /*   LCD: idx3 = *(idx0 + var00000019); ; idx3 += inc1 */
+	0x0bfecf90, /*     DRD1A: *idx3 = *idx2; FN=0 TFD init=31 WS=3 RS=3 */
+	0x9898802d, /*   LCD: idx1 = idx1; idx1 once var0; idx1 += inc5 */
+	0x64000005, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 INT EXT init=0 WS=0 RS=0 */
+	0x0c0cf849, /*     DRD2B1: *idx0 = EU3(); EU3(idx1,var9)  */
+	0x000001f8, /* NOP */
+
+	/* VAR[9]-VAR[14] */
+	0x40000000,
+	0x7fff7fff,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+
+	/* INC[0]-INC[6] */
+	0x40000000,
+	0xe0000000,
+	0xe0000000,
+	0xa000000c,
+	0x20000000,
+	0x00000000,
+	0x00000000,
+};
+
diff --git a/drivers/dma/bestcomm/bcom_fec_rx_task.c b/drivers/dma/bestcomm/bcom_fec_rx_task.c
new file mode 100644
index 0000000..a1ad6a0
--- /dev/null
+++ b/drivers/dma/bestcomm/bcom_fec_rx_task.c
@@ -0,0 +1,78 @@
+/*
+ * Bestcomm FEC RX task microcode
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
+ * on Tue Mar 22 11:19:38 2005 GMT
+ */
+
+#include <asm/types.h>
+
+/*
+ * The header consists of the following fields:
+ *	u32	magic;
+ *	u8	desc_size;
+ *	u8	var_size;
+ *	u8	inc_size;
+ *	u8	first_var;
+ *	u8	reserved[8];
+ *
+ * The size fields contain the number of 32-bit words.
+ */
+
+u32 bcom_fec_rx_task[] = {
+	/* header */
+	0x4243544b,
+	0x18060709,
+	0x00000000,
+	0x00000000,
+
+	/* Task descriptors */
+	0x808220e3, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
+	0x10601010, /*   DRD1A: var4 = var2; FN=0 MORE init=3 WS=0 RS=0 */
+	0xb8800264, /*   LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc4, idx3 += inc4 */
+	0x10001308, /*     DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+	0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
+	0x0cccfcca, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var10)  */
+	0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
+	0xb8c58029, /*   LCD: idx3 = *(idx1 + var00000015); idx3 once var0; idx3 += inc5 */
+	0x60000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=0 RS=0 */
+	0x088cf8cc, /*     DRD2B1: idx2 = EU3(); EU3(idx3,var12)  */
+	0x991982f2, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var11; idx2 += inc6, idx3 += inc2 */
+	0x006acf80, /*     DRD1A: *idx3 = *idx0; FN=0 init=3 WS=1 RS=1 */
+	0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
+	0x9999802d, /*   LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
+	0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
+	0x034cfc4e, /*     DRD2B1: var13 = EU3(); EU3(*idx1,var14)  */
+	0x00008868, /*     DRD1A: idx2 = var13; FN=0 init=0 WS=0 RS=0 */
+	0x99198341, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var13; idx2 += inc0, idx3 += inc1 */
+	0x007ecf80, /*     DRD1A: *idx3 = *idx0; FN=0 init=3 WS=3 RS=3 */
+	0x99198272, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc6, idx3 += inc2 */
+	0x046acf80, /*     DRD1A: *idx3 = *idx0; FN=0 INT init=3 WS=1 RS=1 */
+	0x9819002d, /*   LCD: idx2 = idx0; idx2 once var0; idx2 += inc5 */
+	0x0060c790, /*     DRD1A: *idx1 = *idx2; FN=0 init=3 WS=0 RS=0 */
+	0x000001f8, /*   NOP */
+
+	/* VAR[9]-VAR[14] */
+	0x40000000,
+	0x7fff7fff,
+	0x00000000,
+	0x00000003,
+	0x40000008,
+	0x43ffffff,
+
+	/* INC[0]-INC[6] */
+	0x40000000,
+	0xe0000000,
+	0xe0000000,
+	0xa0000008,
+	0x20000000,
+	0x00000000,
+	0x4000ffff,
+};
+
diff --git a/drivers/dma/bestcomm/bcom_fec_tx_task.c b/drivers/dma/bestcomm/bcom_fec_tx_task.c
new file mode 100644
index 0000000..b1c495c
--- /dev/null
+++ b/drivers/dma/bestcomm/bcom_fec_tx_task.c
@@ -0,0 +1,91 @@
+/*
+ * Bestcomm FEC TX task microcode
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
+ * on Tue Mar 22 11:19:29 2005 GMT
+ */
+
+#include <asm/types.h>
+
+/*
+ * The header consists of the following fields:
+ *	u32	magic;
+ *	u8	desc_size;
+ *	u8	var_size;
+ *	u8	inc_size;
+ *	u8	first_var;
+ *	u8	reserved[8];
+ *
+ * The size fields contain the number of 32-bit words.
+ */
+
+u32 bcom_fec_tx_task[] = {
+	/* header */
+	0x4243544b,
+	0x2407070d,
+	0x00000000,
+	0x00000000,
+
+	/* Task descriptors */
+	0x8018001b, /* LCD: idx0 = var0; idx0 <= var0; idx0 += inc3 */
+	0x60000005, /*   DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
+	0x01ccfc0d, /*   DRD2B1: var7 = EU3(); EU3(*idx0,var13)  */
+	0x8082a123, /* LCD: idx0 = var1, idx1 = var5; idx1 <= var4; idx0 += inc4, idx1 += inc3 */
+	0x10801418, /*   DRD1A: var5 = var3; FN=0 MORE init=4 WS=0 RS=0 */
+	0xf88103a4, /*   LCDEXT: idx2 = *idx1, idx3 = var2; idx2 < var14; idx2 += inc4, idx3 += inc4 */
+	0x801a6024, /*   LCD: idx4 = var0; ; idx4 += inc4 */
+	0x10001708, /*     DRD1A: var5 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+	0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
+	0x0cccfccf, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var15)  */
+	0x991a002c, /*   LCD: idx2 = idx2, idx3 = idx4; idx2 once var0; idx2 += inc5, idx3 += inc4 */
+	0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
+	0x024cfc4d, /*     DRD2B1: var9 = EU3(); EU3(*idx1,var13)  */
+	0x60000003, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=3 EXT init=0 WS=0 RS=0 */
+	0x0cccf247, /*     DRD2B1: *idx3 = EU3(); EU3(var9,var7)  */
+	0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
+	0xb8c80029, /*   LCD: idx3 = *(idx1 + var0000001a); idx3 once var0; idx3 += inc5 */
+	0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
+	0x088cf8d1, /*     DRD2B1: idx2 = EU3(); EU3(idx3,var17)  */
+	0x00002f10, /*     DRD1A: var11 = idx2; FN=0 init=0 WS=0 RS=0 */
+	0x99198432, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var16; idx2 += inc6, idx3 += inc2 */
+	0x008ac398, /*     DRD1A: *idx0 = *idx3; FN=0 init=4 WS=1 RS=1 */
+	0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
+	0x9999802d, /*   LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
+	0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
+	0x048cfc53, /*     DRD2B1: var18 = EU3(); EU3(*idx1,var19)  */
+	0x60000008, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=8 EXT init=0 WS=0 RS=0 */
+	0x088cf48b, /*     DRD2B1: idx2 = EU3(); EU3(var18,var11)  */
+	0x99198481, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var18; idx2 += inc0, idx3 += inc1 */
+	0x009ec398, /*     DRD1A: *idx0 = *idx3; FN=0 init=4 WS=3 RS=3 */
+	0x991983b2, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var14; idx2 += inc6, idx3 += inc2 */
+	0x088ac398, /*     DRD1A: *idx0 = *idx3; FN=0 TFD init=4 WS=1 RS=1 */
+	0x9919002d, /*   LCD: idx2 = idx2; idx2 once var0; idx2 += inc5 */
+	0x60000005, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
+	0x0c4cf88e, /*     DRD2B1: *idx1 = EU3(); EU3(idx2,var14)  */
+	0x000001f8, /*   NOP */
+
+	/* VAR[13]-VAR[19] */
+	0x0c000000,
+	0x40000000,
+	0x7fff7fff,
+	0x00000000,
+	0x00000003,
+	0x40000004,
+	0x43ffffff,
+
+	/* INC[0]-INC[6] */
+	0x40000000,
+	0xe0000000,
+	0xe0000000,
+	0xa0000008,
+	0x20000000,
+	0x00000000,
+	0x4000ffff,
+};
+
diff --git a/drivers/dma/bestcomm/bcom_gen_bd_rx_task.c b/drivers/dma/bestcomm/bcom_gen_bd_rx_task.c
new file mode 100644
index 0000000..efee022
--- /dev/null
+++ b/drivers/dma/bestcomm/bcom_gen_bd_rx_task.c
@@ -0,0 +1,63 @@
+/*
+ * Bestcomm GenBD RX task microcode
+ *
+ * Copyright (C) 2006 AppSpec Computer Technologies Corp.
+ *                    Jeff Gibbons <jeff.gibbons@appspec.com>
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
+ * on Tue Mar 4 10:14:12 2006 GMT
+ *
+ */
+
+#include <asm/types.h>
+
+/*
+ * The header consists of the following fields:
+ *	u32	magic;
+ *	u8	desc_size;
+ *	u8	var_size;
+ *	u8	inc_size;
+ *	u8	first_var;
+ *	u8	reserved[8];
+ *
+ * The size fields contain the number of 32-bit words.
+ */
+
+u32 bcom_gen_bd_rx_task[] = {
+	/* header */
+	0x4243544b,
+	0x0d020409,
+	0x00000000,
+	0x00000000,
+
+	/* Task descriptors */
+	0x808220da, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc3, idx1 += inc2 */
+	0x13e01010, /*   DRD1A: var4 = var2; FN=0 MORE init=31 WS=0 RS=0 */
+	0xb880025b, /*   LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc3, idx3 += inc3 */
+	0x10001308, /*     DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+	0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
+	0x0cccfcca, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var10)  */
+	0xd9190240, /*   LCDEXT: idx2 = idx2; idx2 > var9; idx2 += inc0 */
+	0xb8c5e009, /*   LCD: idx3 = *(idx1 + var00000015); ; idx3 += inc1 */
+	0x07fecf80, /*     DRD1A: *idx3 = *idx0; FN=0 INT init=31 WS=3 RS=3 */
+	0x99190024, /*   LCD: idx2 = idx2; idx2 once var0; idx2 += inc4 */
+	0x60000005, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
+	0x0c4cf889, /*     DRD2B1: *idx1 = EU3(); EU3(idx2,var9)  */
+	0x000001f8, /*   NOP */
+
+	/* VAR[9]-VAR[10] */
+	0x40000000,
+	0x7fff7fff,
+
+	/* INC[0]-INC[3] */
+	0x40000000,
+	0xe0000000,
+	0xa0000008,
+	0x20000000,
+};
+
diff --git a/drivers/dma/bestcomm/bcom_gen_bd_tx_task.c b/drivers/dma/bestcomm/bcom_gen_bd_tx_task.c
new file mode 100644
index 0000000..c605aa4
--- /dev/null
+++ b/drivers/dma/bestcomm/bcom_gen_bd_tx_task.c
@@ -0,0 +1,69 @@
+/*
+ * Bestcomm GenBD TX task microcode
+ *
+ * Copyright (C) 2006 AppSpec Computer Technologies Corp.
+ *                    Jeff Gibbons <jeff.gibbons@appspec.com>
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
+ * on Tue Mar 4 10:14:12 2006 GMT
+ *
+ */
+
+#include <asm/types.h>
+
+/*
+ * The header consists of the following fields:
+ *	u32	magic;
+ *	u8	desc_size;
+ *	u8	var_size;
+ *	u8	inc_size;
+ *	u8	first_var;
+ *	u8	reserved[8];
+ *
+ * The size fields contain the number of 32-bit words.
+ */
+
+u32 bcom_gen_bd_tx_task[] = {
+	/* header */
+	0x4243544b,
+	0x0f040609,
+	0x00000000,
+	0x00000000,
+
+	/* Task descriptors */
+	0x800220e3, /* LCD: idx0 = var0, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
+	0x13e01010, /*   DRD1A: var4 = var2; FN=0 MORE init=31 WS=0 RS=0 */
+	0xb8808264, /*   LCD: idx2 = *idx1, idx3 = var1; idx2 < var9; idx2 += inc4, idx3 += inc4 */
+	0x10001308, /*     DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+	0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
+	0x0cccfcca, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var10)  */
+	0xd9190300, /*   LCDEXT: idx2 = idx2; idx2 > var12; idx2 += inc0 */
+	0xb8c5e009, /*   LCD: idx3 = *(idx1 + var00000015); ; idx3 += inc1 */
+	0x03fec398, /*     DRD1A: *idx0 = *idx3; FN=0 init=31 WS=3 RS=3 */
+	0x9919826a, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc5, idx3 += inc2 */
+	0x0feac398, /*     DRD1A: *idx0 = *idx3; FN=0 TFD INT init=31 WS=1 RS=1 */
+	0x99190036, /*   LCD: idx2 = idx2; idx2 once var0; idx2 += inc6 */
+	0x60000005, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
+	0x0c4cf889, /*     DRD2B1: *idx1 = EU3(); EU3(idx2,var9)  */
+	0x000001f8, /*   NOP */
+
+	/* VAR[9]-VAR[12] */
+	0x40000000,
+	0x7fff7fff,
+	0x00000000,
+	0x40000004,
+
+	/* INC[0]-INC[5] */
+	0x40000000,
+	0xe0000000,
+	0xe0000000,
+	0xa0000008,
+	0x20000000,
+	0x4000ffff,
+};
+
diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c
new file mode 100644
index 0000000..67371fb
--- /dev/null
+++ b/drivers/dma/bestcomm/bestcomm.c
@@ -0,0 +1,532 @@
+/*
+ * Driver for MPC52xx processor BestComm peripheral controller
+ *
+ *
+ * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2005      Varma Electronics Oy,
+ *                         ( by Andrey Volkov <avolkov@varma-el.com> )
+ * Copyright (C) 2003-2004 MontaVista, Software, Inc.
+ *                         ( by Dale Farnsworth <dfarnsworth@mvista.com> )
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mpc52xx.h>
+
+#include <linux/fsl/bestcomm/sram.h>
+#include <linux/fsl/bestcomm/bestcomm_priv.h>
+#include "linux/fsl/bestcomm/bestcomm.h"
+
+#define DRIVER_NAME "bestcomm-core"
+
+/* MPC5200 device tree match tables */
+static struct of_device_id mpc52xx_sram_ids[] __devinitdata = {
+	{ .compatible = "fsl,mpc5200-sram", },
+	{ .compatible = "mpc5200-sram", },
+	{}
+};
+
+
+struct bcom_engine *bcom_eng = NULL;
+EXPORT_SYMBOL_GPL(bcom_eng);	/* needed for inline functions */
+
+/* ======================================================================== */
+/* Public and private API                                                   */
+/* ======================================================================== */
+
+/* Private API */
+
+struct bcom_task *
+bcom_task_alloc(int bd_count, int bd_size, int priv_size)
+{
+	int i, tasknum = -1;
+	struct bcom_task *tsk;
+
+	/* Don't try to do anything if bestcomm init failed */
+	if (!bcom_eng)
+		return NULL;
+
+	/* Get and reserve a task num */
+	spin_lock(&bcom_eng->lock);
+
+	for (i=0; i<BCOM_MAX_TASKS; i++)
+		if (!bcom_eng->tdt[i].stop) {	/* we use stop as a marker */
+			bcom_eng->tdt[i].stop = 0xfffffffful; /* dummy addr */
+			tasknum = i;
+			break;
+		}
+
+	spin_unlock(&bcom_eng->lock);
+
+	if (tasknum < 0)
+		return NULL;
+
+	/* Allocate our structure */
+	tsk = kzalloc(sizeof(struct bcom_task) + priv_size, GFP_KERNEL);
+	if (!tsk)
+		goto error;
+
+	tsk->tasknum = tasknum;
+	if (priv_size)
+		tsk->priv = (void*)tsk + sizeof(struct bcom_task);
+
+	/* Get IRQ of that task */
+	tsk->irq = irq_of_parse_and_map(bcom_eng->ofnode, tsk->tasknum);
+	if (tsk->irq == NO_IRQ)
+		goto error;
+
+	/* Init the BDs, if needed */
+	if (bd_count) {
+		tsk->cookie = kmalloc(sizeof(void*) * bd_count, GFP_KERNEL);
+		if (!tsk->cookie)
+			goto error;
+
+		tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa);
+		if (!tsk->bd)
+			goto error;
+		memset(tsk->bd, 0x00, bd_count * bd_size);
+
+		tsk->num_bd = bd_count;
+		tsk->bd_size = bd_size;
+	}
+
+	return tsk;
+
+error:
+	if (tsk) {
+		if (tsk->irq != NO_IRQ)
+			irq_dispose_mapping(tsk->irq);
+		bcom_sram_free(tsk->bd);
+		kfree(tsk->cookie);
+		kfree(tsk);
+	}
+
+	bcom_eng->tdt[tasknum].stop = 0;
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(bcom_task_alloc);
+
+void
+bcom_task_free(struct bcom_task *tsk)
+{
+	/* Stop the task */
+	bcom_disable_task(tsk->tasknum);
+
+	/* Clear TDT */
+	bcom_eng->tdt[tsk->tasknum].start = 0;
+	bcom_eng->tdt[tsk->tasknum].stop  = 0;
+
+	/* Free everything */
+	irq_dispose_mapping(tsk->irq);
+	bcom_sram_free(tsk->bd);
+	kfree(tsk->cookie);
+	kfree(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_task_free);
+
+int
+bcom_load_image(int task, u32 *task_image)
+{
+	struct bcom_task_header *hdr = (struct bcom_task_header *)task_image;
+	struct bcom_tdt *tdt;
+	u32 *desc, *var, *inc;
+	u32 *desc_src, *var_src, *inc_src;
+
+	/* Safety checks */
+	if (hdr->magic != BCOM_TASK_MAGIC) {
+		printk(KERN_ERR DRIVER_NAME
+			": Trying to load invalid microcode\n");
+		return -EINVAL;
+	}
+
+	if ((task < 0) || (task >= BCOM_MAX_TASKS)) {
+		printk(KERN_ERR DRIVER_NAME
+			": Trying to load invalid task %d\n", task);
+		return -EINVAL;
+	}
+
+	/* Initial load or reload */
+	tdt = &bcom_eng->tdt[task];
+
+	if (tdt->start) {
+		desc = bcom_task_desc(task);
+		if (hdr->desc_size != bcom_task_num_descs(task)) {
+			printk(KERN_ERR DRIVER_NAME
+				": Trying to reload wrong task image "
+				"(%d size %d/%d)!\n",
+				task,
+				hdr->desc_size,
+				bcom_task_num_descs(task));
+			return -EINVAL;
+		}
+	} else {
+		phys_addr_t start_pa;
+
+		desc = bcom_sram_alloc(hdr->desc_size * sizeof(u32), 4, &start_pa);
+		if (!desc)
+			return -ENOMEM;
+
+		tdt->start = start_pa;
+		tdt->stop = start_pa + ((hdr->desc_size-1) * sizeof(u32));
+	}
+
+	var = bcom_task_var(task);
+	inc = bcom_task_inc(task);
+
+	/* Clear & copy */
+	memset(var, 0x00, BCOM_VAR_SIZE);
+	memset(inc, 0x00, BCOM_INC_SIZE);
+
+	desc_src = (u32 *)(hdr + 1);
+	var_src = desc_src + hdr->desc_size;
+	inc_src = var_src + hdr->var_size;
+
+	memcpy(desc, desc_src, hdr->desc_size * sizeof(u32));
+	memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
+	memcpy(inc, inc_src, hdr->inc_size * sizeof(u32));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(bcom_load_image);
+
+void
+bcom_set_initiator(int task, int initiator)
+{
+	int i;
+	int num_descs;
+	u32 *desc;
+	int next_drd_has_initiator;
+
+	bcom_set_tcr_initiator(task, initiator);
+
+	/* Just setting tcr is apparently not enough due to some problem */
+	/* with it. So we just go thru all the microcode and replace in  */
+	/* the DRD directly */
+
+	desc = bcom_task_desc(task);
+	next_drd_has_initiator = 1;
+	num_descs = bcom_task_num_descs(task);
+
+	for (i=0; i<num_descs; i++, desc++) {
+		if (!bcom_desc_is_drd(*desc))
+			continue;
+		if (next_drd_has_initiator)
+			if (bcom_desc_initiator(*desc) != BCOM_INITIATOR_ALWAYS)
+				bcom_set_desc_initiator(desc, initiator);
+		next_drd_has_initiator = !bcom_drd_is_extended(*desc);
+	}
+}
+EXPORT_SYMBOL_GPL(bcom_set_initiator);
+
+
+/* Public API */
+
+void
+bcom_enable(struct bcom_task *tsk)
+{
+	bcom_enable_task(tsk->tasknum);
+}
+EXPORT_SYMBOL_GPL(bcom_enable);
+
+void
+bcom_disable(struct bcom_task *tsk)
+{
+	bcom_disable_task(tsk->tasknum);
+}
+EXPORT_SYMBOL_GPL(bcom_disable);
+
+
+/* ======================================================================== */
+/* Engine init/cleanup                                                      */
+/* ======================================================================== */
+
+/* Function Descriptor table */
+/* this will need to be updated if Freescale changes their task code FDT */
+static u32 fdt_ops[] = {
+	0xa0045670,	/* FDT[48] - load_acc()	  */
+	0x80045670,	/* FDT[49] - unload_acc() */
+	0x21800000,	/* FDT[50] - and()        */
+	0x21e00000,	/* FDT[51] - or()         */
+	0x21500000,	/* FDT[52] - xor()        */
+	0x21400000,	/* FDT[53] - andn()       */
+	0x21500000,	/* FDT[54] - not()        */
+	0x20400000,	/* FDT[55] - add()        */
+	0x20500000,	/* FDT[56] - sub()        */
+	0x20800000,	/* FDT[57] - lsh()        */
+	0x20a00000,	/* FDT[58] - rsh()        */
+	0xc0170000,	/* FDT[59] - crc8()       */
+	0xc0145670,	/* FDT[60] - crc16()      */
+	0xc0345670,	/* FDT[61] - crc32()      */
+	0xa0076540,	/* FDT[62] - endian32()   */
+	0xa0000760,	/* FDT[63] - endian16()   */
+};
+
+
+static int __devinit
+bcom_engine_init(void)
+{
+	int task;
+	phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
+	unsigned int tdt_size, ctx_size, var_size, fdt_size;
+
+	/* Allocate & clear SRAM zones for FDT, TDTs, contexts and vars/incs */
+	tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt);
+	ctx_size = BCOM_MAX_TASKS * BCOM_CTX_SIZE;
+	var_size = BCOM_MAX_TASKS * (BCOM_VAR_SIZE + BCOM_INC_SIZE);
+	fdt_size = BCOM_FDT_SIZE;
+
+	bcom_eng->tdt = bcom_sram_alloc(tdt_size, sizeof(u32), &tdt_pa);
+	bcom_eng->ctx = bcom_sram_alloc(ctx_size, BCOM_CTX_ALIGN, &ctx_pa);
+	bcom_eng->var = bcom_sram_alloc(var_size, BCOM_VAR_ALIGN, &var_pa);
+	bcom_eng->fdt = bcom_sram_alloc(fdt_size, BCOM_FDT_ALIGN, &fdt_pa);
+
+	if (!bcom_eng->tdt || !bcom_eng->ctx || !bcom_eng->var || !bcom_eng->fdt) {
+		printk(KERN_ERR "DMA: SRAM alloc failed in engine init !\n");
+
+		bcom_sram_free(bcom_eng->tdt);
+		bcom_sram_free(bcom_eng->ctx);
+		bcom_sram_free(bcom_eng->var);
+		bcom_sram_free(bcom_eng->fdt);
+
+		return -ENOMEM;
+	}
+
+	memset(bcom_eng->tdt, 0x00, tdt_size);
+	memset(bcom_eng->ctx, 0x00, ctx_size);
+	memset(bcom_eng->var, 0x00, var_size);
+	memset(bcom_eng->fdt, 0x00, fdt_size);
+
+	/* Copy the FDT for the EU#3 */
+	memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
+
+	/* Initialize Task base structure */
+	for (task=0; task<BCOM_MAX_TASKS; task++)
+	{
+		out_be16(&bcom_eng->regs->tcr[task], 0);
+		out_8(&bcom_eng->regs->ipr[task], 0);
+
+		bcom_eng->tdt[task].context	= ctx_pa;
+		bcom_eng->tdt[task].var	= var_pa;
+		bcom_eng->tdt[task].fdt	= fdt_pa;
+
+		var_pa += BCOM_VAR_SIZE + BCOM_INC_SIZE;
+		ctx_pa += BCOM_CTX_SIZE;
+	}
+
+	out_be32(&bcom_eng->regs->taskBar, tdt_pa);
+
+	/* Init 'always' initiator */
+	out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
+
+	/* Disable COMM Bus Prefetch on the original 5200; it's broken */
+	if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR)
+		bcom_disable_prefetch();
+
+	/* Init lock */
+	spin_lock_init(&bcom_eng->lock);
+
+	return 0;
+}
+
+static void
+bcom_engine_cleanup(void)
+{
+	int task;
+
+	/* Stop all tasks */
+	for (task=0; task<BCOM_MAX_TASKS; task++)
+	{
+		out_be16(&bcom_eng->regs->tcr[task], 0);
+		out_8(&bcom_eng->regs->ipr[task], 0);
+	}
+
+	out_be32(&bcom_eng->regs->taskBar, 0ul);
+
+	/* Release the SRAM zones */
+	bcom_sram_free(bcom_eng->tdt);
+	bcom_sram_free(bcom_eng->ctx);
+	bcom_sram_free(bcom_eng->var);
+	bcom_sram_free(bcom_eng->fdt);
+}
+
+
+/* ======================================================================== */
+/* OF platform driver                                                       */
+/* ======================================================================== */
+
+static int __devinit mpc52xx_bcom_probe(struct platform_device *op)
+{
+	struct device_node *ofn_sram;
+	struct resource res_bcom;
+
+	int rv;
+
+	/* Inform user we're ok so far */
+	printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
+
+	/* Get the bestcomm node */
+	of_node_get(op->dev.of_node);
+
+	/* Prepare SRAM */
+	ofn_sram = of_find_matching_node(NULL, mpc52xx_sram_ids);
+	if (!ofn_sram) {
+		printk(KERN_ERR DRIVER_NAME ": "
+			"No SRAM found in device tree\n");
+		rv = -ENODEV;
+		goto error_ofput;
+	}
+	rv = bcom_sram_init(ofn_sram, DRIVER_NAME);
+	of_node_put(ofn_sram);
+
+	if (rv) {
+		printk(KERN_ERR DRIVER_NAME ": "
+			"Error in SRAM init\n");
+		goto error_ofput;
+	}
+
+	/* Get a clean struct */
+	bcom_eng = kzalloc(sizeof(struct bcom_engine), GFP_KERNEL);
+	if (!bcom_eng) {
+		printk(KERN_ERR DRIVER_NAME ": "
+			"Can't allocate state structure\n");
+		rv = -ENOMEM;
+		goto error_sramclean;
+	}
+
+	/* Save the node */
+	bcom_eng->ofnode = op->dev.of_node;
+
+	/* Get, reserve & map io */
+	if (of_address_to_resource(op->dev.of_node, 0, &res_bcom)) {
+		printk(KERN_ERR DRIVER_NAME ": "
+			"Can't get resource\n");
+		rv = -EINVAL;
+		goto error_sramclean;
+	}
+
+	if (!request_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma),
+				DRIVER_NAME)) {
+		printk(KERN_ERR DRIVER_NAME ": "
+			"Can't request registers region\n");
+		rv = -EBUSY;
+		goto error_sramclean;
+	}
+
+	bcom_eng->regs_base = res_bcom.start;
+	bcom_eng->regs = ioremap(res_bcom.start, sizeof(struct mpc52xx_sdma));
+	if (!bcom_eng->regs) {
+		printk(KERN_ERR DRIVER_NAME ": "
+			"Can't map registers\n");
+		rv = -ENOMEM;
+		goto error_release;
+	}
+
+	/* Now, do the real init */
+	rv = bcom_engine_init();
+	if (rv)
+		goto error_unmap;
+
+	/* Done ! */
+	printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n",
+		(long)bcom_eng->regs_base);
+
+	return 0;
+
+	/* Error path */
+error_unmap:
+	iounmap(bcom_eng->regs);
+error_release:
+	release_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma));
+error_sramclean:
+	kfree(bcom_eng);
+	bcom_sram_cleanup();
+error_ofput:
+	of_node_put(op->dev.of_node);
+
+	printk(KERN_ERR "DMA: MPC52xx BestComm init failed !\n");
+
+	return rv;
+}
+
+
+static int mpc52xx_bcom_remove(struct platform_device *op)
+{
+	/* Clean up the engine */
+	bcom_engine_cleanup();
+
+	/* Cleanup SRAM */
+	bcom_sram_cleanup();
+
+	/* Release regs */
+	iounmap(bcom_eng->regs);
+	release_mem_region(bcom_eng->regs_base, sizeof(struct mpc52xx_sdma));
+
+	/* Release the node */
+	of_node_put(bcom_eng->ofnode);
+
+	/* Release memory */
+	kfree(bcom_eng);
+	bcom_eng = NULL;
+
+	return 0;
+}
+
+static struct of_device_id mpc52xx_bcom_of_match[] = {
+	{ .compatible = "fsl,mpc5200-bestcomm", },
+	{ .compatible = "mpc5200-bestcomm", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
+
+
+static struct platform_driver mpc52xx_bcom_of_platform_driver = {
+	.probe		= mpc52xx_bcom_probe,
+	.remove		= mpc52xx_bcom_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = mpc52xx_bcom_of_match,
+	},
+};
+
+
+/* ======================================================================== */
+/* Module                                                                   */
+/* ======================================================================== */
+
+static int __init
+mpc52xx_bcom_init(void)
+{
+	return platform_driver_register(&mpc52xx_bcom_of_platform_driver);
+}
+
+static void __exit
+mpc52xx_bcom_exit(void)
+{
+	platform_driver_unregister(&mpc52xx_bcom_of_platform_driver);
+}
+
+/* If we're not a module, we must make sure everything is setup before  */
+/* anyone tries to use us ... that's why we use subsys_initcall instead */
+/* of module_init. */
+subsys_initcall(mpc52xx_bcom_init);
+module_exit(mpc52xx_bcom_exit);
+
+MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
+MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
+MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
+MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/dma/bestcomm/fec.c b/drivers/dma/bestcomm/fec.c
new file mode 100644
index 0000000..7f1fb1c
--- /dev/null
+++ b/drivers/dma/bestcomm/fec.c
@@ -0,0 +1,270 @@
+/*
+ * Bestcomm FEC tasks driver
+ *
+ *
+ * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003-2004 MontaVista, Software, Inc.
+ *                         ( by Dale Farnsworth <dfarnsworth@mvista.com> )
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/bestcomm_priv.h>
+#include <linux/fsl/bestcomm/fec.h>
+
+
+/* ======================================================================== */
+/* Task image/var/inc                                                       */
+/* ======================================================================== */
+
+/* fec tasks images */
+extern u32 bcom_fec_rx_task[];
+extern u32 bcom_fec_tx_task[];
+
+/* rx task vars that need to be set before enabling the task */
+struct bcom_fec_rx_var {
+	u32 enable;		/* (u16*) address of task's control register */
+	u32 fifo;		/* (u32*) address of fec's fifo */
+	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
+	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
+	u32 bd_start;		/* (struct bcom_bd*) current bd */
+	u32 buffer_size;	/* size of receive buffer */
+};
+
+/* rx task incs that need to be set before enabling the task */
+struct bcom_fec_rx_inc {
+	u16 pad0;
+	s16 incr_bytes;
+	u16 pad1;
+	s16 incr_dst;
+	u16 pad2;
+	s16 incr_dst_ma;
+};
+
+/* tx task vars that need to be set before enabling the task */
+struct bcom_fec_tx_var {
+	u32 DRD;		/* (u32*) address of self-modified DRD */
+	u32 fifo;		/* (u32*) address of fec's fifo */
+	u32 enable;		/* (u16*) address of task's control register */
+	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
+	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
+	u32 bd_start;		/* (struct bcom_bd*) current bd */
+	u32 buffer_size;	/* set by uCode for each packet */
+};
+
+/* tx task incs that need to be set before enabling the task */
+struct bcom_fec_tx_inc {
+	u16 pad0;
+	s16 incr_bytes;
+	u16 pad1;
+	s16 incr_src;
+	u16 pad2;
+	s16 incr_src_ma;
+};
+
+/* private structure in the task */
+struct bcom_fec_priv {
+	phys_addr_t	fifo;
+	int		maxbufsize;
+};
+
+
+/* ======================================================================== */
+/* Task support code                                                        */
+/* ======================================================================== */
+
+struct bcom_task *
+bcom_fec_rx_init(int queue_len, phys_addr_t fifo, int maxbufsize)
+{
+	struct bcom_task *tsk;
+	struct bcom_fec_priv *priv;
+
+	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_fec_bd),
+				sizeof(struct bcom_fec_priv));
+	if (!tsk)
+		return NULL;
+
+	tsk->flags = BCOM_FLAGS_NONE;
+
+	priv = tsk->priv;
+	priv->fifo = fifo;
+	priv->maxbufsize = maxbufsize;
+
+	if (bcom_fec_rx_reset(tsk)) {
+		bcom_task_free(tsk);
+		return NULL;
+	}
+
+	return tsk;
+}
+EXPORT_SYMBOL_GPL(bcom_fec_rx_init);
+
+int
+bcom_fec_rx_reset(struct bcom_task *tsk)
+{
+	struct bcom_fec_priv *priv = tsk->priv;
+	struct bcom_fec_rx_var *var;
+	struct bcom_fec_rx_inc *inc;
+
+	/* Shutdown the task */
+	bcom_disable_task(tsk->tasknum);
+
+	/* Reset the microcode */
+	var = (struct bcom_fec_rx_var *) bcom_task_var(tsk->tasknum);
+	inc = (struct bcom_fec_rx_inc *) bcom_task_inc(tsk->tasknum);
+
+	if (bcom_load_image(tsk->tasknum, bcom_fec_rx_task))
+		return -1;
+
+	var->enable	= bcom_eng->regs_base +
+				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
+	var->fifo	= (u32) priv->fifo;
+	var->bd_base	= tsk->bd_pa;
+	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
+	var->bd_start	= tsk->bd_pa;
+	var->buffer_size = priv->maxbufsize;
+
+	inc->incr_bytes	= -(s16)sizeof(u32);	/* These should be in the   */
+	inc->incr_dst	= sizeof(u32);		/* task image, but we stick */
+	inc->incr_dst_ma= sizeof(u8);		/* to the official ones     */
+
+	/* Reset the BDs */
+	tsk->index = 0;
+	tsk->outdex = 0;
+
+	memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+
+	/* Configure some stuff */
+	bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_RX_BD_PRAGMA);
+	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
+
+	out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_FEC_RX], BCOM_IPR_FEC_RX);
+
+	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(bcom_fec_rx_reset);
+
+void
+bcom_fec_rx_release(struct bcom_task *tsk)
+{
+	/* Nothing special for the FEC tasks */
+	bcom_task_free(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_fec_rx_release);
+
+
+
+	/* Return 2nd to last DRD */
+	/* This is an ugly hack, but at least it's only done
+	   once at initialization */
+static u32 *self_modified_drd(int tasknum)
+{
+	u32 *desc;
+	int num_descs;
+	int drd_count;
+	int i;
+
+	num_descs = bcom_task_num_descs(tasknum);
+	desc = bcom_task_desc(tasknum) + num_descs - 1;
+	drd_count = 0;
+	for (i=0; i<num_descs; i++, desc--)
+		if (bcom_desc_is_drd(*desc) && ++drd_count == 3)
+			break;
+	return desc;
+}
+
+struct bcom_task *
+bcom_fec_tx_init(int queue_len, phys_addr_t fifo)
+{
+	struct bcom_task *tsk;
+	struct bcom_fec_priv *priv;
+
+	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_fec_bd),
+				sizeof(struct bcom_fec_priv));
+	if (!tsk)
+		return NULL;
+
+	tsk->flags = BCOM_FLAGS_ENABLE_TASK;
+
+	priv = tsk->priv;
+	priv->fifo = fifo;
+
+	if (bcom_fec_tx_reset(tsk)) {
+		bcom_task_free(tsk);
+		return NULL;
+	}
+
+	return tsk;
+}
+EXPORT_SYMBOL_GPL(bcom_fec_tx_init);
+
+int
+bcom_fec_tx_reset(struct bcom_task *tsk)
+{
+	struct bcom_fec_priv *priv = tsk->priv;
+	struct bcom_fec_tx_var *var;
+	struct bcom_fec_tx_inc *inc;
+
+	/* Shutdown the task */
+	bcom_disable_task(tsk->tasknum);
+
+	/* Reset the microcode */
+	var = (struct bcom_fec_tx_var *) bcom_task_var(tsk->tasknum);
+	inc = (struct bcom_fec_tx_inc *) bcom_task_inc(tsk->tasknum);
+
+	if (bcom_load_image(tsk->tasknum, bcom_fec_tx_task))
+		return -1;
+
+	var->enable	= bcom_eng->regs_base +
+				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
+	var->fifo	= (u32) priv->fifo;
+	var->DRD	= bcom_sram_va2pa(self_modified_drd(tsk->tasknum));
+	var->bd_base	= tsk->bd_pa;
+	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
+	var->bd_start	= tsk->bd_pa;
+
+	inc->incr_bytes	= -(s16)sizeof(u32);	/* These should be in the   */
+	inc->incr_src	= sizeof(u32);		/* task image, but we stick */
+	inc->incr_src_ma= sizeof(u8);		/* to the official ones     */
+
+	/* Reset the BDs */
+	tsk->index = 0;
+	tsk->outdex = 0;
+
+	memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+
+	/* Configure some stuff */
+	bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_TX_BD_PRAGMA);
+	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
+
+	out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_FEC_TX], BCOM_IPR_FEC_TX);
+
+	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(bcom_fec_tx_reset);
+
+void
+bcom_fec_tx_release(struct bcom_task *tsk)
+{
+	/* Nothing special for the FEC tasks */
+	bcom_task_free(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_fec_tx_release);
+
+
+MODULE_DESCRIPTION("BestComm FEC tasks driver");
+MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/dma/bestcomm/gen_bd.c b/drivers/dma/bestcomm/gen_bd.c
new file mode 100644
index 0000000..1a5b22d
--- /dev/null
+++ b/drivers/dma/bestcomm/gen_bd.c
@@ -0,0 +1,354 @@
+/*
+ * Driver for MPC52xx processor BestComm General Buffer Descriptor
+ *
+ * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2006 AppSpec Computer Technologies Corp.
+ *                    Jeff Gibbons <jeff.gibbons@appspec.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+
+#include <asm/mpc52xx.h>
+#include <asm/mpc52xx_psc.h>
+
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/bestcomm_priv.h>
+#include <linux/fsl/bestcomm/gen_bd.h>
+
+
+/* ======================================================================== */
+/* Task image/var/inc                                                       */
+/* ======================================================================== */
+
+/* gen_bd tasks images */
+extern u32 bcom_gen_bd_rx_task[];
+extern u32 bcom_gen_bd_tx_task[];
+
+/* rx task vars that need to be set before enabling the task */
+struct bcom_gen_bd_rx_var {
+	u32 enable;		/* (u16*) address of task's control register */
+	u32 fifo;		/* (u32*) address of gen_bd's fifo */
+	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
+	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
+	u32 bd_start;		/* (struct bcom_bd*) current bd */
+	u32 buffer_size;	/* size of receive buffer */
+};
+
+/* rx task incs that need to be set before enabling the task */
+struct bcom_gen_bd_rx_inc {
+	u16 pad0;
+	s16 incr_bytes;
+	u16 pad1;
+	s16 incr_dst;
+};
+
+/* tx task vars that need to be set before enabling the task */
+struct bcom_gen_bd_tx_var {
+	u32 fifo;		/* (u32*) address of gen_bd's fifo */
+	u32 enable;		/* (u16*) address of task's control register */
+	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
+	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
+	u32 bd_start;		/* (struct bcom_bd*) current bd */
+	u32 buffer_size;	/* set by uCode for each packet */
+};
+
+/* tx task incs that need to be set before enabling the task */
+struct bcom_gen_bd_tx_inc {
+	u16 pad0;
+	s16 incr_bytes;
+	u16 pad1;
+	s16 incr_src;
+	u16 pad2;
+	s16 incr_src_ma;
+};
+
+/* private structure */
+struct bcom_gen_bd_priv {
+	phys_addr_t	fifo;
+	int		initiator;
+	int		ipr;
+	int		maxbufsize;
+};
+
+
+/* ======================================================================== */
+/* Task support code                                                        */
+/* ======================================================================== */
+
+struct bcom_task *
+bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
+			int initiator, int ipr, int maxbufsize)
+{
+	struct bcom_task *tsk;
+	struct bcom_gen_bd_priv *priv;
+
+	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
+			sizeof(struct bcom_gen_bd_priv));
+	if (!tsk)
+		return NULL;
+
+	tsk->flags = BCOM_FLAGS_NONE;
+
+	priv = tsk->priv;
+	priv->fifo	= fifo;
+	priv->initiator	= initiator;
+	priv->ipr	= ipr;
+	priv->maxbufsize = maxbufsize;
+
+	if (bcom_gen_bd_rx_reset(tsk)) {
+		bcom_task_free(tsk);
+		return NULL;
+	}
+
+	return tsk;
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_init);
+
+int
+bcom_gen_bd_rx_reset(struct bcom_task *tsk)
+{
+	struct bcom_gen_bd_priv *priv = tsk->priv;
+	struct bcom_gen_bd_rx_var *var;
+	struct bcom_gen_bd_rx_inc *inc;
+
+	/* Shutdown the task */
+	bcom_disable_task(tsk->tasknum);
+
+	/* Reset the microcode */
+	var = (struct bcom_gen_bd_rx_var *) bcom_task_var(tsk->tasknum);
+	inc = (struct bcom_gen_bd_rx_inc *) bcom_task_inc(tsk->tasknum);
+
+	if (bcom_load_image(tsk->tasknum, bcom_gen_bd_rx_task))
+		return -1;
+
+	var->enable	= bcom_eng->regs_base +
+				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
+	var->fifo	= (u32) priv->fifo;
+	var->bd_base	= tsk->bd_pa;
+	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
+	var->bd_start	= tsk->bd_pa;
+	var->buffer_size = priv->maxbufsize;
+
+	inc->incr_bytes	= -(s16)sizeof(u32);
+	inc->incr_dst	= sizeof(u32);
+
+	/* Reset the BDs */
+	tsk->index = 0;
+	tsk->outdex = 0;
+
+	memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+
+	/* Configure some stuff */
+	bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA);
+	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
+
+	out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
+	bcom_set_initiator(tsk->tasknum, priv->initiator);
+
+	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_reset);
+
+void
+bcom_gen_bd_rx_release(struct bcom_task *tsk)
+{
+	/* Nothing special for the GenBD tasks */
+	bcom_task_free(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_release);
+
+
+extern struct bcom_task *
+bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
+			int initiator, int ipr)
+{
+	struct bcom_task *tsk;
+	struct bcom_gen_bd_priv *priv;
+
+	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
+			sizeof(struct bcom_gen_bd_priv));
+	if (!tsk)
+		return NULL;
+
+	tsk->flags = BCOM_FLAGS_NONE;
+
+	priv = tsk->priv;
+	priv->fifo	= fifo;
+	priv->initiator	= initiator;
+	priv->ipr	= ipr;
+
+	if (bcom_gen_bd_tx_reset(tsk)) {
+		bcom_task_free(tsk);
+		return NULL;
+	}
+
+	return tsk;
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_init);
+
+int
+bcom_gen_bd_tx_reset(struct bcom_task *tsk)
+{
+	struct bcom_gen_bd_priv *priv = tsk->priv;
+	struct bcom_gen_bd_tx_var *var;
+	struct bcom_gen_bd_tx_inc *inc;
+
+	/* Shutdown the task */
+	bcom_disable_task(tsk->tasknum);
+
+	/* Reset the microcode */
+	var = (struct bcom_gen_bd_tx_var *) bcom_task_var(tsk->tasknum);
+	inc = (struct bcom_gen_bd_tx_inc *) bcom_task_inc(tsk->tasknum);
+
+	if (bcom_load_image(tsk->tasknum, bcom_gen_bd_tx_task))
+		return -1;
+
+	var->enable	= bcom_eng->regs_base +
+				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
+	var->fifo	= (u32) priv->fifo;
+	var->bd_base	= tsk->bd_pa;
+	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
+	var->bd_start	= tsk->bd_pa;
+
+	inc->incr_bytes	= -(s16)sizeof(u32);
+	inc->incr_src	= sizeof(u32);
+	inc->incr_src_ma = sizeof(u8);
+
+	/* Reset the BDs */
+	tsk->index = 0;
+	tsk->outdex = 0;
+
+	memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+
+	/* Configure some stuff */
+	bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA);
+	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
+
+	out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
+	bcom_set_initiator(tsk->tasknum, priv->initiator);
+
+	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_reset);
+
+void
+bcom_gen_bd_tx_release(struct bcom_task *tsk)
+{
+	/* Nothing special for the GenBD tasks */
+	bcom_task_free(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release);
+
+/* ---------------------------------------------------------------------
+ * PSC support code
+ */
+
+/**
+ * bcom_psc_parameters - Bestcomm initialization value table for PSC devices
+ *
+ * This structure is only used internally.  It is a lookup table for PSC
+ * specific parameters to bestcomm tasks.
+ */
+static struct bcom_psc_params {
+	int rx_initiator;
+	int rx_ipr;
+	int tx_initiator;
+	int tx_ipr;
+} bcom_psc_params[] = {
+	[0] = {
+		.rx_initiator = BCOM_INITIATOR_PSC1_RX,
+		.rx_ipr = BCOM_IPR_PSC1_RX,
+		.tx_initiator = BCOM_INITIATOR_PSC1_TX,
+		.tx_ipr = BCOM_IPR_PSC1_TX,
+	},
+	[1] = {
+		.rx_initiator = BCOM_INITIATOR_PSC2_RX,
+		.rx_ipr = BCOM_IPR_PSC2_RX,
+		.tx_initiator = BCOM_INITIATOR_PSC2_TX,
+		.tx_ipr = BCOM_IPR_PSC2_TX,
+	},
+	[2] = {
+		.rx_initiator = BCOM_INITIATOR_PSC3_RX,
+		.rx_ipr = BCOM_IPR_PSC3_RX,
+		.tx_initiator = BCOM_INITIATOR_PSC3_TX,
+		.tx_ipr = BCOM_IPR_PSC3_TX,
+	},
+	[3] = {
+		.rx_initiator = BCOM_INITIATOR_PSC4_RX,
+		.rx_ipr = BCOM_IPR_PSC4_RX,
+		.tx_initiator = BCOM_INITIATOR_PSC4_TX,
+		.tx_ipr = BCOM_IPR_PSC4_TX,
+	},
+	[4] = {
+		.rx_initiator = BCOM_INITIATOR_PSC5_RX,
+		.rx_ipr = BCOM_IPR_PSC5_RX,
+		.tx_initiator = BCOM_INITIATOR_PSC5_TX,
+		.tx_ipr = BCOM_IPR_PSC5_TX,
+	},
+	[5] = {
+		.rx_initiator = BCOM_INITIATOR_PSC6_RX,
+		.rx_ipr = BCOM_IPR_PSC6_RX,
+		.tx_initiator = BCOM_INITIATOR_PSC6_TX,
+		.tx_ipr = BCOM_IPR_PSC6_TX,
+	},
+};
+
+/**
+ * bcom_psc_gen_bd_rx_init - Allocate a receive bcom_task for a PSC port
+ * @psc_num:	Number of the PSC to allocate a task for
+ * @queue_len:	number of buffer descriptors to allocate for the task
+ * @fifo:	physical address of FIFO register
+ * @maxbufsize:	Maximum receive data size in bytes.
+ *
+ * Allocate a bestcomm task structure for receiving data from a PSC.
+ */
+struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
+					   phys_addr_t fifo, int maxbufsize)
+{
+	if (psc_num >= MPC52xx_PSC_MAXNUM)
+		return NULL;
+
+	return bcom_gen_bd_rx_init(queue_len, fifo,
+				   bcom_psc_params[psc_num].rx_initiator,
+				   bcom_psc_params[psc_num].rx_ipr,
+				   maxbufsize);
+}
+EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_rx_init);
+
+/**
+ * bcom_psc_gen_bd_tx_init - Allocate a transmit bcom_task for a PSC port
+ * @psc_num:	Number of the PSC to allocate a task for
+ * @queue_len:	number of buffer descriptors to allocate for the task
+ * @fifo:	physical address of FIFO register
+ *
+ * Allocate a bestcomm task structure for transmitting data to a PSC.
+ */
+struct bcom_task *
+bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, phys_addr_t fifo)
+{
+	struct psc;
+	return bcom_gen_bd_tx_init(queue_len, fifo,
+				   bcom_psc_params[psc_num].tx_initiator,
+				   bcom_psc_params[psc_num].tx_ipr);
+}
+EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init);
+
+
+MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
+MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/dma/bestcomm/sram.c b/drivers/dma/bestcomm/sram.c
new file mode 100644
index 0000000..5e2ed30
--- /dev/null
+++ b/drivers/dma/bestcomm/sram.c
@@ -0,0 +1,178 @@
+/*
+ * Simple memory allocator for on-board SRAM
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/of.h>
+
+#include <asm/io.h>
+#include <asm/mmu.h>
+
+#include <linux/fsl/bestcomm/sram.h>
+
+
+/* Struct keeping our 'state' */
+struct bcom_sram *bcom_sram = NULL;
+EXPORT_SYMBOL_GPL(bcom_sram);	/* needed for inline functions */
+
+
+/* ======================================================================== */
+/* Public API                                                               */
+/* ======================================================================== */
+/* DO NOT USE in interrupts, if needed in irq handler, we should use the
+   _irqsave version of the spin_locks */
+
+int bcom_sram_init(struct device_node *sram_node, char *owner)
+{
+	int rv;
+	const u32 *regaddr_p;
+	u64 regaddr64, size64;
+	unsigned int psize;
+
+	/* Create our state struct */
+	if (bcom_sram) {
+		printk(KERN_ERR "%s: bcom_sram_init: "
+			"Already initialized !\n", owner);
+		return -EBUSY;
+	}
+
+	bcom_sram = kmalloc(sizeof(struct bcom_sram), GFP_KERNEL);
+	if (!bcom_sram) {
+		printk(KERN_ERR "%s: bcom_sram_init: "
+			"Couldn't allocate internal state !\n", owner);
+		return -ENOMEM;
+	}
+
+	/* Get address and size of the sram */
+	regaddr_p = of_get_address(sram_node, 0, &size64, NULL);
+	if (!regaddr_p) {
+		printk(KERN_ERR "%s: bcom_sram_init: "
+			"Invalid device node !\n", owner);
+		rv = -EINVAL;
+		goto error_free;
+	}
+
+	regaddr64 = of_translate_address(sram_node, regaddr_p);
+
+	bcom_sram->base_phys = (phys_addr_t) regaddr64;
+	bcom_sram->size = (unsigned int) size64;
+
+	/* Request region */
+	if (!request_mem_region(bcom_sram->base_phys, bcom_sram->size, owner)) {
+		printk(KERN_ERR "%s: bcom_sram_init: "
+			"Couldn't request region !\n", owner);
+		rv = -EBUSY;
+		goto error_free;
+	}
+
+	/* Map SRAM */
+		/* sram is not really __iomem */
+	bcom_sram->base_virt = (void*) ioremap(bcom_sram->base_phys, bcom_sram->size);
+
+	if (!bcom_sram->base_virt) {
+		printk(KERN_ERR "%s: bcom_sram_init: "
+			"Map error SRAM zone 0x%08lx (0x%0x)!\n",
+			owner, (long)bcom_sram->base_phys, bcom_sram->size );
+		rv = -ENOMEM;
+		goto error_release;
+	}
+
+	/* Create an rheap (defaults to 32 bits word alignment) */
+	bcom_sram->rh = rh_create(4);
+
+	/* Attach the free zones */
+#if 0
+	/* Currently disabled ... for future use only */
+	reg_addr_p = of_get_property(sram_node, "available", &psize);
+#else
+	regaddr_p = NULL;
+	psize = 0;
+#endif
+
+	if (!regaddr_p || !psize) {
+		/* Attach the whole zone */
+		rh_attach_region(bcom_sram->rh, 0, bcom_sram->size);
+	} else {
+		/* Attach each zone independently */
+		while (psize >= 2 * sizeof(u32)) {
+			phys_addr_t zbase = of_translate_address(sram_node, regaddr_p);
+			rh_attach_region(bcom_sram->rh, zbase - bcom_sram->base_phys, regaddr_p[1]);
+			regaddr_p += 2;
+			psize -= 2 * sizeof(u32);
+		}
+	}
+
+	/* Init our spinlock */
+	spin_lock_init(&bcom_sram->lock);
+
+	return 0;
+
+error_release:
+	release_mem_region(bcom_sram->base_phys, bcom_sram->size);
+error_free:
+	kfree(bcom_sram);
+	bcom_sram = NULL;
+
+	return rv;
+}
+EXPORT_SYMBOL_GPL(bcom_sram_init);
+
+void bcom_sram_cleanup(void)
+{
+	/* Free resources */
+	if (bcom_sram) {
+		rh_destroy(bcom_sram->rh);
+		iounmap((void __iomem *)bcom_sram->base_virt);
+		release_mem_region(bcom_sram->base_phys, bcom_sram->size);
+		kfree(bcom_sram);
+		bcom_sram = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(bcom_sram_cleanup);
+
+void* bcom_sram_alloc(int size, int align, phys_addr_t *phys)
+{
+	unsigned long offset;
+
+	spin_lock(&bcom_sram->lock);
+	offset = rh_alloc_align(bcom_sram->rh, size, align, NULL);
+	spin_unlock(&bcom_sram->lock);
+
+	if (IS_ERR_VALUE(offset))
+		return NULL;
+
+	*phys = bcom_sram->base_phys + offset;
+	return bcom_sram->base_virt + offset;
+}
+EXPORT_SYMBOL_GPL(bcom_sram_alloc);
+
+void bcom_sram_free(void *ptr)
+{
+	unsigned long offset;
+
+	if (!ptr)
+		return;
+
+	offset = ptr - bcom_sram->base_virt;
+
+	spin_lock(&bcom_sram->lock);
+	rh_free(bcom_sram->rh, offset);
+	spin_unlock(&bcom_sram->lock);
+}
+EXPORT_SYMBOL_GPL(bcom_sram_free);
+
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index 2933d08..c077be0 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -40,8 +40,8 @@
 #include <asm/delay.h>
 #include <asm/mpc52xx.h>
 
-#include <sysdev/bestcomm/bestcomm.h>
-#include <sysdev/bestcomm/fec.h>
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/fec.h>
 
 #include "fec_mpc52xx.h"
 
diff --git a/include/linux/fsl/bestcomm/ata.h b/include/linux/fsl/bestcomm/ata.h
new file mode 100644
index 0000000..0b23718
--- /dev/null
+++ b/include/linux/fsl/bestcomm/ata.h
@@ -0,0 +1,30 @@
+/*
+ * Header for Bestcomm ATA task driver
+ *
+ *
+ * Copyright (C) 2006 Freescale - John Rigby
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __BESTCOMM_ATA_H__
+#define __BESTCOMM_ATA_H__
+
+
+struct bcom_ata_bd {
+	u32	status;
+	u32	src_pa;
+	u32	dst_pa;
+};
+
+extern struct bcom_task * bcom_ata_init(int queue_len, int maxbufsize);
+extern void bcom_ata_rx_prepare(struct bcom_task *tsk);
+extern void bcom_ata_tx_prepare(struct bcom_task *tsk);
+extern void bcom_ata_reset_bd(struct bcom_task *tsk);
+extern void bcom_ata_release(struct bcom_task *tsk);
+
+#endif /* __BESTCOMM_ATA_H__ */
+
diff --git a/include/linux/fsl/bestcomm/bestcomm.h b/include/linux/fsl/bestcomm/bestcomm.h
new file mode 100644
index 0000000..a0e2e6b
--- /dev/null
+++ b/include/linux/fsl/bestcomm/bestcomm.h
@@ -0,0 +1,213 @@
+/*
+ * Public header for the MPC52xx processor BestComm driver
+ *
+ *
+ * Copyright (C) 2006      Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2005      Varma Electronics Oy,
+ *                         ( by Andrey Volkov <avolkov@varma-el.com> )
+ * Copyright (C) 2003-2004 MontaVista, Software, Inc.
+ *                         ( by Dale Farnsworth <dfarnsworth@mvista.com> )
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __BESTCOMM_H__
+#define __BESTCOMM_H__
+
+/**
+ * struct bcom_bd - Structure describing a generic BestComm buffer descriptor
+ * @status: The current status of this buffer. Exact meaning depends on the
+ *          task type
+ * @data: An array of u32 extra data.  Size of array is task dependent.
+ *
+ * Note: Don't dereference a bcom_bd pointer as an array.  The size of the
+ *       bcom_bd is variable.  Use bcom_get_bd() instead.
+ */
+struct bcom_bd {
+	u32	status;
+	u32	data[0];	/* variable payload size */
+};
+
+/* ======================================================================== */
+/* Generic task management                                                   */
+/* ======================================================================== */
+
+/**
+ * struct bcom_task - Structure describing a loaded BestComm task
+ *
+ * This structure is never built by the driver it self. It's built and
+ * filled the intermediate layer of the BestComm API, the task dependent
+ * support code.
+ *
+ * Most likely you don't need to poke around inside this structure. The
+ * fields are exposed in the header just for the sake of inline functions
+ */
+struct bcom_task {
+	unsigned int	tasknum;
+	unsigned int	flags;
+	int		irq;
+
+	struct bcom_bd	*bd;
+	phys_addr_t	bd_pa;
+	void		**cookie;
+	unsigned short	index;
+	unsigned short	outdex;
+	unsigned int	num_bd;
+	unsigned int	bd_size;
+
+	void*		priv;
+};
+
+#define BCOM_FLAGS_NONE         0x00000000ul
+#define BCOM_FLAGS_ENABLE_TASK  (1ul <<  0)
+
+/**
+ * bcom_enable - Enable a BestComm task
+ * @tsk: The BestComm task structure
+ *
+ * This function makes sure the given task is enabled and can be run
+ * by the BestComm engine as needed
+ */
+extern void bcom_enable(struct bcom_task *tsk);
+
+/**
+ * bcom_disable - Disable a BestComm task
+ * @tsk: The BestComm task structure
+ *
+ * This function disable a given task, making sure it's not executed
+ * by the BestComm engine.
+ */
+extern void bcom_disable(struct bcom_task *tsk);
+
+
+/**
+ * bcom_get_task_irq - Returns the irq number of a BestComm task
+ * @tsk: The BestComm task structure
+ */
+static inline int
+bcom_get_task_irq(struct bcom_task *tsk) {
+	return tsk->irq;
+}
+
+/* ======================================================================== */
+/* BD based tasks helpers                                                   */
+/* ======================================================================== */
+
+#define BCOM_BD_READY	0x40000000ul
+
+/** _bcom_next_index - Get next input index.
+ * @tsk: pointer to task structure
+ *
+ * Support function; Device drivers should not call this
+ */
+static inline int
+_bcom_next_index(struct bcom_task *tsk)
+{
+	return ((tsk->index + 1) == tsk->num_bd) ? 0 : tsk->index + 1;
+}
+
+/** _bcom_next_outdex - Get next output index.
+ * @tsk: pointer to task structure
+ *
+ * Support function; Device drivers should not call this
+ */
+static inline int
+_bcom_next_outdex(struct bcom_task *tsk)
+{
+	return ((tsk->outdex + 1) == tsk->num_bd) ? 0 : tsk->outdex + 1;
+}
+
+/**
+ * bcom_queue_empty - Checks if a BestComm task BD queue is empty
+ * @tsk: The BestComm task structure
+ */
+static inline int
+bcom_queue_empty(struct bcom_task *tsk)
+{
+	return tsk->index == tsk->outdex;
+}
+
+/**
+ * bcom_queue_full - Checks if a BestComm task BD queue is full
+ * @tsk: The BestComm task structure
+ */
+static inline int
+bcom_queue_full(struct bcom_task *tsk)
+{
+	return tsk->outdex == _bcom_next_index(tsk);
+}
+
+/**
+ * bcom_get_bd - Get a BD from the queue
+ * @tsk: The BestComm task structure
+ * index: Index of the BD to fetch
+ */
+static inline struct bcom_bd
+*bcom_get_bd(struct bcom_task *tsk, unsigned int index)
+{
+	/* A cast to (void*) so the address can be incremented by the
+	 * real size instead of by sizeof(struct bcom_bd) */
+	return ((void *)tsk->bd) + (index * tsk->bd_size);
+}
+
+/**
+ * bcom_buffer_done - Checks if a BestComm 
+ * @tsk: The BestComm task structure
+ */
+static inline int
+bcom_buffer_done(struct bcom_task *tsk)
+{
+	struct bcom_bd *bd;
+	if (bcom_queue_empty(tsk))
+		return 0;
+
+	bd = bcom_get_bd(tsk, tsk->outdex);
+	return !(bd->status & BCOM_BD_READY);
+}
+
+/**
+ * bcom_prepare_next_buffer - clear status of next available buffer.
+ * @tsk: The BestComm task structure
+ *
+ * Returns pointer to next buffer descriptor
+ */
+static inline struct bcom_bd *
+bcom_prepare_next_buffer(struct bcom_task *tsk)
+{
+	struct bcom_bd *bd;
+
+	bd = bcom_get_bd(tsk, tsk->index);
+	bd->status = 0;	/* cleanup last status */
+	return bd;
+}
+
+static inline void
+bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie)
+{
+	struct bcom_bd *bd = bcom_get_bd(tsk, tsk->index);
+
+	tsk->cookie[tsk->index] = cookie;
+	mb();	/* ensure the bd is really up-to-date */
+	bd->status |= BCOM_BD_READY;
+	tsk->index = _bcom_next_index(tsk);
+	if (tsk->flags & BCOM_FLAGS_ENABLE_TASK)
+		bcom_enable(tsk);
+}
+
+static inline void *
+bcom_retrieve_buffer(struct bcom_task *tsk, u32 *p_status, struct bcom_bd **p_bd)
+{
+	void *cookie = tsk->cookie[tsk->outdex];
+	struct bcom_bd *bd = bcom_get_bd(tsk, tsk->outdex);
+
+	if (p_status)
+		*p_status = bd->status;
+	if (p_bd)
+		*p_bd = bd;
+	tsk->outdex = _bcom_next_outdex(tsk);
+	return cookie;
+}
+
+#endif /* __BESTCOMM_H__ */
diff --git a/include/linux/fsl/bestcomm/bestcomm_priv.h b/include/linux/fsl/bestcomm/bestcomm_priv.h
new file mode 100644
index 0000000..3b52f3f
--- /dev/null
+++ b/include/linux/fsl/bestcomm/bestcomm_priv.h
@@ -0,0 +1,350 @@
+/*
+ * Private header for the MPC52xx processor BestComm driver
+ *
+ * By private, we mean that driver should not use it directly. It's meant
+ * to be used by the BestComm engine driver itself and by the intermediate
+ * layer between the core and the drivers.
+ *
+ * Copyright (C) 2006      Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2005      Varma Electronics Oy,
+ *                         ( by Andrey Volkov <avolkov@varma-el.com> )
+ * Copyright (C) 2003-2004 MontaVista, Software, Inc.
+ *                         ( by Dale Farnsworth <dfarnsworth@mvista.com> )
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __BESTCOMM_PRIV_H__
+#define __BESTCOMM_PRIV_H__
+
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <asm/io.h>
+#include <asm/mpc52xx.h>
+
+#include "sram.h"
+
+
+/* ======================================================================== */
+/* Engine related stuff                                                     */
+/* ======================================================================== */
+
+/* Zones sizes and needed alignments */
+#define BCOM_MAX_TASKS		16
+#define BCOM_MAX_VAR		24
+#define BCOM_MAX_INC		8
+#define BCOM_MAX_FDT		64
+#define BCOM_MAX_CTX		20
+#define BCOM_CTX_SIZE		(BCOM_MAX_CTX * sizeof(u32))
+#define BCOM_CTX_ALIGN		0x100
+#define BCOM_VAR_SIZE		(BCOM_MAX_VAR * sizeof(u32))
+#define BCOM_INC_SIZE		(BCOM_MAX_INC * sizeof(u32))
+#define BCOM_VAR_ALIGN		0x80
+#define BCOM_FDT_SIZE		(BCOM_MAX_FDT * sizeof(u32))
+#define BCOM_FDT_ALIGN		0x100
+
+/**
+ * struct bcom_tdt - Task Descriptor Table Entry
+ *
+ */
+struct bcom_tdt {
+	u32 start;
+	u32 stop;
+	u32 var;
+	u32 fdt;
+	u32 exec_status;	/* used internally by BestComm engine */
+	u32 mvtp;		/* used internally by BestComm engine */
+	u32 context;
+	u32 litbase;
+};
+
+/**
+ * struct bcom_engine
+ *
+ * This holds all info needed globaly to handle the engine
+ */
+struct bcom_engine {
+	struct device_node		*ofnode;
+	struct mpc52xx_sdma __iomem     *regs;
+	phys_addr_t                      regs_base;
+
+	struct bcom_tdt			*tdt;
+	u32				*ctx;
+	u32				*var;
+	u32				*fdt;
+
+	spinlock_t			lock;
+};
+
+extern struct bcom_engine *bcom_eng;
+
+
+/* ======================================================================== */
+/* Tasks related stuff                                                      */
+/* ======================================================================== */
+
+/* Tasks image header */
+#define BCOM_TASK_MAGIC		0x4243544B	/* 'BCTK' */
+
+struct bcom_task_header {
+	u32	magic;
+	u8	desc_size;	/* the size fields     */
+	u8	var_size;	/* are given in number */
+	u8	inc_size;	/* of 32-bits words    */
+	u8	first_var;
+	u8	reserved[8];
+};
+
+/* Descriptors structure & co */
+#define BCOM_DESC_NOP		0x000001f8
+#define BCOM_LCD_MASK		0x80000000
+#define BCOM_DRD_EXTENDED	0x40000000
+#define BCOM_DRD_INITIATOR_SHIFT	21
+
+/* Tasks pragma */
+#define BCOM_PRAGMA_BIT_RSV		7	/* reserved pragma bit */
+#define BCOM_PRAGMA_BIT_PRECISE_INC	6	/* increment 0=when possible, */
+						/*           1=iter end */
+#define BCOM_PRAGMA_BIT_RST_ERROR_NO	5	/* don't reset errors on */
+						/* task enable */
+#define BCOM_PRAGMA_BIT_PACK		4	/* pack data enable */
+#define BCOM_PRAGMA_BIT_INTEGER		3	/* data alignment */
+						/* 0=frac(msb), 1=int(lsb) */
+#define BCOM_PRAGMA_BIT_SPECREAD	2	/* XLB speculative read */
+#define BCOM_PRAGMA_BIT_CW		1	/* write line buffer enable */
+#define BCOM_PRAGMA_BIT_RL		0	/* read line buffer enable */
+
+	/* Looks like XLB speculative read generates XLB errors when a buffer
+	 * is at the end of the physical memory. i.e. when accessing the
+	 * lasts words, the engine tries to prefetch the next but there is no
+	 * next ...
+	 */
+#define BCOM_STD_PRAGMA		((0 << BCOM_PRAGMA_BIT_RSV)		| \
+				 (0 << BCOM_PRAGMA_BIT_PRECISE_INC)	| \
+				 (0 << BCOM_PRAGMA_BIT_RST_ERROR_NO)	| \
+				 (0 << BCOM_PRAGMA_BIT_PACK)		| \
+				 (0 << BCOM_PRAGMA_BIT_INTEGER)		| \
+				 (0 << BCOM_PRAGMA_BIT_SPECREAD)	| \
+				 (1 << BCOM_PRAGMA_BIT_CW)		| \
+				 (1 << BCOM_PRAGMA_BIT_RL))
+
+#define BCOM_PCI_PRAGMA		((0 << BCOM_PRAGMA_BIT_RSV)		| \
+				 (0 << BCOM_PRAGMA_BIT_PRECISE_INC)	| \
+				 (0 << BCOM_PRAGMA_BIT_RST_ERROR_NO)	| \
+				 (0 << BCOM_PRAGMA_BIT_PACK)		| \
+				 (1 << BCOM_PRAGMA_BIT_INTEGER)		| \
+				 (0 << BCOM_PRAGMA_BIT_SPECREAD)	| \
+				 (1 << BCOM_PRAGMA_BIT_CW)		| \
+				 (1 << BCOM_PRAGMA_BIT_RL))
+
+#define BCOM_ATA_PRAGMA		BCOM_STD_PRAGMA
+#define BCOM_CRC16_DP_0_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_CRC16_DP_1_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_FEC_RX_BD_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_FEC_TX_BD_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_GEN_DP_0_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_GEN_DP_1_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_GEN_DP_2_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_GEN_DP_3_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_GEN_DP_BD_0_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_GEN_DP_BD_1_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_GEN_RX_BD_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_GEN_TX_BD_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_GEN_LPC_PRAGMA	BCOM_STD_PRAGMA
+#define BCOM_PCI_RX_PRAGMA	BCOM_PCI_PRAGMA
+#define BCOM_PCI_TX_PRAGMA	BCOM_PCI_PRAGMA
+
+/* Initiators number */
+#define BCOM_INITIATOR_ALWAYS	 0
+#define BCOM_INITIATOR_SCTMR_0	 1
+#define BCOM_INITIATOR_SCTMR_1	 2
+#define BCOM_INITIATOR_FEC_RX	 3
+#define BCOM_INITIATOR_FEC_TX	 4
+#define BCOM_INITIATOR_ATA_RX	 5
+#define BCOM_INITIATOR_ATA_TX	 6
+#define BCOM_INITIATOR_SCPCI_RX	 7
+#define BCOM_INITIATOR_SCPCI_TX	 8
+#define BCOM_INITIATOR_PSC3_RX	 9
+#define BCOM_INITIATOR_PSC3_TX	10
+#define BCOM_INITIATOR_PSC2_RX	11
+#define BCOM_INITIATOR_PSC2_TX	12
+#define BCOM_INITIATOR_PSC1_RX	13
+#define BCOM_INITIATOR_PSC1_TX	14
+#define BCOM_INITIATOR_SCTMR_2	15
+#define BCOM_INITIATOR_SCLPC	16
+#define BCOM_INITIATOR_PSC5_RX	17
+#define BCOM_INITIATOR_PSC5_TX	18
+#define BCOM_INITIATOR_PSC4_RX	19
+#define BCOM_INITIATOR_PSC4_TX	20
+#define BCOM_INITIATOR_I2C2_RX	21
+#define BCOM_INITIATOR_I2C2_TX	22
+#define BCOM_INITIATOR_I2C1_RX	23
+#define BCOM_INITIATOR_I2C1_TX	24
+#define BCOM_INITIATOR_PSC6_RX	25
+#define BCOM_INITIATOR_PSC6_TX	26
+#define BCOM_INITIATOR_IRDA_RX	25
+#define BCOM_INITIATOR_IRDA_TX	26
+#define BCOM_INITIATOR_SCTMR_3	27
+#define BCOM_INITIATOR_SCTMR_4	28
+#define BCOM_INITIATOR_SCTMR_5	29
+#define BCOM_INITIATOR_SCTMR_6	30
+#define BCOM_INITIATOR_SCTMR_7	31
+
+/* Initiators priorities */
+#define BCOM_IPR_ALWAYS		7
+#define BCOM_IPR_SCTMR_0	2
+#define BCOM_IPR_SCTMR_1	2
+#define BCOM_IPR_FEC_RX		6
+#define BCOM_IPR_FEC_TX		5
+#define BCOM_IPR_ATA_RX		7
+#define BCOM_IPR_ATA_TX		7
+#define BCOM_IPR_SCPCI_RX	2
+#define BCOM_IPR_SCPCI_TX	2
+#define BCOM_IPR_PSC3_RX	2
+#define BCOM_IPR_PSC3_TX	2
+#define BCOM_IPR_PSC2_RX	2
+#define BCOM_IPR_PSC2_TX	2
+#define BCOM_IPR_PSC1_RX	2
+#define BCOM_IPR_PSC1_TX	2
+#define BCOM_IPR_SCTMR_2	2
+#define BCOM_IPR_SCLPC		2
+#define BCOM_IPR_PSC5_RX	2
+#define BCOM_IPR_PSC5_TX	2
+#define BCOM_IPR_PSC4_RX	2
+#define BCOM_IPR_PSC4_TX	2
+#define BCOM_IPR_I2C2_RX	2
+#define BCOM_IPR_I2C2_TX	2
+#define BCOM_IPR_I2C1_RX	2
+#define BCOM_IPR_I2C1_TX	2
+#define BCOM_IPR_PSC6_RX	2
+#define BCOM_IPR_PSC6_TX	2
+#define BCOM_IPR_IRDA_RX	2
+#define BCOM_IPR_IRDA_TX	2
+#define BCOM_IPR_SCTMR_3	2
+#define BCOM_IPR_SCTMR_4	2
+#define BCOM_IPR_SCTMR_5	2
+#define BCOM_IPR_SCTMR_6	2
+#define BCOM_IPR_SCTMR_7	2
+
+
+/* ======================================================================== */
+/* API                                                                      */
+/* ======================================================================== */
+
+extern struct bcom_task *bcom_task_alloc(int bd_count, int bd_size, int priv_size);
+extern void bcom_task_free(struct bcom_task *tsk);
+extern int bcom_load_image(int task, u32 *task_image);
+extern void bcom_set_initiator(int task, int initiator);
+
+
+#define TASK_ENABLE             0x8000
+
+/**
+ * bcom_disable_prefetch - Hook to disable bus prefetching
+ *
+ * ATA DMA and the original MPC5200 need this due to silicon bugs.  At the
+ * moment disabling prefetch is a one-way street.  There is no mechanism
+ * in place to turn prefetch back on after it has been disabled.  There is
+ * no reason it couldn't be done, it would just be more complex to implement.
+ */
+static inline void bcom_disable_prefetch(void)
+{
+	u16 regval;
+
+	regval = in_be16(&bcom_eng->regs->PtdCntrl);
+	out_be16(&bcom_eng->regs->PtdCntrl, regval | 1);
+};
+
+static inline void
+bcom_enable_task(int task)
+{
+        u16 reg;
+        reg = in_be16(&bcom_eng->regs->tcr[task]);
+        out_be16(&bcom_eng->regs->tcr[task],  reg | TASK_ENABLE);
+}
+
+static inline void
+bcom_disable_task(int task)
+{
+        u16 reg = in_be16(&bcom_eng->regs->tcr[task]);
+        out_be16(&bcom_eng->regs->tcr[task], reg & ~TASK_ENABLE);
+}
+
+
+static inline u32 *
+bcom_task_desc(int task)
+{
+	return bcom_sram_pa2va(bcom_eng->tdt[task].start);
+}
+
+static inline int
+bcom_task_num_descs(int task)
+{
+	return (bcom_eng->tdt[task].stop - bcom_eng->tdt[task].start)/sizeof(u32) + 1;
+}
+
+static inline u32 *
+bcom_task_var(int task)
+{
+	return bcom_sram_pa2va(bcom_eng->tdt[task].var);
+}
+
+static inline u32 *
+bcom_task_inc(int task)
+{
+	return &bcom_task_var(task)[BCOM_MAX_VAR];
+}
+
+
+static inline int
+bcom_drd_is_extended(u32 desc)
+{
+	return (desc) & BCOM_DRD_EXTENDED;
+}
+
+static inline int
+bcom_desc_is_drd(u32 desc)
+{
+	return !(desc & BCOM_LCD_MASK) && desc != BCOM_DESC_NOP;
+}
+
+static inline int
+bcom_desc_initiator(u32 desc)
+{
+	return (desc >> BCOM_DRD_INITIATOR_SHIFT) & 0x1f;
+}
+
+static inline void
+bcom_set_desc_initiator(u32 *desc, int initiator)
+{
+	*desc = (*desc & ~(0x1f << BCOM_DRD_INITIATOR_SHIFT)) |
+			((initiator & 0x1f) << BCOM_DRD_INITIATOR_SHIFT);
+}
+
+
+static inline void
+bcom_set_task_pragma(int task, int pragma)
+{
+	u32 *fdt = &bcom_eng->tdt[task].fdt;
+	*fdt = (*fdt & ~0xff) | pragma;
+}
+
+static inline void
+bcom_set_task_auto_start(int task, int next_task)
+{
+	u16 __iomem *tcr = &bcom_eng->regs->tcr[task];
+	out_be16(tcr, (in_be16(tcr) & ~0xff) | 0x00c0 | next_task);
+}
+
+static inline void
+bcom_set_tcr_initiator(int task, int initiator)
+{
+	u16 __iomem *tcr = &bcom_eng->regs->tcr[task];
+	out_be16(tcr, (in_be16(tcr) & ~0x1f00) | ((initiator & 0x1f) << 8));
+}
+
+
+#endif /* __BESTCOMM_PRIV_H__ */
+
diff --git a/include/linux/fsl/bestcomm/fec.h b/include/linux/fsl/bestcomm/fec.h
new file mode 100644
index 0000000..ee565d9
--- /dev/null
+++ b/include/linux/fsl/bestcomm/fec.h
@@ -0,0 +1,61 @@
+/*
+ * Header for Bestcomm FEC tasks driver
+ *
+ *
+ * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003-2004 MontaVista, Software, Inc.
+ *                         ( by Dale Farnsworth <dfarnsworth@mvista.com> )
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __BESTCOMM_FEC_H__
+#define __BESTCOMM_FEC_H__
+
+
+struct bcom_fec_bd {
+	u32	status;
+	u32	skb_pa;
+};
+
+#define BCOM_FEC_TX_BD_TFD	0x08000000ul	/* transmit frame done */
+#define BCOM_FEC_TX_BD_TC	0x04000000ul	/* transmit CRC */
+#define BCOM_FEC_TX_BD_ABC	0x02000000ul	/* append bad CRC */
+
+#define BCOM_FEC_RX_BD_L	0x08000000ul	/* buffer is last in frame */
+#define BCOM_FEC_RX_BD_BC	0x00800000ul	/* DA is broadcast */
+#define BCOM_FEC_RX_BD_MC	0x00400000ul	/* DA is multicast and not broadcast */
+#define BCOM_FEC_RX_BD_LG	0x00200000ul	/* Rx frame length violation */
+#define BCOM_FEC_RX_BD_NO	0x00100000ul	/* Rx non-octet aligned frame */
+#define BCOM_FEC_RX_BD_CR	0x00040000ul	/* Rx CRC error */
+#define BCOM_FEC_RX_BD_OV	0x00020000ul	/* overrun */
+#define BCOM_FEC_RX_BD_TR	0x00010000ul	/* Rx frame truncated */
+#define BCOM_FEC_RX_BD_LEN_MASK	0x000007fful	/* mask for length of received frame */
+#define BCOM_FEC_RX_BD_ERRORS	(BCOM_FEC_RX_BD_LG | BCOM_FEC_RX_BD_NO | \
+		BCOM_FEC_RX_BD_CR | BCOM_FEC_RX_BD_OV | BCOM_FEC_RX_BD_TR)
+
+
+extern struct bcom_task *
+bcom_fec_rx_init(int queue_len, phys_addr_t fifo, int maxbufsize);
+
+extern int
+bcom_fec_rx_reset(struct bcom_task *tsk);
+
+extern void
+bcom_fec_rx_release(struct bcom_task *tsk);
+
+
+extern struct bcom_task *
+bcom_fec_tx_init(int queue_len, phys_addr_t fifo);
+
+extern int
+bcom_fec_tx_reset(struct bcom_task *tsk);
+
+extern void
+bcom_fec_tx_release(struct bcom_task *tsk);
+
+
+#endif /* __BESTCOMM_FEC_H__ */
+
diff --git a/include/linux/fsl/bestcomm/gen_bd.h b/include/linux/fsl/bestcomm/gen_bd.h
new file mode 100644
index 0000000..de47260
--- /dev/null
+++ b/include/linux/fsl/bestcomm/gen_bd.h
@@ -0,0 +1,53 @@
+/*
+ * Header for Bestcomm General Buffer Descriptor tasks driver
+ *
+ *
+ * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2006 AppSpec Computer Technologies Corp.
+ *                    Jeff Gibbons <jeff.gibbons@appspec.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ *
+ */
+
+#ifndef __BESTCOMM_GEN_BD_H__
+#define __BESTCOMM_GEN_BD_H__
+
+struct bcom_gen_bd {
+	u32	status;
+	u32	buf_pa;
+};
+
+
+extern struct bcom_task *
+bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
+			int initiator, int ipr, int maxbufsize);
+
+extern int
+bcom_gen_bd_rx_reset(struct bcom_task *tsk);
+
+extern void
+bcom_gen_bd_rx_release(struct bcom_task *tsk);
+
+
+extern struct bcom_task *
+bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
+			int initiator, int ipr);
+
+extern int
+bcom_gen_bd_tx_reset(struct bcom_task *tsk);
+
+extern void
+bcom_gen_bd_tx_release(struct bcom_task *tsk);
+
+
+/* PSC support utility wrappers */
+struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
+					   phys_addr_t fifo, int maxbufsize);
+struct bcom_task * bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len,
+					   phys_addr_t fifo);
+#endif  /* __BESTCOMM_GEN_BD_H__ */
+
diff --git a/include/linux/fsl/bestcomm/sram.h b/include/linux/fsl/bestcomm/sram.h
new file mode 100644
index 0000000..b6d6689
--- /dev/null
+++ b/include/linux/fsl/bestcomm/sram.h
@@ -0,0 +1,54 @@
+/*
+ * Handling of a sram zone for bestcomm
+ *
+ *
+ * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __BESTCOMM_SRAM_H__
+#define __BESTCOMM_SRAM_H__
+
+#include <asm/rheap.h>
+#include <asm/mmu.h>
+#include <linux/spinlock.h>
+
+
+/* Structure used internally */
+	/* The internals are here for the inline functions
+	 * sake, certainly not for the user to mess with !
+	 */
+struct bcom_sram {
+	phys_addr_t		 base_phys;
+	void 			*base_virt;
+	unsigned int		 size;
+	rh_info_t		*rh;
+	spinlock_t		 lock;
+};
+
+extern struct bcom_sram *bcom_sram;
+
+
+/* Public API */
+extern int  bcom_sram_init(struct device_node *sram_node, char *owner);
+extern void bcom_sram_cleanup(void);
+
+extern void* bcom_sram_alloc(int size, int align, phys_addr_t *phys);
+extern void  bcom_sram_free(void *ptr);
+
+static inline phys_addr_t bcom_sram_va2pa(void *va) {
+	return bcom_sram->base_phys +
+		(unsigned long)(va - bcom_sram->base_virt);
+}
+
+static inline void *bcom_sram_pa2va(phys_addr_t pa) {
+	return bcom_sram->base_virt +
+		(unsigned long)(pa - bcom_sram->base_phys);
+}
+
+
+#endif  /* __BESTCOMM_SRAM_H__ */
+
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 9997c03..2a847ca 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -14,8 +14,8 @@
 
 #include <sound/soc.h>
 
-#include <sysdev/bestcomm/bestcomm.h>
-#include <sysdev/bestcomm/gen_bd.h>
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/gen_bd.h>
 #include <asm/mpc52xx_psc.h>
 
 #include "mpc5200_dma.h"
-- 
1.7.1

^ permalink raw reply related

* [PATCH v2] powerpc, dma: move bestcomm driver from arch/powerpc/sysdev to drivers/dma
From: Philippe De Muyter @ 2012-10-12 15:52 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: Philippe De Muyter

The bestcomm dma hardware, and some of its users like the FEC ethernet
component, is used in different FreeScale parts, including non-powerpc
parts like the ColdFire MCF547x & MCF548x families.  Don't keep the
driver hidden in arch/powerpc where it is inaccessible for other arches.
.c files are moved to arch/drivers/dma/bestcomm, while
.h files are moved to include/linux/fsl/bestcomm.  Makefiles, Kconfigs
and #include directives are updated for the new file locations.

Tested by recompiling for MPC5200 with all bestcomm users enabled.

Signed-off-by: Philippe De Muyter <phdm@macqel.be>
---
 arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c      |    6 +++---
 arch/powerpc/platforms/Kconfig                     |    2 --
 arch/powerpc/sysdev/Makefile                       |    1 -
 drivers/Makefile                                   |    2 +-
 drivers/ata/pata_mpc52xx.c                         |    6 +++---
 drivers/dma/Kconfig                                |    2 ++
 drivers/dma/Makefile                               |    1 +
 .../sysdev => drivers/dma}/bestcomm/Kconfig        |    0
 .../sysdev => drivers/dma}/bestcomm/Makefile       |    0
 .../powerpc/sysdev => drivers/dma}/bestcomm/ata.c  |    6 +++---
 .../dma}/bestcomm/bcom_ata_task.c                  |    0
 .../dma}/bestcomm/bcom_fec_rx_task.c               |    0
 .../dma}/bestcomm/bcom_fec_tx_task.c               |    0
 .../dma}/bestcomm/bcom_gen_bd_rx_task.c            |    0
 .../dma}/bestcomm/bcom_gen_bd_tx_task.c            |    0
 .../sysdev => drivers/dma}/bestcomm/bestcomm.c     |    6 +++---
 .../powerpc/sysdev => drivers/dma}/bestcomm/fec.c  |    6 +++---
 .../sysdev => drivers/dma}/bestcomm/gen_bd.c       |    6 +++---
 .../powerpc/sysdev => drivers/dma}/bestcomm/sram.c |    2 +-
 drivers/net/ethernet/freescale/fec_mpc52xx.c       |    4 ++--
 .../sysdev => include/linux/fsl}/bestcomm/ata.h    |    0
 .../linux/fsl}/bestcomm/bestcomm.h                 |    0
 .../linux/fsl}/bestcomm/bestcomm_priv.h            |    0
 .../sysdev => include/linux/fsl}/bestcomm/fec.h    |    0
 .../sysdev => include/linux/fsl}/bestcomm/gen_bd.h |    0
 .../sysdev => include/linux/fsl}/bestcomm/sram.h   |    0
 sound/soc/fsl/mpc5200_dma.c                        |    4 ++--
 27 files changed, 27 insertions(+), 27 deletions(-)
 rename {arch/powerpc/sysdev => drivers/dma}/bestcomm/Kconfig (100%)
 rename {arch/powerpc/sysdev => drivers/dma}/bestcomm/Makefile (100%)
 rename {arch/powerpc/sysdev => drivers/dma}/bestcomm/ata.c (97%)
 rename {arch/powerpc/sysdev => drivers/dma}/bestcomm/bcom_ata_task.c (100%)
 rename {arch/powerpc/sysdev => drivers/dma}/bestcomm/bcom_fec_rx_task.c (100%)
 rename {arch/powerpc/sysdev => drivers/dma}/bestcomm/bcom_fec_tx_task.c (100%)
 rename {arch/powerpc/sysdev => drivers/dma}/bestcomm/bcom_gen_bd_rx_task.c (100%)
 rename {arch/powerpc/sysdev => drivers/dma}/bestcomm/bcom_gen_bd_tx_task.c (100%)
 rename {arch/powerpc/sysdev => drivers/dma}/bestcomm/bestcomm.c (99%)
 rename {arch/powerpc/sysdev => drivers/dma}/bestcomm/fec.c (98%)
 rename {arch/powerpc/sysdev => drivers/dma}/bestcomm/gen_bd.c (98%)
 rename {arch/powerpc/sysdev => drivers/dma}/bestcomm/sram.c (99%)
 rename {arch/powerpc/sysdev => include/linux/fsl}/bestcomm/ata.h (100%)
 rename {arch/powerpc/sysdev => include/linux/fsl}/bestcomm/bestcomm.h (100%)
 rename {arch/powerpc/sysdev => include/linux/fsl}/bestcomm/bestcomm_priv.h (100%)
 rename {arch/powerpc/sysdev => include/linux/fsl}/bestcomm/fec.h (100%)
 rename {arch/powerpc/sysdev => include/linux/fsl}/bestcomm/gen_bd.h (100%)
 rename {arch/powerpc/sysdev => include/linux/fsl}/bestcomm/sram.h (100%)

diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
index 2351f9e..089e665 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
@@ -20,9 +20,9 @@
 #include <asm/mpc52xx.h>
 #include <asm/time.h>
 
-#include <sysdev/bestcomm/bestcomm.h>
-#include <sysdev/bestcomm/bestcomm_priv.h>
-#include <sysdev/bestcomm/gen_bd.h>
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/bestcomm_priv.h>
+#include <linux/fsl/bestcomm/gen_bd.h>
 
 MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
 MODULE_DESCRIPTION("MPC5200 LocalPlus FIFO device driver");
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index e7a896a..405f763 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -351,8 +351,6 @@ config OF_RTC
 	  Uses information from the OF or flattened device tree to instantiate
 	  platform devices for direct mapped RTC chips like the DS1742 or DS1743.
 
-source "arch/powerpc/sysdev/bestcomm/Kconfig"
-
 config SIMPLE_GPIO
 	bool "Support for simple, memory-mapped GPIO controllers"
 	depends on PPC
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index a57600b..3884776 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -26,7 +26,6 @@ obj-$(CONFIG_SIMPLE_GPIO)	+= simple_gpio.o
 obj-$(CONFIG_FSL_RIO)		+= fsl_rio.o fsl_rmu.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
-obj-$(CONFIG_PPC_BESTCOMM)	+= bestcomm/
 mv64x60-$(CONFIG_PCI)		+= mv64x60_pci.o
 obj-$(CONFIG_MV64X60)		+= $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o \
 				   mv64x60_udbg.o
diff --git a/drivers/Makefile b/drivers/Makefile
index 03da5b6..b69189e 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -25,7 +25,7 @@ obj-$(CONFIG_PNP)		+= pnp/
 obj-y				+= amba/
 # Many drivers will want to use DMA so this has to be made available
 # really early.
-obj-$(CONFIG_DMA_ENGINE)	+= dma/
+obj-$(CONFIG_DMADEVICES)	+= dma/
 
 obj-$(CONFIG_VIRTIO)		+= virtio/
 obj-$(CONFIG_XEN)		+= xen/
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index d2c102f..3d0d4d2 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -26,9 +26,9 @@
 #include <asm/prom.h>
 #include <asm/mpc52xx.h>
 
-#include <sysdev/bestcomm/bestcomm.h>
-#include <sysdev/bestcomm/bestcomm_priv.h>
-#include <sysdev/bestcomm/ata.h>
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/bestcomm_priv.h>
+#include <linux/fsl/bestcomm/ata.h>
 
 #define DRV_NAME	"mpc52xx_ata"
 
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 677cd6e..464050b 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -114,6 +114,8 @@ config MPC512X_DMA
 	---help---
 	  Enable support for the Freescale MPC512x built-in DMA engine.
 
+source "drivers/dma/bestcomm/Kconfig"
+
 config MV_XOR
 	bool "Marvell XOR engine support"
 	depends on PLAT_ORION
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 7428fea..642d967 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
 obj-$(CONFIG_FSL_DMA) += fsldma.o
 obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
+obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
 obj-$(CONFIG_MV_XOR) += mv_xor.o
 obj-$(CONFIG_DW_DMAC) += dw_dmac.o
 obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/drivers/dma/bestcomm/Kconfig
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/Kconfig
rename to drivers/dma/bestcomm/Kconfig
diff --git a/arch/powerpc/sysdev/bestcomm/Makefile b/drivers/dma/bestcomm/Makefile
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/Makefile
rename to drivers/dma/bestcomm/Makefile
diff --git a/arch/powerpc/sysdev/bestcomm/ata.c b/drivers/dma/bestcomm/ata.c
similarity index 97%
rename from arch/powerpc/sysdev/bestcomm/ata.c
rename to drivers/dma/bestcomm/ata.c
index 901c9f9..2fd87f8 100644
--- a/arch/powerpc/sysdev/bestcomm/ata.c
+++ b/drivers/dma/bestcomm/ata.c
@@ -18,9 +18,9 @@
 #include <linux/types.h>
 #include <asm/io.h>
 
-#include "bestcomm.h"
-#include "bestcomm_priv.h"
-#include "ata.h"
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/bestcomm_priv.h>
+#include <linux/fsl/bestcomm/ata.h>
 
 
 /* ======================================================================== */
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_ata_task.c b/drivers/dma/bestcomm/bcom_ata_task.c
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/bcom_ata_task.c
rename to drivers/dma/bestcomm/bcom_ata_task.c
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c b/drivers/dma/bestcomm/bcom_fec_rx_task.c
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c
rename to drivers/dma/bestcomm/bcom_fec_rx_task.c
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c b/drivers/dma/bestcomm/bcom_fec_tx_task.c
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c
rename to drivers/dma/bestcomm/bcom_fec_tx_task.c
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c b/drivers/dma/bestcomm/bcom_gen_bd_rx_task.c
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c
rename to drivers/dma/bestcomm/bcom_gen_bd_rx_task.c
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c b/drivers/dma/bestcomm/bcom_gen_bd_tx_task.c
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c
rename to drivers/dma/bestcomm/bcom_gen_bd_tx_task.c
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c
similarity index 99%
rename from arch/powerpc/sysdev/bestcomm/bestcomm.c
rename to drivers/dma/bestcomm/bestcomm.c
index b3fbb27..67371fb 100644
--- a/arch/powerpc/sysdev/bestcomm/bestcomm.c
+++ b/drivers/dma/bestcomm/bestcomm.c
@@ -23,9 +23,9 @@
 #include <asm/irq.h>
 #include <asm/mpc52xx.h>
 
-#include "sram.h"
-#include "bestcomm_priv.h"
-#include "bestcomm.h"
+#include <linux/fsl/bestcomm/sram.h>
+#include <linux/fsl/bestcomm/bestcomm_priv.h>
+#include "linux/fsl/bestcomm/bestcomm.h"
 
 #define DRIVER_NAME "bestcomm-core"
 
diff --git a/arch/powerpc/sysdev/bestcomm/fec.c b/drivers/dma/bestcomm/fec.c
similarity index 98%
rename from arch/powerpc/sysdev/bestcomm/fec.c
rename to drivers/dma/bestcomm/fec.c
index 957a988..7f1fb1c 100644
--- a/arch/powerpc/sysdev/bestcomm/fec.c
+++ b/drivers/dma/bestcomm/fec.c
@@ -16,9 +16,9 @@
 #include <linux/types.h>
 #include <asm/io.h>
 
-#include "bestcomm.h"
-#include "bestcomm_priv.h"
-#include "fec.h"
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/bestcomm_priv.h>
+#include <linux/fsl/bestcomm/fec.h>
 
 
 /* ======================================================================== */
diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.c b/drivers/dma/bestcomm/gen_bd.c
similarity index 98%
rename from arch/powerpc/sysdev/bestcomm/gen_bd.c
rename to drivers/dma/bestcomm/gen_bd.c
index e0a53e3..1a5b22d 100644
--- a/arch/powerpc/sysdev/bestcomm/gen_bd.c
+++ b/drivers/dma/bestcomm/gen_bd.c
@@ -21,9 +21,9 @@
 #include <asm/mpc52xx.h>
 #include <asm/mpc52xx_psc.h>
 
-#include "bestcomm.h"
-#include "bestcomm_priv.h"
-#include "gen_bd.h"
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/bestcomm_priv.h>
+#include <linux/fsl/bestcomm/gen_bd.h>
 
 
 /* ======================================================================== */
diff --git a/arch/powerpc/sysdev/bestcomm/sram.c b/drivers/dma/bestcomm/sram.c
similarity index 99%
rename from arch/powerpc/sysdev/bestcomm/sram.c
rename to drivers/dma/bestcomm/sram.c
index b6db23e..5e2ed30 100644
--- a/arch/powerpc/sysdev/bestcomm/sram.c
+++ b/drivers/dma/bestcomm/sram.c
@@ -23,7 +23,7 @@
 #include <asm/io.h>
 #include <asm/mmu.h>
 
-#include "sram.h"
+#include <linux/fsl/bestcomm/sram.h>
 
 
 /* Struct keeping our 'state' */
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index 2933d08..c077be0 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -40,8 +40,8 @@
 #include <asm/delay.h>
 #include <asm/mpc52xx.h>
 
-#include <sysdev/bestcomm/bestcomm.h>
-#include <sysdev/bestcomm/fec.h>
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/fec.h>
 
 #include "fec_mpc52xx.h"
 
diff --git a/arch/powerpc/sysdev/bestcomm/ata.h b/include/linux/fsl/bestcomm/ata.h
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/ata.h
rename to include/linux/fsl/bestcomm/ata.h
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.h b/include/linux/fsl/bestcomm/bestcomm.h
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/bestcomm.h
rename to include/linux/fsl/bestcomm/bestcomm.h
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h b/include/linux/fsl/bestcomm/bestcomm_priv.h
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
rename to include/linux/fsl/bestcomm/bestcomm_priv.h
diff --git a/arch/powerpc/sysdev/bestcomm/fec.h b/include/linux/fsl/bestcomm/fec.h
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/fec.h
rename to include/linux/fsl/bestcomm/fec.h
diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.h b/include/linux/fsl/bestcomm/gen_bd.h
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/gen_bd.h
rename to include/linux/fsl/bestcomm/gen_bd.h
diff --git a/arch/powerpc/sysdev/bestcomm/sram.h b/include/linux/fsl/bestcomm/sram.h
similarity index 100%
rename from arch/powerpc/sysdev/bestcomm/sram.h
rename to include/linux/fsl/bestcomm/sram.h
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 9997c03..2a847ca 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -14,8 +14,8 @@
 
 #include <sound/soc.h>
 
-#include <sysdev/bestcomm/bestcomm.h>
-#include <sysdev/bestcomm/gen_bd.h>
+#include <linux/fsl/bestcomm/bestcomm.h>
+#include <linux/fsl/bestcomm/gen_bd.h>
 #include <asm/mpc52xx_psc.h>
 
 #include "mpc5200_dma.h"
-- 
1.7.1

^ permalink raw reply related

* Re: [PATCH v3 1/2] powerpc/PCI: move DMA & IRQ init to device_add() notification path
From: Bjorn Helgaas @ 2012-10-12 18:03 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Michal Simek, Hiroo Matsumoto, microblaze-uclinux,
	Kenji Kaneshige, Jesse Larrew, jbarnes, Dominik Brodowski,
	linux-pci, linuxppc-dev
In-Reply-To: <1340060143.2372.50.camel@pasglop>

On Mon, Jun 18, 2012 at 4:55 PM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> On Mon, 2012-06-18 at 15:06 -0600, Bjorn Helgaas wrote:
>> We're moving the CardBus IRQ config from before pci_bus_add_devices()
>> to after.  I see why you did that: we're proposing to do the powerpc
>> DMA & IRQ setup in pci_bus_add_devices(), so we don't want to have the
>> powerpc IRQ init clobber the CardBus IRQ config.
>>
>> But a driver can claim the device as soon as we call
>> pci_bus_add_devices(), so we're potentially changing dev->irq after a
>> driver has already looked at it, which sounds like a bug.
>>
>> There are only five possibilities for powerpc pci_irq_fixup:
>>
>>       ppc47x_pci_irq_fixup
>>       mpc85xx_cds_pci_irq_fixup
>>       maple_pci_irq_fixup
>>       pmac_pci_irq_fixup
>>       rtas_msi_pci_irq_fixup
>>
>> If these were normal PCI header quirks instead, they could run
>> earlier, and we wouldn't need to move this
>> cardbus_config_irq_and_cls() call.  Is it possible to make these
>> quirks, Ben?
>
> Wait ... why are those fixups relevant ? They have to run after
> pci_read_irq_line() (which should have been called pcibios_read_irq_line
> really) but that's fine, we call both back to back....
>
> The problem has to do with the fact that we setup pdev->irq inside
> pci_bus_add_devices() with the new proposed code (the fixup itself is
> just a detail).
>
> You want cardbus to "quirk" the irq after that's been fixed up... maybe
> that's a case for moving cardbus_config_irq_and_cls() to
> pci_enable_device() ? Or add another hook inside
> pci_bus_add_devices()...

This thread has languished a long time, and I think the original
problem (hot-added e1000e devices on powerpc don't work) still exists,
doesn't it?

I'd like to get a kernel bugzilla opened so (a) this doesn't get
forgotten and (b) we can attach things like dmesg logs showing the
issue.

The current patch does this:

>        pci_bus_add_devices(bus);
> +       cardbus_config_irq_and_cls(bus, s->pci_irq);

I don't think we can do this, because pci_bus_add_devices() can bind a
driver to the device, and we can't change dev->irq after that point.

cardbus_config_irq_and_cls() has to do with the way CardBus interrupts
work, so it seems like it should be better integrated into the PCI
core.  For example, maybe it could be integrated into the
PCI_HEADER_TYPE_CARDBUS case in pci_setup_device().

I think that would still require the powerpc IRQ fixups to be done
earlier, e.g., as a header quirk or a pcibios hook.

Bjorn

^ permalink raw reply

* Re: [PATCH 5/10] memory-hotplug : memory-hotplug: check page type in get_page_bootmem
From: KOSAKI Motohiro @ 2012-10-12 19:28 UTC (permalink / raw)
  To: Yasuaki Ishimatsu
  Cc: linux-s390, linux-ia64, wency, len.brown, linux-acpi, linux-sh,
	x86, linux-kernel, cmetcalf, linux-mm, minchan.kim, rientjes,
	sparclinux, cl, linuxppc-dev, akpm, liuj97
In-Reply-To: <506E46B6.3060502@jp.fujitsu.com>

On Thu, Oct 4, 2012 at 10:32 PM, Yasuaki Ishimatsu
<isimatu.yasuaki@jp.fujitsu.com> wrote:
> The function get_page_bootmem() may be called more than one time to the same
> page. There is no need to set page's type, private if the function is not
> the first time called to the page.
>
> Note: the patch is just optimization and does not fix any problem.
>
> CC: David Rientjes <rientjes@google.com>
> CC: Jiang Liu <liuj97@gmail.com>
> CC: Len Brown <len.brown@intel.com>
> CC: Christoph Lameter <cl@linux.com>
> Cc: Minchan Kim <minchan.kim@gmail.com>
> CC: Andrew Morton <akpm@linux-foundation.org>
> CC: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
> CC: Wen Congyang <wency@cn.fujitsu.com>
> Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
> ---
>  mm/memory_hotplug.c |   15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
>
> Index: linux-3.6/mm/memory_hotplug.c
> ===================================================================
> --- linux-3.6.orig/mm/memory_hotplug.c  2012-10-04 18:29:58.284676075 +0900
> +++ linux-3.6/mm/memory_hotplug.c       2012-10-04 18:30:03.454680542 +0900
> @@ -95,10 +95,17 @@ static void release_memory_resource(stru
>  static void get_page_bootmem(unsigned long info,  struct page *page,
>                              unsigned long type)
>  {
> -       page->lru.next = (struct list_head *) type;
> -       SetPagePrivate(page);
> -       set_page_private(page, info);
> -       atomic_inc(&page->_count);
> +       unsigned long page_type;
> +
> +       page_type = (unsigned long)page->lru.next;

If I understand correctly, page->lru.next might be uninitialized yet.

Moreover, I have no seen any good effect in this patch. I don't understand
why we need to increase code complexity.



> +       if (page_type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
> +           page_type > MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE){
> +               page->lru.next = (struct list_head *)type;
> +               SetPagePrivate(page);
> +               set_page_private(page, info);
> +               atomic_inc(&page->_count);
> +       } else
> +               atomic_inc(&page->_count);
>  }
>
>  /* reference to __meminit __free_pages_bootmem is valid
>
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply


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