linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24
@ 2007-09-16 10:53 Sylvain Munaut
  2007-09-16 10:53 ` [PATCH 1/7] powerpc: exports rheap symbol to modules Sylvain Munaut
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Sylvain Munaut @ 2007-09-16 10:53 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Grant Likely, PowerPC dev list

Hello Paul, Hi everyone,

This series of patch is mainly the bestcomm support for
the mpc5200. It was posted a while ago and received some
comments. Theses are all addressed here (afaik).

The first few patch are more a preparation for what
follows. (rheap module support & extended fields in psc
structure).

The rest is the core support followed by each specific
microcode support. (Previous emails explained the stucture
better, I'm not gonna repeat it here)

This particular version has been tested on the EFIKA and
works fine. Previous versions have been tested on a lot
of different platforms by numerous people. (and since the
changes since last version are cosmetic ...).

This series _doesn_t_ include any driver that actually make
use of bestcomm support. Hopefully theses will come. I
think Domen Puncer sent a cleaned up driver for ethernet.


        Sylvain

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/7] powerpc: exports rheap symbol to modules
  2007-09-16 10:53 [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Sylvain Munaut
@ 2007-09-16 10:53 ` Sylvain Munaut
  2007-09-16 10:53 ` [PATCH 2/7] powerpc: Changes the config mechanism for rheap Sylvain Munaut
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Sylvain Munaut @ 2007-09-16 10:53 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Grant Likely, Sylvain Munaut, PowerPC dev list

Theses can be useful in modules too. So we export them.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
 arch/powerpc/lib/rheap.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
index ada5b42..22c3b4f 100644
--- a/arch/powerpc/lib/rheap.c
+++ b/arch/powerpc/lib/rheap.c
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/err.h>
 #include <linux/slab.h>
@@ -275,6 +276,7 @@ rh_info_t *rh_create(unsigned int alignment)
 
 	return info;
 }
+EXPORT_SYMBOL_GPL(rh_create);
 
 /*
  * Destroy a dynamically created remote heap.  Deallocate only if the areas
@@ -288,6 +290,7 @@ void rh_destroy(rh_info_t * info)
 	if ((info->flags & RHIF_STATIC_INFO) == 0)
 		kfree(info);
 }
+EXPORT_SYMBOL_GPL(rh_destroy);
 
 /*
  * Initialize in place a remote heap info block.  This is needed to support
@@ -320,6 +323,7 @@ void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks,
 	for (i = 0, blk = block; i < max_blocks; i++, blk++)
 		list_add(&blk->list, &info->empty_list);
 }
+EXPORT_SYMBOL_GPL(rh_init);
 
 /* Attach a free memory region, coalesces regions if adjuscent */
 int rh_attach_region(rh_info_t * info, unsigned long start, int size)
@@ -360,6 +364,7 @@ int rh_attach_region(rh_info_t * info, unsigned long start, int size)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(rh_attach_region);
 
 /* Detatch given address range, splits free block if needed. */
 unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size)
@@ -428,6 +433,7 @@ unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size)
 
 	return s;
 }
+EXPORT_SYMBOL_GPL(rh_detach_region);
 
 /* Allocate a block of memory at the specified alignment.  The value returned
  * is an offset into the buffer initialized by rh_init(), or a negative number
@@ -502,6 +508,7 @@ unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const ch
 
 	return start;
 }
+EXPORT_SYMBOL_GPL(rh_alloc_align);
 
 /* Allocate a block of memory at the default alignment.  The value returned is
  * an offset into the buffer initialized by rh_init(), or a negative number if
@@ -511,6 +518,7 @@ unsigned long rh_alloc(rh_info_t * info, int size, const char *owner)
 {
 	return rh_alloc_align(info, size, info->alignment, owner);
 }
+EXPORT_SYMBOL_GPL(rh_alloc);
 
 /* Allocate a block of memory at the given offset, rounded up to the default
  * alignment.  The value returned is an offset into the buffer initialized by
@@ -594,6 +602,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co
 
 	return start;
 }
+EXPORT_SYMBOL_GPL(rh_alloc_fixed);
 
 /* Deallocate the memory previously allocated by one of the rh_alloc functions.
  * The return value is the size of the deallocated block, or a negative number
@@ -626,6 +635,7 @@ int rh_free(rh_info_t * info, unsigned long start)
 
 	return size;
 }
+EXPORT_SYMBOL_GPL(rh_free);
 
 int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats)
 {
@@ -663,6 +673,7 @@ int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats)
 
 	return nr;
 }
+EXPORT_SYMBOL_GPL(rh_get_stats);
 
 int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner)
 {
@@ -687,6 +698,7 @@ int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner)
 
 	return size;
 }
+EXPORT_SYMBOL_GPL(rh_set_owner);
 
 void rh_dump(rh_info_t * info)
 {
@@ -722,6 +734,7 @@ void rh_dump(rh_info_t * info)
 		       st[i].size, st[i].owner != NULL ? st[i].owner : "");
 	printk(KERN_INFO "\n");
 }
+EXPORT_SYMBOL_GPL(rh_dump);
 
 void rh_dump_blk(rh_info_t * info, rh_block_t * blk)
 {
@@ -729,3 +742,5 @@ void rh_dump_blk(rh_info_t * info, rh_block_t * blk)
 	       "blk @0x%p: 0x%lx-0x%lx (%u)\n",
 	       blk, blk->start, blk->start + blk->size, blk->size);
 }
+EXPORT_SYMBOL_GPL(rh_dump_blk);
+
-- 
1.5.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/7] powerpc: Changes the config mechanism for rheap
  2007-09-16 10:53 [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Sylvain Munaut
  2007-09-16 10:53 ` [PATCH 1/7] powerpc: exports rheap symbol to modules Sylvain Munaut
@ 2007-09-16 10:53 ` Sylvain Munaut
  2007-09-16 15:59   ` Kumar Gala
  2007-09-16 10:53 ` [PATCH 3/7] powerpc/ppc32: Update mpc52xx_psc structure with B revision changes Sylvain Munaut
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Sylvain Munaut @ 2007-09-16 10:53 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Grant Likely, Sylvain Munaut, PowerPC dev list

Instead of having in the makefile all the option that
requires rheap, we define a configuration symbol
and when needed we make sure it's selected.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
 arch/powerpc/Kconfig                   |    2 ++
 arch/powerpc/lib/Kconfig               |    3 +++
 arch/powerpc/lib/Makefile              |    5 +----
 arch/powerpc/platforms/Kconfig         |    2 ++
 arch/powerpc/platforms/Kconfig.cputype |    1 +
 5 files changed, 9 insertions(+), 4 deletions(-)
 create mode 100644 arch/powerpc/lib/Kconfig

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 00099ef..76063b9 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -634,6 +634,8 @@ source "fs/Kconfig"
 
 source "arch/powerpc/sysdev/qe_lib/Kconfig"
 
+source "arch/powerpc/lib/Kconfig"
+
 source "lib/Kconfig"
 
 menu "Instrumentation Support"
diff --git a/arch/powerpc/lib/Kconfig b/arch/powerpc/lib/Kconfig
new file mode 100644
index 0000000..f383ad4
--- /dev/null
+++ b/arch/powerpc/lib/Kconfig
@@ -0,0 +1,3 @@
+config PPC_LIB_RHEAP
+	bool
+	default n
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 0a486d4..f75c2a1 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -13,7 +13,6 @@ endif
 
 obj-$(CONFIG_PPC64)	+= checksum_64.o copypage_64.o copyuser_64.o \
 			   memcpy_64.o usercopy_64.o mem_64.o string.o
-obj-$(CONFIG_QUICC_ENGINE) += rheap.o
 obj-$(CONFIG_XMON)	+= sstep.o
 obj-$(CONFIG_KPROBES)	+= sstep.o
 obj-$(CONFIG_NOT_COHERENT_CACHE)	+= dma-noncoherent.o
@@ -22,6 +21,4 @@ ifeq ($(CONFIG_PPC64),y)
 obj-$(CONFIG_SMP)	+= locks.o
 endif
 
-# Temporary hack until we have migrated to asm-powerpc
-obj-$(CONFIG_8xx)	+= rheap.o
-obj-$(CONFIG_CPM2)	+= rheap.o
+obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 19d4628..9189ba5 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -257,6 +257,7 @@ config TAU_AVERAGE
 
 config QUICC_ENGINE
 	bool
+	select PPC_LIB_RHEAP
 	help
 	  The QUICC Engine (QE) is a new generation of communications
 	  coprocessors on Freescale embedded CPUs (akin to CPM in older chips).
@@ -266,6 +267,7 @@ config QUICC_ENGINE
 config CPM2
 	bool
 	default n
+	select PPC_LIB_RHEAP
 	help
 	  The CPM2 (Communications Processor Module) is a coprocessor on
 	  embedded CPUs made by Freescale.  Selecting this option means that
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index e4b2aee..29d8eff 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -36,6 +36,7 @@ config PPC_8xx
 	bool "Freescale 8xx"
 	select FSL_SOC
 	select 8xx
+	select PPC_LIB_RHEAP
 
 config 40x
 	bool "AMCC 40x"
-- 
1.5.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/7] powerpc/ppc32: Update mpc52xx_psc structure with B revision changes
  2007-09-16 10:53 [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Sylvain Munaut
  2007-09-16 10:53 ` [PATCH 1/7] powerpc: exports rheap symbol to modules Sylvain Munaut
  2007-09-16 10:53 ` [PATCH 2/7] powerpc: Changes the config mechanism for rheap Sylvain Munaut
@ 2007-09-16 10:53 ` Sylvain Munaut
  2007-09-16 10:53 ` [PATCH 4/7] powerpc: BestComm core support for Freescale MPC5200 Sylvain Munaut
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Sylvain Munaut @ 2007-09-16 10:53 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Grant Likely, Sylvain Munaut, PowerPC dev list

On the mpc5200b the ccr register is 32 bits wide while on the
mpc5200 it's only 16 bits. It's up to the driver to use the
correct format depending on the chip it's running on.

The 5200b also offers some more registers & status in AC97
mode. Again, if not running on a 5200b the driver should not
use those.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
 include/asm-ppc/mpc52xx_psc.h |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/include/asm-ppc/mpc52xx_psc.h b/include/asm-ppc/mpc52xx_psc.h
index 9d850b2..c82b8d4 100644
--- a/include/asm-ppc/mpc52xx_psc.h
+++ b/include/asm-ppc/mpc52xx_psc.h
@@ -28,6 +28,10 @@
 #define MPC52xx_PSC_MAXNUM	6
 
 /* Programmable Serial Controller (PSC) status register bits */
+#define MPC52xx_PSC_SR_UNEX_RX	0x0001
+#define MPC52xx_PSC_SR_DATA_VAL	0x0002
+#define MPC52xx_PSC_SR_DATA_OVR	0x0004
+#define MPC52xx_PSC_SR_CMDSEND	0x0008
 #define MPC52xx_PSC_SR_CDE	0x0080
 #define MPC52xx_PSC_SR_RXRDY	0x0100
 #define MPC52xx_PSC_SR_RXFULL	0x0200
@@ -132,8 +136,10 @@ struct mpc52xx_psc {
 	u8		reserved5[3];
 	u8		ctlr;		/* PSC + 0x1c */
 	u8		reserved6[3];
-	u16		ccr;		/* PSC + 0x20 */
-	u8		reserved7[14];
+	u32		ccr;		/* PSC + 0x20 */
+	u32		ac97_slots;	/* PSC + 0x24 */
+	u32		ac97_cmd;	/* PSC + 0x28 */
+	u32		ac97_data;	/* PSC + 0x2c */
 	u8		ivr;		/* PSC + 0x30 */
 	u8		reserved8[3];
 	u8		ip;		/* PSC + 0x34 */
-- 
1.5.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/7] powerpc: BestComm core support for Freescale MPC5200
  2007-09-16 10:53 [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Sylvain Munaut
                   ` (2 preceding siblings ...)
  2007-09-16 10:53 ` [PATCH 3/7] powerpc/ppc32: Update mpc52xx_psc structure with B revision changes Sylvain Munaut
@ 2007-09-16 10:53 ` Sylvain Munaut
  2007-09-16 12:31   ` Stephen Rothwell
                     ` (2 more replies)
  2007-09-16 10:53 ` [PATCH 5/7] powerpc: BestComm ATA task support Sylvain Munaut
                   ` (3 subsequent siblings)
  7 siblings, 3 replies; 15+ messages in thread
From: Sylvain Munaut @ 2007-09-16 10:53 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Grant Likely, Sylvain Munaut, PowerPC dev list

This patch adds support for the core of the BestComm API
for the Freescale MPC5200(b). The BestComm engine is a
microcode-controlled / tasks-based DMA used by several
of the onchip devices.

Setting up the tasks / memory allocation and all common
low level functions are handled by this patch.
The specifics details of each tasks and their microcode
are split-out in separate patches.

This is not the official API, but a much cleaner one.
(hopefully)

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
 arch/powerpc/platforms/Kconfig               |    2 +
 arch/powerpc/sysdev/Makefile                 |    1 +
 arch/powerpc/sysdev/bestcomm/Kconfig         |   18 +
 arch/powerpc/sysdev/bestcomm/Makefile        |    8 +
 arch/powerpc/sysdev/bestcomm/bestcomm.c      |  657 ++++++++++++++++++++++++++
 arch/powerpc/sysdev/bestcomm/bestcomm.h      |  136 ++++++
 arch/powerpc/sysdev/bestcomm/bestcomm_priv.h |  325 +++++++++++++
 arch/powerpc/sysdev/bestcomm/sram.c          |  177 +++++++
 arch/powerpc/sysdev/bestcomm/sram.h          |   54 +++
 9 files changed, 1378 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/sysdev/bestcomm/Kconfig
 create mode 100644 arch/powerpc/sysdev/bestcomm/Makefile
 create mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm.c
 create mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm.h
 create mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
 create mode 100644 arch/powerpc/sysdev/bestcomm/sram.c
 create mode 100644 arch/powerpc/sysdev/bestcomm/sram.h

diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 9189ba5..99d48be 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -293,4 +293,6 @@ config FSL_ULI1575
 	  Freescale reference boards. The boards all use the ULI in pretty
 	  much the same way.
 
+source "arch/powerpc/sysdev/bestcomm/Kconfig"
+
 endmenu
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 08ce31e..0c8a29d 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_FSL_PCI)		+= fsl_pci.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
 obj-$(CONFIG_RTC_DRV_CMOS)	+= rtc_cmos_setup.o
diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/arch/powerpc/sysdev/bestcomm/Kconfig
new file mode 100644
index 0000000..3366e24
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/Kconfig
@@ -0,0 +1,18 @@
+#
+# 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. It's usage is
+	  optionnal 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.
+
diff --git a/arch/powerpc/sysdev/bestcomm/Makefile b/arch/powerpc/sysdev/bestcomm/Makefile
new file mode 100644
index 0000000..a24aa06
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for BestComm & co
+#
+
+bestcomm-core-objs	:= bestcomm.o sram.o
+
+obj-$(CONFIG_PPC_BESTCOMM)		+= bestcomm-core.o
+ 
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c
new file mode 100644
index 0000000..10fb476
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c
@@ -0,0 +1,657 @@
+/*
+ * 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 <asm/io.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/mpc52xx.h>
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+
+#include "sram.h"
+#include "bestcomm_priv.h"
+#include "bestcomm.h"
+
+#define DRIVER_NAME "bestcomm-core"
+
+
+struct bcom_engine *bcom_eng = NULL;
+EXPORT_SYMBOL_GPL(bcom_eng);	/* needed for inline functions */
+
+
+/* ======================================================================== */
+/* Public and private API                                                   */
+/* ======================================================================== */
+
+/* Debug Dump */
+
+#define BCOM_DPRINTK(a,b...) printk(KERN_DEBUG DRIVER_NAME ": " a, ## b)
+
+void
+bcom_dump_status(void)
+{
+	int i;
+	struct mpc52xx_sdma __iomem *r = bcom_eng->regs;
+
+	BCOM_DPRINTK("BestComm status dump (pa=%08lx, va=%p)\n",
+			bcom_eng->regs_base, bcom_eng->regs);
+	BCOM_DPRINTK(" taskBar         = %08x\n", in_be32(&r->taskBar));
+	BCOM_DPRINTK(" currentPointer  = %08x\n", in_be32(&r->currentPointer));
+	BCOM_DPRINTK(" endPointer      = %08x\n", in_be32(&r->endPointer));
+	BCOM_DPRINTK(" variablePointer = %08x\n", in_be32(&r->variablePointer));
+	BCOM_DPRINTK(" IntVect1        = %08x\n", (u32)in_8(&r->IntVect1));
+	BCOM_DPRINTK(" IntVect2        = %08x\n", (u32)in_8(&r->IntVect2));
+	BCOM_DPRINTK(" PtdCntrl        = %08hx\n", in_be16(&r->PtdCntrl));
+	BCOM_DPRINTK(" IntPend         = %08x\n", in_be32(&r->IntPend));
+	BCOM_DPRINTK(" IntMask         = %08x\n", in_be32(&r->IntMask));
+
+	BCOM_DPRINTK(" TCR dump :\n");
+
+	for (i=0; i<16; i++) {
+		printk("%s%04hx%s",
+			(i&0x7) == 0x0 ? KERN_DEBUG "\t" : "",
+			in_be16(&r->tcr[i]),
+			(i&0x7) == 0x7 ? "\n" : " ");
+	}
+
+	BCOM_DPRINTK(" IPR dump :\n");
+
+	for (i=0; i<32; i++) {
+		printk("%s%02x%s",
+			(i&0x7) == 0x0 ? KERN_DEBUG "\t" : "",
+			(u32)in_8(&r->ipr[i]),
+			(i&0x7) == 0x7 ? "\n" : " ");
+	}
+
+	BCOM_DPRINTK(" cReqSelect      = %08x\n", in_be32(&r->cReqSelect));
+	BCOM_DPRINTK(" task_size0      = %08x\n", in_be32(&r->task_size0));
+	BCOM_DPRINTK(" task_size1      = %08x\n", in_be32(&r->task_size1));
+	BCOM_DPRINTK(" MDEDebug        = %08x\n", in_be32(&r->MDEDebug));
+	BCOM_DPRINTK(" ADSDebug        = %08x\n", in_be32(&r->ADSDebug));
+	BCOM_DPRINTK(" Value1          = %08x\n", in_be32(&r->Value1));
+	BCOM_DPRINTK(" Value2          = %08x\n", in_be32(&r->Value2));
+	BCOM_DPRINTK(" Control         = %08x\n", in_be32(&r->Control));
+	BCOM_DPRINTK(" Status          = %08x\n", in_be32(&r->Status));
+	BCOM_DPRINTK(" PTDDebug        = %08x\n", in_be32(&r->PTDDebug));
+}
+EXPORT_SYMBOL_GPL(bcom_dump_status);
+
+void
+bcom_dump_task(int task)
+{
+	int i;
+	u32 *p;
+	struct bcom_tdt *tdt = &bcom_eng->tdt[task];
+
+	BCOM_DPRINTK("Task dump %d\n", task);
+	BCOM_DPRINTK(" tcr          = %04hx\n", bcom_eng->regs->tcr[task]);
+	BCOM_DPRINTK(" tdt          = %p\n", &bcom_eng->tdt[task]);
+	BCOM_DPRINTK(" tdt->start   = %08x\n", tdt->start);
+	BCOM_DPRINTK(" tdt->stop    = %08x\n", tdt->stop);
+	BCOM_DPRINTK(" tdt->var     = %08x\n", tdt->var);
+	BCOM_DPRINTK(" tdt->fdt     = %08x\n", tdt->fdt);
+	BCOM_DPRINTK(" tdt->status  = %08x\n", tdt->exec_status);
+	BCOM_DPRINTK(" tdt->mvtp    = %08x\n", tdt->mvtp);
+	BCOM_DPRINTK(" tdt->context = %08x\n", tdt->context);
+	BCOM_DPRINTK(" tdt->litbase = %08x\n", tdt->litbase);
+
+	BCOM_DPRINTK(" code    :\n");
+
+	p = bcom_task_desc(task);
+	for (i=0; i<bcom_task_num_descs(task); i++)
+		printk(KERN_DEBUG "\t%p %08x\n", &p[i], p[i]);
+
+	BCOM_DPRINTK(" var/inc :\n");
+
+	p = bcom_task_var(task);
+	for (i=0; i<BCOM_MAX_VAR+BCOM_MAX_INC; i++)
+		printk(KERN_DEBUG "\t%p %08x\n", &p[i], p[i]);
+}
+EXPORT_SYMBOL_GPL(bcom_dump_task);
+
+void
+bcom_dump_bdring(struct bcom_task *tsk)
+{
+	int i, j;
+
+	BCOM_DPRINTK("BD ring dump %d\n", tsk->tasknum);
+
+	for (i=0; i<tsk->num_bd; i++) {
+		BCOM_DPRINTK(" BD[%02d] :\n", i);
+		BCOM_DPRINTK("  cookie   : %p\n", tsk->cookie[i]);
+		BCOM_DPRINTK("  status   : %08x\n", tsk->bd[i].status);
+		for (j=0; j<(tsk->bd_size/sizeof(u32))-1; j++)
+			BCOM_DPRINTK("  data[%02d] : %08x\n",
+				j, tsk->bd[i].data[j]);
+	}
+}
+EXPORT_SYMBOL_GPL(bcom_dump_bdring);
+
+
+/* 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;
+
+	/* 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_release(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_release);
+
+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, apparently it's not reliable yet */
+	/* FIXME: This should be done on 5200 and not 5200B ... */
+	out_be16(&bcom_eng->regs->PtdCntrl, in_be16(&bcom_eng->regs->PtdCntrl) | 1);
+
+	/* 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 of_device *op, const struct of_device_id *match)
+{
+	struct device_node *ofn_bcom, *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 */
+	ofn_bcom = op->node;
+	of_node_get(ofn_bcom);
+
+	/* Prepare SRAM */
+	ofn_sram = of_find_compatible_node(NULL, "sram", "mpc5200-sram");
+	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 = ofn_bcom;
+
+	/* Get, reserve & map io */
+	if (of_address_to_resource(bcom_eng->ofnode, 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",
+		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:
+	bcom_sram_cleanup();
+error_ofput:
+	of_node_put(bcom_eng->ofnode);
+
+	printk(KERN_ERR "DMA: MPC52xx BestComm init failed !\n");
+
+	return rv;
+}
+
+
+static int
+mpc52xx_bcom_remove(struct of_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;
+}
+
+
+#ifdef CONFIG_PM
+
+static int
+mpc52xx_bcom_suspend(struct of_device *op, pm_message_t state)
+{
+	return 0;	/* FIXME : What to do here ? */
+}
+
+static int
+mpc52xx_bcom_resume(struct of_device *op)
+{
+	return 0;
+}
+
+#endif
+
+static struct of_device_id mpc52xx_bcom_of_match[] = {
+	{
+		.type		= "dma-controller",
+		.compatible	= "mpc5200-bestcomm",
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
+
+
+static struct of_platform_driver mpc52xx_bcom_of_platform_driver = {
+	.owner		= THIS_MODULE,
+	.name		= DRIVER_NAME,
+	.match_table	= mpc52xx_bcom_of_match,
+	.probe		= mpc52xx_bcom_probe,
+	.remove		= mpc52xx_bcom_remove,
+#ifdef CONFIG_PM
+	.suspend	= mpc52xx_bcom_suspend,
+	.resume		= mpc52xx_bcom_resume,
+#endif
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+
+/* ======================================================================== */
+/* Module                                                                   */
+/* ======================================================================== */
+
+static int __init
+mpc52xx_bcom_init(void)
+{
+	return of_register_platform_driver(&mpc52xx_bcom_of_platform_driver);
+}
+
+static void __exit
+mpc52xx_bcom_exit(void)
+{
+	of_unregister_platform_driver(&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
new file mode 100644
index 0000000..eac3eec
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/bestcomm.h
@@ -0,0 +1,136 @@
+/*
+ * 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; /* defined later on ... */
+
+
+/* ======================================================================== */
+/* Generic task managment                                                   */
+/* ======================================================================== */
+
+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)
+
+
+extern void bcom_enable(struct bcom_task *tsk);
+extern void bcom_disable(struct bcom_task *tsk);
+
+static inline int
+bcom_get_task_irq(struct bcom_task *tsk) {
+	return tsk->irq;
+}
+
+
+/* Debug dumps */
+extern void bcom_dump_status(void);
+extern void bcom_dump_task(int task);
+extern void bcom_dump_bdring(struct bcom_task *tsk);
+
+
+/* ======================================================================== */
+/* BD based tasks helpers                                                   */
+/* ======================================================================== */
+
+struct bcom_bd {
+	u32	status;
+	u32	data[1];	/* variable, but at least 1 */
+};
+
+#define BCOM_BD_READY	0x40000000ul
+
+static inline int	/* user shouldn't use this ! */
+_bcom_next_index(struct bcom_task *tsk)
+{
+	return ((tsk->index + 1) == tsk->num_bd) ? 0 : tsk->index + 1;
+}
+
+static inline int	/* user shouldn't use this ! */
+_bcom_next_outdex(struct bcom_task *tsk)
+{
+	return ((tsk->outdex + 1) == tsk->num_bd) ? 0 : tsk->outdex + 1;
+}
+
+static inline int
+bcom_queue_empty(struct bcom_task *tsk)
+{
+	return tsk->index == tsk->outdex;
+}
+
+static inline int
+bcom_queue_full(struct bcom_task *tsk)
+{
+	return tsk->outdex == _bcom_next_index(tsk);
+}
+
+static inline int
+bcom_buffer_done(struct bcom_task *tsk)
+{
+	if (bcom_queue_empty(tsk))
+		return 0;
+	return !(tsk->bd[tsk->outdex].status & BCOM_BD_READY);
+}
+
+static inline struct bcom_bd *
+bcom_prepare_next_buffer(struct bcom_task *tsk)
+{
+	tsk->bd[tsk->index].status = 0;	/* cleanup last status */
+	return &tsk->bd[tsk->index];
+}
+
+static inline void
+bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie)
+{
+	tsk->cookie[tsk->index] = cookie;
+	mb();	/* ensure the bd is really up-to-date */
+	tsk->bd[tsk->index].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];
+	if (p_status)
+		*p_status = tsk->bd[tsk->outdex].status;
+	if (p_bd)
+		*p_bd = &tsk->bd[tsk->outdex];
+	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
new file mode 100644
index 0000000..6f33f0c
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
@@ -0,0 +1,325 @@
+/*
+ * Private 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_PRIV_H__
+#define __BESTCOMM_PRIV_H__
+
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/prom.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
+
+/* 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;
+};
+
+/* 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 stucture & 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		4
+#define BCOM_IPR_ATA_TX		3
+#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_release(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
+
+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/sram.c b/arch/powerpc/sysdev/bestcomm/sram.c
new file mode 100644
index 0000000..a5094d6
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/sram.c
@@ -0,0 +1,177 @@
+/*
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/prom.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 initialiwed !\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: "
+			"Couln'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, 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
new file mode 100644
index 0000000..b6d6689
--- /dev/null
+++ b/arch/powerpc/sysdev/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__ */
+
-- 
1.5.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/7] powerpc: BestComm ATA task support
  2007-09-16 10:53 [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Sylvain Munaut
                   ` (3 preceding siblings ...)
  2007-09-16 10:53 ` [PATCH 4/7] powerpc: BestComm core support for Freescale MPC5200 Sylvain Munaut
@ 2007-09-16 10:53 ` Sylvain Munaut
  2007-09-16 10:53 ` [PATCH 6/7] powerpc: BestComm FEC " Sylvain Munaut
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Sylvain Munaut @ 2007-09-16 10:53 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Grant Likely, Sylvain Munaut, PowerPC dev list

This is the microcode for the ATA task and the associated
support code.

The microcode itself comes directly from the offical
API (v2.2)

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
 arch/powerpc/sysdev/bestcomm/Kconfig         |    7 +
 arch/powerpc/sysdev/bestcomm/Makefile        |    2 +
 arch/powerpc/sysdev/bestcomm/ata.c           |  154 ++++++++++++++++++++++++++
 arch/powerpc/sysdev/bestcomm/ata.h           |   37 ++++++
 arch/powerpc/sysdev/bestcomm/bcom_ata_task.c |   67 +++++++++++
 5 files changed, 267 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/sysdev/bestcomm/ata.c
 create mode 100644 arch/powerpc/sysdev/bestcomm/ata.h
 create mode 100644 arch/powerpc/sysdev/bestcomm/bcom_ata_task.c

diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/arch/powerpc/sysdev/bestcomm/Kconfig
index 3366e24..9d087ce 100644
--- a/arch/powerpc/sysdev/bestcomm/Kconfig
+++ b/arch/powerpc/sysdev/bestcomm/Kconfig
@@ -16,3 +16,10 @@ config PPC_BESTCOMM
 	  If you want to use drivers that require DMA operations,
 	  answer Y or M. Otherwise say N.
 
+config PPC_BESTCOMM_ATA
+	tristate "Bestcomm ATA task support"
+	depends on PPC_BESTCOMM
+	default n
+	help
+	  This option enables the support for the ATA task.
+
diff --git a/arch/powerpc/sysdev/bestcomm/Makefile b/arch/powerpc/sysdev/bestcomm/Makefile
index a24aa06..b7a6a40 100644
--- a/arch/powerpc/sysdev/bestcomm/Makefile
+++ b/arch/powerpc/sysdev/bestcomm/Makefile
@@ -3,6 +3,8 @@
 #
 
 bestcomm-core-objs	:= bestcomm.o sram.o
+bestcomm-ata-objs	:= ata.o bcom_ata_task.o
 
 obj-$(CONFIG_PPC_BESTCOMM)		+= bestcomm-core.o
+obj-$(CONFIG_PPC_BESTCOMM_ATA)		+= bestcomm-ata.o
  
diff --git a/arch/powerpc/sysdev/bestcomm/ata.c b/arch/powerpc/sysdev/bestcomm/ata.c
new file mode 100644
index 0000000..4b213b1
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/ata.c
@@ -0,0 +1,154 @@
+/*
+ * 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;
+
+	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_release(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_release(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
new file mode 100644
index 0000000..1098276
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/ata.h
@@ -0,0 +1,37 @@
+/*
+ * 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	dst_pa;
+	u32	src_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);
+
+
+#endif /* __BESTCOMM_ATA_H__ */
+
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_ata_task.c b/arch/powerpc/sysdev/bestcomm/bcom_ata_task.c
new file mode 100644
index 0000000..cc6049a
--- /dev/null
+++ b/arch/powerpc/sysdev/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,
+};
+
-- 
1.5.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/7] powerpc: BestComm FEC task support
  2007-09-16 10:53 [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Sylvain Munaut
                   ` (4 preceding siblings ...)
  2007-09-16 10:53 ` [PATCH 5/7] powerpc: BestComm ATA task support Sylvain Munaut
@ 2007-09-16 10:53 ` Sylvain Munaut
  2007-09-16 10:53 ` [PATCH 7/7] powerpc: BestComm GenBD " Sylvain Munaut
  2007-09-18  2:15 ` [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Jon Smirl
  7 siblings, 0 replies; 15+ messages in thread
From: Sylvain Munaut @ 2007-09-16 10:53 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Grant Likely, Sylvain Munaut, PowerPC dev list

This is the microcode for the FEC task and the associated
support code.

The microcode itself comes directly from the offical
API (v2.2)

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
 arch/powerpc/sysdev/bestcomm/Kconfig            |    7 +
 arch/powerpc/sysdev/bestcomm/Makefile           |    2 +
 arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c |   78 +++++++
 arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c |   91 ++++++++
 arch/powerpc/sysdev/bestcomm/fec.c              |  270 +++++++++++++++++++++++
 arch/powerpc/sysdev/bestcomm/fec.h              |   48 ++++
 6 files changed, 496 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c
 create mode 100644 arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c
 create mode 100644 arch/powerpc/sysdev/bestcomm/fec.c
 create mode 100644 arch/powerpc/sysdev/bestcomm/fec.h

diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/arch/powerpc/sysdev/bestcomm/Kconfig
index 9d087ce..831763b 100644
--- a/arch/powerpc/sysdev/bestcomm/Kconfig
+++ b/arch/powerpc/sysdev/bestcomm/Kconfig
@@ -23,3 +23,10 @@ config PPC_BESTCOMM_ATA
 	help
 	  This option enables the support for the ATA task.
 
+config PPC_BESTCOMM_FEC
+	tristate "Bestcomm FEC tasks support"
+	depends on PPC_BESTCOMM
+	default n
+	help
+	  This option enables the support for the FEC tasks.
+
diff --git a/arch/powerpc/sysdev/bestcomm/Makefile b/arch/powerpc/sysdev/bestcomm/Makefile
index b7a6a40..537d174 100644
--- a/arch/powerpc/sysdev/bestcomm/Makefile
+++ b/arch/powerpc/sysdev/bestcomm/Makefile
@@ -4,7 +4,9 @@
 
 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
 
 obj-$(CONFIG_PPC_BESTCOMM)		+= bestcomm-core.o
 obj-$(CONFIG_PPC_BESTCOMM_ATA)		+= bestcomm-ata.o
+obj-$(CONFIG_PPC_BESTCOMM_FEC)		+= bestcomm-fec.o
  
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c
new file mode 100644
index 0000000..a1ad6a0
--- /dev/null
+++ b/arch/powerpc/sysdev/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/arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c
new file mode 100644
index 0000000..b1c495c
--- /dev/null
+++ b/arch/powerpc/sysdev/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/arch/powerpc/sysdev/bestcomm/fec.c b/arch/powerpc/sysdev/bestcomm/fec.c
new file mode 100644
index 0000000..1d7bf40
--- /dev/null
+++ b/arch/powerpc/sysdev/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 "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_release(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_release(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_release(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_release(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
new file mode 100644
index 0000000..fa880ca
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/fec.h
@@ -0,0 +1,48 @@
+/*
+ * 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_INT	0x04000000ul	/* interrupt */
+
+
+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__ */
+
-- 
1.5.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/7] powerpc: BestComm GenBD task support
  2007-09-16 10:53 [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Sylvain Munaut
                   ` (5 preceding siblings ...)
  2007-09-16 10:53 ` [PATCH 6/7] powerpc: BestComm FEC " Sylvain Munaut
@ 2007-09-16 10:53 ` Sylvain Munaut
  2007-09-18  2:15 ` [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Jon Smirl
  7 siblings, 0 replies; 15+ messages in thread
From: Sylvain Munaut @ 2007-09-16 10:53 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Grant Likely, Sylvain Munaut, PowerPC dev list

This is the microcode for the GenBD task and the associated
support code. This is a generic task that copy data to/from
a hardware FIFO. This is currently locked to 32bits wide
access but could be extended as needed.

The microcode itself comes directly from the offical
API (v2.2)

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
 arch/powerpc/sysdev/bestcomm/Kconfig               |    7 +
 arch/powerpc/sysdev/bestcomm/Makefile              |    2 +
 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/gen_bd.c              |  260 ++++++++++++++++++++
 arch/powerpc/sysdev/bestcomm/gen_bd.h              |   48 ++++
 6 files changed, 449 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c
 create mode 100644 arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c
 create mode 100644 arch/powerpc/sysdev/bestcomm/gen_bd.c
 create mode 100644 arch/powerpc/sysdev/bestcomm/gen_bd.h

diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/arch/powerpc/sysdev/bestcomm/Kconfig
index 831763b..57cc565 100644
--- a/arch/powerpc/sysdev/bestcomm/Kconfig
+++ b/arch/powerpc/sysdev/bestcomm/Kconfig
@@ -30,3 +30,10 @@ config PPC_BESTCOMM_FEC
 	help
 	  This option enables the support for the FEC tasks.
 
+config PPC_BESTCOMM_GEN_BD
+	tristate "Bestcomm GenBD tasks support"
+	depends on PPC_BESTCOMM
+	default n
+	help
+	  This option enables the support for the GenBD tasks.
+
diff --git a/arch/powerpc/sysdev/bestcomm/Makefile b/arch/powerpc/sysdev/bestcomm/Makefile
index 537d174..aed2df2 100644
--- a/arch/powerpc/sysdev/bestcomm/Makefile
+++ b/arch/powerpc/sysdev/bestcomm/Makefile
@@ -5,8 +5,10 @@
 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/bcom_gen_bd_rx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c
new file mode 100644
index 0000000..efee022
--- /dev/null
+++ b/arch/powerpc/sysdev/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/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c
new file mode 100644
index 0000000..c605aa4
--- /dev/null
+++ b/arch/powerpc/sysdev/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/arch/powerpc/sysdev/bestcomm/gen_bd.c b/arch/powerpc/sysdev/bestcomm/gen_bd.c
new file mode 100644
index 0000000..4470482
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/gen_bd.c
@@ -0,0 +1,260 @@
+/*
+ * 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/version.h>
+#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 "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_release(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_release(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_release(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_release(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release);
+
+
+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
new file mode 100644
index 0000000..5b6fa80
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/gen_bd.h
@@ -0,0 +1,48 @@
+/*
+ * 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);
+
+
+#endif  /* __BESTCOMM_GEN_BD_H__ */
+
-- 
1.5.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/7] powerpc: BestComm core support for Freescale MPC5200
  2007-09-16 10:53 ` [PATCH 4/7] powerpc: BestComm core support for Freescale MPC5200 Sylvain Munaut
@ 2007-09-16 12:31   ` Stephen Rothwell
  2007-09-16 16:07   ` Kumar Gala
  2007-09-17  8:57   ` Matt Sealey
  2 siblings, 0 replies; 15+ messages in thread
From: Stephen Rothwell @ 2007-09-16 12:31 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: Grant Likely, Paul Mackerras, PowerPC dev list

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

On Sun, 16 Sep 2007 12:53:27 +0200 Sylvain Munaut <tnt@246tNt.com> wrote:
>
> +++ b/arch/powerpc/sysdev/bestcomm/Makefile
> @@ -0,0 +1,8 @@
> +#
> +# Makefile for BestComm & co
> +#
> +
> +bestcomm-core-objs	:= bestcomm.o sram.o
> +
> +obj-$(CONFIG_PPC_BESTCOMM)		+= bestcomm-core.o

Or just obj-y since the whole makefile is dependent on CONFIG_PPC_BESTCOMM.

> +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c
>
> +#include <asm/io.h>
> +#include <asm/irq.h>
> +#include <asm/prom.h>
> +#include <asm/mpc52xx.h>
> +#include <asm/of_device.h>
> +#include <asm/of_platform.h>

Please include linux/of_device.h and linux/of_platform.h instead.
And linux/of.h instead of asm/prom.h.

> +	ofn_bcom = op->node;
> +	of_node_get(ofn_bcom);

The usual idiom is ofn_bcom = of_get_node(op->node);

> +	/* Save the node */
> +	bcom_eng->ofnode = ofn_bcom;
> +
> +	/* Get, reserve & map io */
> +	if (of_address_to_resource(bcom_eng->ofnode, 0, &res_bcom)) {
                                   ^^^^^^^^^^^^^^^^
Any reason not to use ofn_bcom here?

> +	/* Error path */
> +error_unmap:
> +	iounmap(bcom_eng->regs);
> +error_release:
> +	release_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma));
> +error_sramclean:
> +	bcom_sram_cleanup();
> +error_ofput:
> +	of_node_put(bcom_eng->ofnode);
                    ^^^^^^^^^^^^^^^^
And here?  Also bcom_eng doesn't get freed in the error path.

> +++ b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
> +#include <linux/spinlock.h>
> +#include <asm/io.h>
> +#include <asm/prom.h>

Again please include linux/of.h instead of asm/prom.h

> +++ b/arch/powerpc/sysdev/bestcomm/sram.c
> +
> +#include <asm/io.h>
> +#include <asm/mmu.h>
> +#include <asm/prom.h>

And again.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/7] powerpc: Changes the config mechanism for rheap
  2007-09-16 10:53 ` [PATCH 2/7] powerpc: Changes the config mechanism for rheap Sylvain Munaut
@ 2007-09-16 15:59   ` Kumar Gala
  0 siblings, 0 replies; 15+ messages in thread
From: Kumar Gala @ 2007-09-16 15:59 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: Grant Likely, Paul Mackerras, PowerPC dev list


On Sep 16, 2007, at 5:53 AM, Sylvain Munaut wrote:

> Instead of having in the makefile all the option that
> requires rheap, we define a configuration symbol
> and when needed we make sure it's selected.
>
> Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
> ---
>  arch/powerpc/Kconfig                   |    2 ++
>  arch/powerpc/lib/Kconfig               |    3 +++
>  arch/powerpc/lib/Makefile              |    5 +----
>  arch/powerpc/platforms/Kconfig         |    2 ++
>  arch/powerpc/platforms/Kconfig.cputype |    1 +
>  5 files changed, 9 insertions(+), 4 deletions(-)
>  create mode 100644 arch/powerpc/lib/Kconfig

This probably breaks arch/ppc in that you'll need to add the proper  
select PPC_LIB_RHEAP to its Kconfig(s) for 8xx & CPM2.

> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 00099ef..76063b9 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -634,6 +634,8 @@ source "fs/Kconfig"
>
>  source "arch/powerpc/sysdev/qe_lib/Kconfig"
>
> +source "arch/powerpc/lib/Kconfig"
> +
>  source "lib/Kconfig"
>
>  menu "Instrumentation Support"
> diff --git a/arch/powerpc/lib/Kconfig b/arch/powerpc/lib/Kconfig
> new file mode 100644
> index 0000000..f383ad4

why not just stick this in the toplevel powerpc/Kconfig

> --- /dev/null
> +++ b/arch/powerpc/lib/Kconfig
> @@ -0,0 +1,3 @@
> +config PPC_LIB_RHEAP
> +	bool
> +	default n

Please add a help description here.

[snip]

- k

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/7] powerpc: BestComm core support for Freescale MPC5200
  2007-09-16 10:53 ` [PATCH 4/7] powerpc: BestComm core support for Freescale MPC5200 Sylvain Munaut
  2007-09-16 12:31   ` Stephen Rothwell
@ 2007-09-16 16:07   ` Kumar Gala
  2007-09-17  8:57   ` Matt Sealey
  2 siblings, 0 replies; 15+ messages in thread
From: Kumar Gala @ 2007-09-16 16:07 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: Grant Likely, Paul Mackerras, PowerPC dev list


On Sep 16, 2007, at 5:53 AM, Sylvain Munaut wrote:

> This patch adds support for the core of the BestComm API
> for the Freescale MPC5200(b). The BestComm engine is a
> microcode-controlled / tasks-based DMA used by several
> of the onchip devices.
>
> Setting up the tasks / memory allocation and all common
> low level functions are handled by this patch.
> The specifics details of each tasks and their microcode
> are split-out in separate patches.
>
> This is not the official API, but a much cleaner one.
> (hopefully)
>
> Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
> ---
>  arch/powerpc/platforms/Kconfig               |    2 +
>  arch/powerpc/sysdev/Makefile                 |    1 +
>  arch/powerpc/sysdev/bestcomm/Kconfig         |   18 +
>  arch/powerpc/sysdev/bestcomm/Makefile        |    8 +
>  arch/powerpc/sysdev/bestcomm/bestcomm.c      |  657 +++++++++++++++ 
> +++++++++++
>  arch/powerpc/sysdev/bestcomm/bestcomm.h      |  136 ++++++
>  arch/powerpc/sysdev/bestcomm/bestcomm_priv.h |  325 +++++++++++++
>  arch/powerpc/sysdev/bestcomm/sram.c          |  177 +++++++
>  arch/powerpc/sysdev/bestcomm/sram.h          |   54 +++
>  9 files changed, 1378 insertions(+), 0 deletions(-)
>  create mode 100644 arch/powerpc/sysdev/bestcomm/Kconfig
>  create mode 100644 arch/powerpc/sysdev/bestcomm/Makefile
>  create mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm.c
>  create mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm.h
>  create mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
>  create mode 100644 arch/powerpc/sysdev/bestcomm/sram.c
>  create mode 100644 arch/powerpc/sysdev/bestcomm/sram.h

this version still doesn't address comments made back in may:

http://ozlabs.org/pipermail/linuxppc-dev/2007-May/036224.html

Also, what about splitting bestcomm.c into bestcomm_task.c &  
bestcomm_drv.c (or just bestcomm.c) or something like that.  It seems  
'private API' isn't really the proper term.

- k

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/7] powerpc: BestComm core support for Freescale MPC5200
  2007-09-16 10:53 ` [PATCH 4/7] powerpc: BestComm core support for Freescale MPC5200 Sylvain Munaut
  2007-09-16 12:31   ` Stephen Rothwell
  2007-09-16 16:07   ` Kumar Gala
@ 2007-09-17  8:57   ` Matt Sealey
  2 siblings, 0 replies; 15+ messages in thread
From: Matt Sealey @ 2007-09-17  8:57 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: Grant Likely, Paul Mackerras, PowerPC dev list

My only nitpick is the function naming.

Why not bestcomm_blah() rather than bcom_blah()?

I also think, even though the SRAM functionality is dependant
on BestComm (it's hard to seperate into another driver because
of kernel driver init order being 'random'?) it should be named
after the chip and not the DMA unit - the SRAM can be used for
pretty much anything a developer wants.

For instance, you could allocate it for the power management
code, or simply as some kind of buffer between a PIO managed
port if you do not want to use main memory for some reason.
On the MPC5121E it looks like AXE (audio DSP) and certain other
components will be sharing SRAM with BestComm and there will
be a good deal more of it.

Just looking to the future on some code sharing, because of
the above.

On a lighter note (not something that should block these
patches), would it be a good idea perhaps to abstract SRAM
allocations into a driver class of it's own in this same
way? Nearly every SoC has some kind of built-in SRAM and
even some Northbridges (Marvell Discovery) - ostensibly for
peripheral buffers like ethernet and so on, they can still
be used for anything. Couldn't it be a library or driver
simply with a custom init/teardown function (platform
specific)? I suppose the fact that SRAM could be probed
after BestComm or other peripherals is the problem here,
but there is a platform device for Pegasos ethernet which
modifies Discovery SRAM parameters.. I suppose this is
what I am thinking of getting rid of and allowing code
to be shared and SRAM allocation and usage becoming more
of a tool for other devices and drivers to use, and not
simply something claimed/controlled by BestComm or Ethernet,
and occasionally hijacked by something else.

-- 
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations

Sylvain Munaut wrote:
> This patch adds support for the core of the BestComm API
> for the Freescale MPC5200(b). The BestComm engine is a
> microcode-controlled / tasks-based DMA used by several
> of the onchip devices.
> 
> Setting up the tasks / memory allocation and all common
> low level functions are handled by this patch.
> The specifics details of each tasks and their microcode
> are split-out in separate patches.
> 
> This is not the official API, but a much cleaner one.
> (hopefully)
> 
> Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
> ---
>  arch/powerpc/platforms/Kconfig               |    2 +
>  arch/powerpc/sysdev/Makefile                 |    1 +
>  arch/powerpc/sysdev/bestcomm/Kconfig         |   18 +
>  arch/powerpc/sysdev/bestcomm/Makefile        |    8 +
>  arch/powerpc/sysdev/bestcomm/bestcomm.c      |  657 ++++++++++++++++++++++++++
>  arch/powerpc/sysdev/bestcomm/bestcomm.h      |  136 ++++++
>  arch/powerpc/sysdev/bestcomm/bestcomm_priv.h |  325 +++++++++++++
>  arch/powerpc/sysdev/bestcomm/sram.c          |  177 +++++++
>  arch/powerpc/sysdev/bestcomm/sram.h          |   54 +++
>  9 files changed, 1378 insertions(+), 0 deletions(-)
>  create mode 100644 arch/powerpc/sysdev/bestcomm/Kconfig
>  create mode 100644 arch/powerpc/sysdev/bestcomm/Makefile
>  create mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm.c
>  create mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm.h
>  create mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
>  create mode 100644 arch/powerpc/sysdev/bestcomm/sram.c
>  create mode 100644 arch/powerpc/sysdev/bestcomm/sram.h
> 
> diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
> index 9189ba5..99d48be 100644
> --- a/arch/powerpc/platforms/Kconfig
> +++ b/arch/powerpc/platforms/Kconfig
> @@ -293,4 +293,6 @@ config FSL_ULI1575
>  	  Freescale reference boards. The boards all use the ULI in pretty
>  	  much the same way.
>  
> +source "arch/powerpc/sysdev/bestcomm/Kconfig"
> +
>  endmenu
> diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
> index 08ce31e..0c8a29d 100644
> --- a/arch/powerpc/sysdev/Makefile
> +++ b/arch/powerpc/sysdev/Makefile
> @@ -15,6 +15,7 @@ obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
>  obj-$(CONFIG_FSL_PCI)		+= fsl_pci.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
>  obj-$(CONFIG_RTC_DRV_CMOS)	+= rtc_cmos_setup.o
> diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/arch/powerpc/sysdev/bestcomm/Kconfig
> new file mode 100644
> index 0000000..3366e24
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/Kconfig
> @@ -0,0 +1,18 @@
> +#
> +# 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. It's usage is
> +	  optionnal 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.
> +
> diff --git a/arch/powerpc/sysdev/bestcomm/Makefile b/arch/powerpc/sysdev/bestcomm/Makefile
> new file mode 100644
> index 0000000..a24aa06
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/Makefile
> @@ -0,0 +1,8 @@
> +#
> +# Makefile for BestComm & co
> +#
> +
> +bestcomm-core-objs	:= bestcomm.o sram.o
> +
> +obj-$(CONFIG_PPC_BESTCOMM)		+= bestcomm-core.o
> + 
> diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c
> new file mode 100644
> index 0000000..10fb476
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c
> @@ -0,0 +1,657 @@
> +/*
> + * 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 <asm/io.h>
> +#include <asm/irq.h>
> +#include <asm/prom.h>
> +#include <asm/mpc52xx.h>
> +#include <asm/of_device.h>
> +#include <asm/of_platform.h>
> +
> +#include "sram.h"
> +#include "bestcomm_priv.h"
> +#include "bestcomm.h"
> +
> +#define DRIVER_NAME "bestcomm-core"
> +
> +
> +struct bcom_engine *bcom_eng = NULL;
> +EXPORT_SYMBOL_GPL(bcom_eng);	/* needed for inline functions */
> +
> +
> +/* ======================================================================== */
> +/* Public and private API                                                   */
> +/* ======================================================================== */
> +
> +/* Debug Dump */
> +
> +#define BCOM_DPRINTK(a,b...) printk(KERN_DEBUG DRIVER_NAME ": " a, ## b)
> +
> +void
> +bcom_dump_status(void)
> +{
> +	int i;
> +	struct mpc52xx_sdma __iomem *r = bcom_eng->regs;
> +
> +	BCOM_DPRINTK("BestComm status dump (pa=%08lx, va=%p)\n",
> +			bcom_eng->regs_base, bcom_eng->regs);
> +	BCOM_DPRINTK(" taskBar         = %08x\n", in_be32(&r->taskBar));
> +	BCOM_DPRINTK(" currentPointer  = %08x\n", in_be32(&r->currentPointer));
> +	BCOM_DPRINTK(" endPointer      = %08x\n", in_be32(&r->endPointer));
> +	BCOM_DPRINTK(" variablePointer = %08x\n", in_be32(&r->variablePointer));
> +	BCOM_DPRINTK(" IntVect1        = %08x\n", (u32)in_8(&r->IntVect1));
> +	BCOM_DPRINTK(" IntVect2        = %08x\n", (u32)in_8(&r->IntVect2));
> +	BCOM_DPRINTK(" PtdCntrl        = %08hx\n", in_be16(&r->PtdCntrl));
> +	BCOM_DPRINTK(" IntPend         = %08x\n", in_be32(&r->IntPend));
> +	BCOM_DPRINTK(" IntMask         = %08x\n", in_be32(&r->IntMask));
> +
> +	BCOM_DPRINTK(" TCR dump :\n");
> +
> +	for (i=0; i<16; i++) {
> +		printk("%s%04hx%s",
> +			(i&0x7) == 0x0 ? KERN_DEBUG "\t" : "",
> +			in_be16(&r->tcr[i]),
> +			(i&0x7) == 0x7 ? "\n" : " ");
> +	}
> +
> +	BCOM_DPRINTK(" IPR dump :\n");
> +
> +	for (i=0; i<32; i++) {
> +		printk("%s%02x%s",
> +			(i&0x7) == 0x0 ? KERN_DEBUG "\t" : "",
> +			(u32)in_8(&r->ipr[i]),
> +			(i&0x7) == 0x7 ? "\n" : " ");
> +	}
> +
> +	BCOM_DPRINTK(" cReqSelect      = %08x\n", in_be32(&r->cReqSelect));
> +	BCOM_DPRINTK(" task_size0      = %08x\n", in_be32(&r->task_size0));
> +	BCOM_DPRINTK(" task_size1      = %08x\n", in_be32(&r->task_size1));
> +	BCOM_DPRINTK(" MDEDebug        = %08x\n", in_be32(&r->MDEDebug));
> +	BCOM_DPRINTK(" ADSDebug        = %08x\n", in_be32(&r->ADSDebug));
> +	BCOM_DPRINTK(" Value1          = %08x\n", in_be32(&r->Value1));
> +	BCOM_DPRINTK(" Value2          = %08x\n", in_be32(&r->Value2));
> +	BCOM_DPRINTK(" Control         = %08x\n", in_be32(&r->Control));
> +	BCOM_DPRINTK(" Status          = %08x\n", in_be32(&r->Status));
> +	BCOM_DPRINTK(" PTDDebug        = %08x\n", in_be32(&r->PTDDebug));
> +}
> +EXPORT_SYMBOL_GPL(bcom_dump_status);
> +
> +void
> +bcom_dump_task(int task)
> +{
> +	int i;
> +	u32 *p;
> +	struct bcom_tdt *tdt = &bcom_eng->tdt[task];
> +
> +	BCOM_DPRINTK("Task dump %d\n", task);
> +	BCOM_DPRINTK(" tcr          = %04hx\n", bcom_eng->regs->tcr[task]);
> +	BCOM_DPRINTK(" tdt          = %p\n", &bcom_eng->tdt[task]);
> +	BCOM_DPRINTK(" tdt->start   = %08x\n", tdt->start);
> +	BCOM_DPRINTK(" tdt->stop    = %08x\n", tdt->stop);
> +	BCOM_DPRINTK(" tdt->var     = %08x\n", tdt->var);
> +	BCOM_DPRINTK(" tdt->fdt     = %08x\n", tdt->fdt);
> +	BCOM_DPRINTK(" tdt->status  = %08x\n", tdt->exec_status);
> +	BCOM_DPRINTK(" tdt->mvtp    = %08x\n", tdt->mvtp);
> +	BCOM_DPRINTK(" tdt->context = %08x\n", tdt->context);
> +	BCOM_DPRINTK(" tdt->litbase = %08x\n", tdt->litbase);
> +
> +	BCOM_DPRINTK(" code    :\n");
> +
> +	p = bcom_task_desc(task);
> +	for (i=0; i<bcom_task_num_descs(task); i++)
> +		printk(KERN_DEBUG "\t%p %08x\n", &p[i], p[i]);
> +
> +	BCOM_DPRINTK(" var/inc :\n");
> +
> +	p = bcom_task_var(task);
> +	for (i=0; i<BCOM_MAX_VAR+BCOM_MAX_INC; i++)
> +		printk(KERN_DEBUG "\t%p %08x\n", &p[i], p[i]);
> +}
> +EXPORT_SYMBOL_GPL(bcom_dump_task);
> +
> +void
> +bcom_dump_bdring(struct bcom_task *tsk)
> +{
> +	int i, j;
> +
> +	BCOM_DPRINTK("BD ring dump %d\n", tsk->tasknum);
> +
> +	for (i=0; i<tsk->num_bd; i++) {
> +		BCOM_DPRINTK(" BD[%02d] :\n", i);
> +		BCOM_DPRINTK("  cookie   : %p\n", tsk->cookie[i]);
> +		BCOM_DPRINTK("  status   : %08x\n", tsk->bd[i].status);
> +		for (j=0; j<(tsk->bd_size/sizeof(u32))-1; j++)
> +			BCOM_DPRINTK("  data[%02d] : %08x\n",
> +				j, tsk->bd[i].data[j]);
> +	}
> +}
> +EXPORT_SYMBOL_GPL(bcom_dump_bdring);
> +
> +
> +/* 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;
> +
> +	/* 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_release(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_release);
> +
> +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, apparently it's not reliable yet */
> +	/* FIXME: This should be done on 5200 and not 5200B ... */
> +	out_be16(&bcom_eng->regs->PtdCntrl, in_be16(&bcom_eng->regs->PtdCntrl) | 1);
> +
> +	/* 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 of_device *op, const struct of_device_id *match)
> +{
> +	struct device_node *ofn_bcom, *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 */
> +	ofn_bcom = op->node;
> +	of_node_get(ofn_bcom);
> +
> +	/* Prepare SRAM */
> +	ofn_sram = of_find_compatible_node(NULL, "sram", "mpc5200-sram");
> +	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 = ofn_bcom;
> +
> +	/* Get, reserve & map io */
> +	if (of_address_to_resource(bcom_eng->ofnode, 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",
> +		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:
> +	bcom_sram_cleanup();
> +error_ofput:
> +	of_node_put(bcom_eng->ofnode);
> +
> +	printk(KERN_ERR "DMA: MPC52xx BestComm init failed !\n");
> +
> +	return rv;
> +}
> +
> +
> +static int
> +mpc52xx_bcom_remove(struct of_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;
> +}
> +
> +
> +#ifdef CONFIG_PM
> +
> +static int
> +mpc52xx_bcom_suspend(struct of_device *op, pm_message_t state)
> +{
> +	return 0;	/* FIXME : What to do here ? */
> +}
> +
> +static int
> +mpc52xx_bcom_resume(struct of_device *op)
> +{
> +	return 0;
> +}
> +
> +#endif
> +
> +static struct of_device_id mpc52xx_bcom_of_match[] = {
> +	{
> +		.type		= "dma-controller",
> +		.compatible	= "mpc5200-bestcomm",
> +	},
> +	{},
> +};
> +
> +MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
> +
> +
> +static struct of_platform_driver mpc52xx_bcom_of_platform_driver = {
> +	.owner		= THIS_MODULE,
> +	.name		= DRIVER_NAME,
> +	.match_table	= mpc52xx_bcom_of_match,
> +	.probe		= mpc52xx_bcom_probe,
> +	.remove		= mpc52xx_bcom_remove,
> +#ifdef CONFIG_PM
> +	.suspend	= mpc52xx_bcom_suspend,
> +	.resume		= mpc52xx_bcom_resume,
> +#endif
> +	.driver		= {
> +		.name	= DRIVER_NAME,
> +		.owner	= THIS_MODULE,
> +	},
> +};
> +
> +
> +/* ======================================================================== */
> +/* Module                                                                   */
> +/* ======================================================================== */
> +
> +static int __init
> +mpc52xx_bcom_init(void)
> +{
> +	return of_register_platform_driver(&mpc52xx_bcom_of_platform_driver);
> +}
> +
> +static void __exit
> +mpc52xx_bcom_exit(void)
> +{
> +	of_unregister_platform_driver(&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
> new file mode 100644
> index 0000000..eac3eec
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.h
> @@ -0,0 +1,136 @@
> +/*
> + * 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; /* defined later on ... */
> +
> +
> +/* ======================================================================== */
> +/* Generic task managment                                                   */
> +/* ======================================================================== */
> +
> +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)
> +
> +
> +extern void bcom_enable(struct bcom_task *tsk);
> +extern void bcom_disable(struct bcom_task *tsk);
> +
> +static inline int
> +bcom_get_task_irq(struct bcom_task *tsk) {
> +	return tsk->irq;
> +}
> +
> +
> +/* Debug dumps */
> +extern void bcom_dump_status(void);
> +extern void bcom_dump_task(int task);
> +extern void bcom_dump_bdring(struct bcom_task *tsk);
> +
> +
> +/* ======================================================================== */
> +/* BD based tasks helpers                                                   */
> +/* ======================================================================== */
> +
> +struct bcom_bd {
> +	u32	status;
> +	u32	data[1];	/* variable, but at least 1 */
> +};
> +
> +#define BCOM_BD_READY	0x40000000ul
> +
> +static inline int	/* user shouldn't use this ! */
> +_bcom_next_index(struct bcom_task *tsk)
> +{
> +	return ((tsk->index + 1) == tsk->num_bd) ? 0 : tsk->index + 1;
> +}
> +
> +static inline int	/* user shouldn't use this ! */
> +_bcom_next_outdex(struct bcom_task *tsk)
> +{
> +	return ((tsk->outdex + 1) == tsk->num_bd) ? 0 : tsk->outdex + 1;
> +}
> +
> +static inline int
> +bcom_queue_empty(struct bcom_task *tsk)
> +{
> +	return tsk->index == tsk->outdex;
> +}
> +
> +static inline int
> +bcom_queue_full(struct bcom_task *tsk)
> +{
> +	return tsk->outdex == _bcom_next_index(tsk);
> +}
> +
> +static inline int
> +bcom_buffer_done(struct bcom_task *tsk)
> +{
> +	if (bcom_queue_empty(tsk))
> +		return 0;
> +	return !(tsk->bd[tsk->outdex].status & BCOM_BD_READY);
> +}
> +
> +static inline struct bcom_bd *
> +bcom_prepare_next_buffer(struct bcom_task *tsk)
> +{
> +	tsk->bd[tsk->index].status = 0;	/* cleanup last status */
> +	return &tsk->bd[tsk->index];
> +}
> +
> +static inline void
> +bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie)
> +{
> +	tsk->cookie[tsk->index] = cookie;
> +	mb();	/* ensure the bd is really up-to-date */
> +	tsk->bd[tsk->index].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];
> +	if (p_status)
> +		*p_status = tsk->bd[tsk->outdex].status;
> +	if (p_bd)
> +		*p_bd = &tsk->bd[tsk->outdex];
> +	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
> new file mode 100644
> index 0000000..6f33f0c
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
> @@ -0,0 +1,325 @@
> +/*
> + * Private 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_PRIV_H__
> +#define __BESTCOMM_PRIV_H__
> +
> +#include <linux/spinlock.h>
> +#include <asm/io.h>
> +#include <asm/prom.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
> +
> +/* 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;
> +};
> +
> +/* 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 stucture & 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		4
> +#define BCOM_IPR_ATA_TX		3
> +#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_release(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
> +
> +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/sram.c b/arch/powerpc/sysdev/bestcomm/sram.c
> new file mode 100644
> index 0000000..a5094d6
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/sram.c
> @@ -0,0 +1,177 @@
> +/*
> + * 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/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/string.h>
> +#include <linux/ioport.h>
> +
> +#include <asm/io.h>
> +#include <asm/mmu.h>
> +#include <asm/prom.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 initialiwed !\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: "
> +			"Couln'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, 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
> new file mode 100644
> index 0000000..b6d6689
> --- /dev/null
> +++ b/arch/powerpc/sysdev/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__ */
> +

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24
  2007-09-16 10:53 [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Sylvain Munaut
                   ` (6 preceding siblings ...)
  2007-09-16 10:53 ` [PATCH 7/7] powerpc: BestComm GenBD " Sylvain Munaut
@ 2007-09-18  2:15 ` Jon Smirl
  2007-09-18  4:29   ` tnt
  7 siblings, 1 reply; 15+ messages in thread
From: Jon Smirl @ 2007-09-18  2:15 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: Grant Likely, Paul Mackerras, PowerPC dev list

On 9/16/07, Sylvain Munaut <tnt@246tnt.com> wrote:
> Hello Paul, Hi everyone,
>
> This series of patch is mainly the bestcomm support for
> the mpc5200. It was posted a while ago and received some
> comments. Theses are all addressed here (afaik).

Does this series supersede these pacthes out of your older series?

0010-powerpc-In-rheap.c-move-the-EXPORT_SYMBOL-and-use.patch
0011-powerpc-BestComm-move-the-EXPORT_SYMBOL-and-use-th.patch
0012-powerpc-BestComm-ATA-task-move-the-EXPORT_SYMBOL-a.patch
0013-powerpc-BestComm-FEC-task-move-the-EXPORT_SYMBOL-a.patch
0014-powerpc-BestComm-GenBD-task-move-the-EXPORT_SYMBOL.patch
0015-powerpc-BestComm-Replace-global-variable-bcom-by-b.patch
0016-powerpc-Make-the-BestComm-driver-a-standard-of_plat.patch
0017-powerpc-Fix-typo-in-BestComm-ATA-task-support-code.patch
0018-powerpc-BestComm-ATA-task-microcode-insert-copyri.patch
0019-powerpc-BestComm-FEC-task-microcode-insert-copyri.patch
0020-powerpc-BestComm-GenBD-task-microcode-insert-copy.patch
0021-powerpc-Fix-errors-in-bcom-bcom_eng-renaming.patch



-- 
Jon Smirl
jonsmirl@gmail.com

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24
  2007-09-18  2:15 ` [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Jon Smirl
@ 2007-09-18  4:29   ` tnt
  2007-09-18 14:11     ` Kumar Gala
  0 siblings, 1 reply; 15+ messages in thread
From: tnt @ 2007-09-18  4:29 UTC (permalink / raw)
  To: Jon Smirl; +Cc: PowerPC dev list

> On 9/16/07, Sylvain Munaut <tnt@246tnt.com> wrote:
>> Hello Paul, Hi everyone,
>>
>> This series of patch is mainly the bestcomm support for
>> the mpc5200. It was posted a while ago and received some
>> comments. Theses are all addressed here (afaik).
>
> Does this series supersede these pacthes out of your older series?

Yes.
Those are the patches I wrote to fix the comments received last time.
They are now merged inside the main patches.

Apparently I forgot to fix some other comments so I'll have to do
that and repost again.


Sylvain

>
> 0010-powerpc-In-rheap.c-move-the-EXPORT_SYMBOL-and-use.patch
> 0011-powerpc-BestComm-move-the-EXPORT_SYMBOL-and-use-th.patch
> 0012-powerpc-BestComm-ATA-task-move-the-EXPORT_SYMBOL-a.patch
> 0013-powerpc-BestComm-FEC-task-move-the-EXPORT_SYMBOL-a.patch
> 0014-powerpc-BestComm-GenBD-task-move-the-EXPORT_SYMBOL.patch
> 0015-powerpc-BestComm-Replace-global-variable-bcom-by-b.patch
> 0016-powerpc-Make-the-BestComm-driver-a-standard-of_plat.patch
> 0017-powerpc-Fix-typo-in-BestComm-ATA-task-support-code.patch
> 0018-powerpc-BestComm-ATA-task-microcode-insert-copyri.patch
> 0019-powerpc-BestComm-FEC-task-microcode-insert-copyri.patch
> 0020-powerpc-BestComm-GenBD-task-microcode-insert-copy.patch
> 0021-powerpc-Fix-errors-in-bcom-bcom_eng-renaming.patch
>
>
>
> --
> Jon Smirl
> jonsmirl@gmail.com
>
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24
  2007-09-18  4:29   ` tnt
@ 2007-09-18 14:11     ` Kumar Gala
  0 siblings, 0 replies; 15+ messages in thread
From: Kumar Gala @ 2007-09-18 14:11 UTC (permalink / raw)
  To: tnt, Sylvain Munaut; +Cc: PowerPC dev list


On Sep 17, 2007, at 11:29 PM, tnt@blacksnow.net wrote:

>> On 9/16/07, Sylvain Munaut <tnt@246tnt.com> wrote:
>>> Hello Paul, Hi everyone,
>>>
>>> This series of patch is mainly the bestcomm support for
>>> the mpc5200. It was posted a while ago and received some
>>> comments. Theses are all addressed here (afaik).
>>
>> Does this series supersede these pacthes out of your older series?
>
> Yes.
> Those are the patches I wrote to fix the comments received last time.
> They are now merged inside the main patches.
>
> Apparently I forgot to fix some other comments so I'll have to do
> that and repost again.
>

One of the big things I'd like to see for the core bestcomm lib is  
proper kernel doc support for the APIs.  I think we should be going  
more of this for things like QE and will push on the guys doing  
working there to better document the 'library' APIs.

Also, I remember you wrote up some documentation/email about what the  
APIs did.  Is that in a clean enough state to add do Documentation/ 
powerpc/?

- k

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2007-09-18 14:08 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-16 10:53 [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Sylvain Munaut
2007-09-16 10:53 ` [PATCH 1/7] powerpc: exports rheap symbol to modules Sylvain Munaut
2007-09-16 10:53 ` [PATCH 2/7] powerpc: Changes the config mechanism for rheap Sylvain Munaut
2007-09-16 15:59   ` Kumar Gala
2007-09-16 10:53 ` [PATCH 3/7] powerpc/ppc32: Update mpc52xx_psc structure with B revision changes Sylvain Munaut
2007-09-16 10:53 ` [PATCH 4/7] powerpc: BestComm core support for Freescale MPC5200 Sylvain Munaut
2007-09-16 12:31   ` Stephen Rothwell
2007-09-16 16:07   ` Kumar Gala
2007-09-17  8:57   ` Matt Sealey
2007-09-16 10:53 ` [PATCH 5/7] powerpc: BestComm ATA task support Sylvain Munaut
2007-09-16 10:53 ` [PATCH 6/7] powerpc: BestComm FEC " Sylvain Munaut
2007-09-16 10:53 ` [PATCH 7/7] powerpc: BestComm GenBD " Sylvain Munaut
2007-09-18  2:15 ` [PATCH 0/7] MPC52xx Bestcomm submission for 2.6.24 Jon Smirl
2007-09-18  4:29   ` tnt
2007-09-18 14:11     ` Kumar Gala

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).