LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/5] Add Freescale DMA engine driver maintainer.
From: Zhang Wei @ 2007-09-07 10:53 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <1189162437484-git-send-email-wei.zhang@freescale.com>

This patch adds Freescale DMA engine driver maintainer.

Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
---
 MAINTAINERS |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 01f222e..1be4f23 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1527,6 +1527,13 @@ L:	linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 W:	http://linux-fbdev.sourceforge.net/
 S:	Maintained
 
+FREESCALE DMA DRIVER
+P;	Zhang Wei
+M:	wei.zhang@freescale.com
+L:	linuxppc-embedded@ozlabs.org
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+
 FREESCALE SOC FS_ENET DRIVER
 P:	Pantelis Antoniou
 M:	pantelis.antoniou@gmail.com
-- 
1.5.2

^ permalink raw reply related

* [PATCH 3/5] Add DMA of-node to mpc8641hpcn board dts
From: Zhang Wei @ 2007-09-07 10:53 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <11891624382764-git-send-email-wei.zhang@freescale.com>

This patch adds DMA of-node to MPC8641HPCN board dts.

Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
Signed-off-by: Ebony Zhu <ebony.zhu@freescale.com>
---
 arch/powerpc/boot/dts/mpc8641_hpcn.dts |   40 ++++++++++++++++++++++++++++++++
 1 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
index 5d82709..e0175a4 100644
--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
@@ -433,5 +433,45 @@
 			device_type = "open-pic";
 			big-endian;
 		};
+
+		dma@21000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,dma";
+			reg = <21300 4>;
+			ranges = <0 21100 200>;
+			dma-channel@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "fsl,mpc8540-dma-channel";
+				reg = <0 80>;
+				interrupt-parent = <&mpic>;
+				interrupts = <14 2>;
+			};
+			dma-channel@80 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "fsl,mpc8540-dma-channel";
+				reg = <80 80>;
+				interrupt-parent = <&mpic>;
+				interrupts = <15 2>;
+			};
+			dma-channel@100 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "fsl,mpc8540-dma-channel";
+				reg = <100 80>;
+				interrupt-parent = <&mpic>;
+				interrupts = <16 2>;
+			};
+			dma-channel@180 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "fsl,mpc8540-dma-channel";
+				reg = <180 80>;
+				interrupt-parent = <&mpic>;
+				interrupts = <17 2>;
+			};
+		};
 	};
 };
-- 
1.5.2

^ permalink raw reply related

* [PATCH 4/5] Add of-device and DMA bus support to MPC8641HPCN board.
From: Zhang Wei @ 2007-09-07 10:53 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <11891624391565-git-send-email-wei.zhang@freescale.com>

This patch adds of-device and DMA device bus support
to MPC8641HPCN board.

Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
---
 arch/powerpc/platforms/86xx/mpc86xx_hpcn.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index e9eaa07..e141259 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -18,6 +18,7 @@
 #include <linux/kdev_t.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
+#include <linux/of_platform.h>
 
 #include <asm/system.h>
 #include <asm/time.h>
@@ -444,3 +445,19 @@ define_machine(mpc86xx_hpcn) {
 	.progress		= udbg_progress,
 	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
 };
+
+static struct of_device_id mpc86xx_of_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "fsl,dma", },
+	{},
+};
+
+static __init int mpc86xx_of_device_init(void)
+{
+	if (!machine_is(mpc86xx_hpcn))
+		return 0;
+
+	return of_platform_bus_probe(NULL, mpc86xx_of_ids, NULL);
+}
+
+device_initcall(mpc86xx_of_device_init);
-- 
1.5.2

^ permalink raw reply related

* [PATCH 5/5] Add DMA engine driver for Freescale MPC85xx processors.
From: Zhang Wei @ 2007-09-07 10:54 UTC (permalink / raw)
  To: paulus, shannon.nelson; +Cc: linuxppc-dev, linux-kernel

The driver implements DMA engine API for Freescale MPC85xx DMA
controller, which could be used for MEM<-->MEM, IO_ADDR<-->MEM
and IO_ADDR<-->IO_ADDR data transfer.
The driver supports the Basic mode of Freescale MPC85xx DMA controller.
The MPC85xx processors supported include MPC8540/60, MPC8555, MPC8548,
MPC8641 and so on.
The support for MPC83xx(MPC8349, MPC8360) is experimental.

Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
Signed-off-by: Ebony Zhu <ebony.zhu@freescale.com>
---
 drivers/dma/Kconfig  |    8 +
 drivers/dma/Makefile |    1 +
 drivers/dma/fsldma.c |  995 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/dma/fsldma.h |  188 ++++++++++
 4 files changed, 1192 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dma/fsldma.c
 create mode 100644 drivers/dma/fsldma.h

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 8f670da..a99e925 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -40,4 +40,12 @@ config INTEL_IOP_ADMA
         ---help---
           Enable support for the Intel(R) IOP Series RAID engines.
 
+config FSL_DMA
+	bool "Freescale MPC85xx/MPC83xx DMA support"
+	depends on DMA_ENGINE && PPC
+	---help---
+	  Enable support for the Freescale DMA engine. Now, it support
+	  MPC8560/40, MPC8555, MPC8548 and MPC8641 processors.
+	  The MPC8349, MPC8360 support is experimental.
+
 endmenu
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index b3839b6..50ab26c 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
 obj-$(CONFIG_NET_DMA) += iovlock.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
+obj-$(CONFIG_FSL_DMA) += fsldma.o
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
new file mode 100644
index 0000000..9e2d56b
--- /dev/null
+++ b/drivers/dma/fsldma.c
@@ -0,0 +1,995 @@
+/*
+ * Freescale MPC85xx, MPC83xx DMA Engine support
+ *
+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author:
+ *   Zhang Wei <wei.zhang@freescale.com>, Jul 2007
+ *   Ebony Zhu <ebony.zhu@freescale.com>, May 2007
+ *
+ * Description:
+ *   DMA engine driver for Freescale MPC8540 DMA controller, which is
+ *   also fit for MPC8560, MPC8555, MPC8548, MPC8641, and etc.
+ *   The support for MPC8349 DMA contorller is also added. But it's
+ *   ONLY experimental for MPC8349 now.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/dmaengine.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/of_platform.h>
+
+#include "fsldma.h"
+
+static LIST_HEAD(recy_ln_chain);	/* ld chain for recycle */
+static spinlock_t recy_ln_lock = SPIN_LOCK_UNLOCKED;
+
+static void dma_do_tasklet(unsigned long unused);
+static DECLARE_TASKLET(dma_tasklet, dma_do_tasklet, 0);
+
+#define to_fsl_chan(chan) container_of(chan, struct fsl_dma_chan, common)
+#define to_fsl_desc(lh) container_of(lh, struct fsl_desc_sw, node)
+#define tx_to_fsl_desc(tx) container_of(tx, struct fsl_desc_sw, async_tx)
+
+static void dma_init(struct fsl_dma_chan *fsl_chan)
+{
+	/* Reset the channel */
+	MIX_OUT(fsl_chan, &fsl_chan->reg_base->mr, 0, 32);
+
+	switch (fsl_chan->feature & FSL_DMA_IP_MASK) {
+	case FSL_DMA_IP_86XX:
+		/* Set the channel to below modes:
+		 * EIE - Error interrupt enable
+		 * EOSIE - End of segments interrupt enable (basic mode)
+		 * EOLNIE - End of links interrupt enable
+		 */
+		MIX_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EIE
+				| FSL_DMA_MR_EOLNIE | FSL_DMA_MR_EOSIE, 32);
+		break;
+	case FSL_DMA_IP_83XX:
+		/* Set the channel to below modes:
+		 * EOTIE - End-of-transfer interrupt enable
+		 */
+		MIX_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EOTIE,
+				32);
+		break;
+	}
+
+}
+
+static void set_sr(struct fsl_dma_chan *fsl_chan, dma_addr_t val)
+{
+	MIX_OUT(fsl_chan, &fsl_chan->reg_base->sr, val, 32);
+}
+
+static dma_addr_t get_sr(struct fsl_dma_chan *fsl_chan)
+{
+	return MIX_IN(fsl_chan, &fsl_chan->reg_base->sr, 32);
+}
+
+static void get_desc(struct fsl_dma_chan *fsl_chan, struct fsl_dma_ld_hw *hw,
+			struct fsl_ld_desc *ld)
+{
+	BUG_ON(!hw);
+
+	ld->src = MIX_TO_CPU(fsl_chan, hw->src_addr, 64);
+	ld->dest = MIX_TO_CPU(fsl_chan, hw->dst_addr, 64);
+	ld->count = MIX_TO_CPU(fsl_chan, hw->count, 32);
+	ld->next_ld_desc = MIX_TO_CPU(fsl_chan, hw->next_ln_addr, 64);
+
+	switch (fsl_chan->feature & FSL_DMA_IP_MASK) {
+	case FSL_DMA_IP_86XX:
+		ld->src &= (dma_addr_t)0x0000ffffffffffffull;
+		ld->dest &= (dma_addr_t)0x0000ffffffffffffull;
+		break;
+	case FSL_DMA_IP_83XX:
+		ld->next_ld_desc &= ~FSL_DMA_SNEN;
+		break;
+	}
+}
+
+static void set_desc(struct fsl_dma_chan *fsl_chan, struct fsl_dma_ld_hw *hw,
+			struct fsl_ld_desc *ld)
+{
+	hw->src_addr = (__mix64)CPU_TO_MIX(fsl_chan, ld->src, 64);
+	hw->dst_addr = (__mix64)CPU_TO_MIX(fsl_chan, ld->dest, 64);
+	hw->count = (__mix32)CPU_TO_MIX(fsl_chan, ld->count, 32);
+	hw->next_ln_addr = (__mix64)CPU_TO_MIX(fsl_chan, ld->next_ld_desc, 64);
+
+	switch (fsl_chan->feature & FSL_DMA_IP_MASK) {
+	case FSL_DMA_IP_86XX:
+		hw->src_addr.be |= CPU_TO_MIX(fsl_chan,
+					(u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ
+					<< 32, 64);
+		hw->dst_addr.be |= CPU_TO_MIX(fsl_chan,
+					(u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE
+					<< 32, 64);
+		break;
+	case FSL_DMA_IP_83XX:
+		hw->next_ln_addr.le |= CPU_TO_MIX(fsl_chan, FSL_DMA_SNEN, 64);
+		break;
+	}
+}
+
+static void set_cdar(struct fsl_dma_chan *fsl_chan, dma_addr_t addr)
+{
+	MIX_OUT(fsl_chan, &fsl_chan->reg_base->cdar, addr | FSL_DMA_SNEN, 64);
+}
+
+static dma_addr_t get_cdar(struct fsl_dma_chan *fsl_chan)
+{
+	return MIX_IN(fsl_chan, &fsl_chan->reg_base->cdar, 64) & ~FSL_DMA_SNEN;
+}
+
+static void set_ndar(struct fsl_dma_chan *fsl_chan, dma_addr_t addr)
+{
+	MIX_OUT(fsl_chan, &fsl_chan->reg_base->ndar, addr, 64);
+}
+
+static dma_addr_t get_ndar(struct fsl_dma_chan *fsl_chan)
+{
+	return MIX_IN(fsl_chan, &fsl_chan->reg_base->ndar, 64);
+}
+
+static int dma_is_idle(struct fsl_dma_chan *fsl_chan)
+{
+	return (get_sr(fsl_chan) & FSL_DMA_SR_CB) == 0;
+}
+
+static void dma_start(struct fsl_dma_chan *fsl_chan)
+{
+	MIX_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+		MIX_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) | FSL_DMA_MR_CS,
+		32);
+}
+
+static void dma_halt(struct fsl_dma_chan *fsl_chan)
+{
+	MIX_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+		MIX_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) & ~FSL_DMA_MR_CS,
+		32);
+}
+
+static void set_ld_eol(struct fsl_dma_chan *fsl_chan,
+			struct fsl_desc_sw *desc)
+{
+	struct fsl_ld_desc ld;
+	get_desc(fsl_chan, &desc->hw, &ld);
+	ld.next_ld_desc |= FSL_DMA_EOL;
+	set_desc(fsl_chan, &desc->hw, &ld);
+}
+
+static void append_ld_queue(struct fsl_dma_chan *fsl_chan,
+		struct fsl_desc_sw *new_desc)
+{
+	struct fsl_ld_desc ld;
+	struct fsl_desc_sw *queue_tail = to_fsl_desc(fsl_chan->ld_queue.prev);
+
+	if (list_empty(&fsl_chan->ld_queue))
+		return;
+
+	get_desc(fsl_chan, &queue_tail->hw, &ld);
+	/* Link to the new descript physical address and
+	 * Enable End-of-segment interrupt for
+	 * the last link descriptor.
+	 * (the previous node's next link descriptor)
+	 */
+	ld.next_ld_desc = new_desc->async_tx.phys | FSL_DMA_EOSIE;
+	set_desc(fsl_chan, &queue_tail->hw, &ld);
+}
+
+static void fsl_dma_set_src(dma_addr_t addr,
+				struct dma_async_tx_descriptor *tx, int index)
+{
+	struct fsl_desc_sw *desc_node, *desc = tx_to_fsl_desc(tx);
+	struct fsl_dma_chan *fsl_chan = to_fsl_chan(tx->chan);
+
+	list_for_each_entry(desc_node, &desc->async_tx.tx_list, node) {
+		struct fsl_ld_desc ld;
+		get_desc(fsl_chan, &desc_node->hw, &ld);
+		ld.src = addr;
+		set_desc(fsl_chan, &desc_node->hw, &ld);
+		addr += FSL_DMA_BCR_MAX_CNT;
+	}
+}
+
+static void fsl_dma_set_dest(dma_addr_t addr,
+				struct dma_async_tx_descriptor *tx, int index)
+{
+	struct fsl_desc_sw *desc_node, *desc = tx_to_fsl_desc(tx);
+	struct fsl_dma_chan *fsl_chan = to_fsl_chan(tx->chan);
+
+	list_for_each_entry(desc_node, &desc->async_tx.tx_list, node) {
+		struct fsl_ld_desc ld;
+		get_desc(fsl_chan, &desc_node->hw, &ld);
+		ld.dest = addr;
+		set_desc(fsl_chan, &desc_node->hw, &ld);
+		addr += FSL_DMA_BCR_MAX_CNT;
+	}
+}
+
+static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
+	struct fsl_dma_chan *fsl_chan = to_fsl_chan(tx->chan);
+	unsigned long flags;
+	dma_cookie_t cookie;
+
+	/* cookie increment and adding to ld_queue must be atomic */
+	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+
+	cookie = fsl_chan->common.cookie;
+	cookie++;
+	if (cookie < 0)
+		cookie = 1;
+	desc->async_tx.cookie = cookie;
+	fsl_chan->common.cookie = desc->async_tx.cookie;
+
+	append_ld_queue(fsl_chan, desc);
+	list_splice_init(&desc->async_tx.tx_list, fsl_chan->ld_queue.prev);
+
+	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+
+	return cookie;
+}
+
+/**
+ * fsl_dma_alloc_descriptor - Allocate descriptor from channel's DMA pool.
+ *
+ * Return - The descriptor allocated. NULL for failed.
+ */
+static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
+					struct fsl_dma_chan *fsl_chan,
+					gfp_t flags)
+{
+	dma_addr_t pdesc;
+	struct fsl_desc_sw *desc_sw;
+
+	desc_sw = dma_pool_alloc(fsl_chan->desc_pool, flags, &pdesc);
+	if (desc_sw) {
+		memset(desc_sw, 0, sizeof(struct fsl_desc_sw));
+		dma_async_tx_descriptor_init(&desc_sw->async_tx,
+						&fsl_chan->common);
+		desc_sw->async_tx.tx_set_src = fsl_dma_set_src;
+		desc_sw->async_tx.tx_set_dest = fsl_dma_set_dest;
+		desc_sw->async_tx.tx_submit = fsl_dma_tx_submit;
+		INIT_LIST_HEAD(&desc_sw->async_tx.tx_list);
+		desc_sw->async_tx.phys = pdesc;
+	}
+
+	return desc_sw;
+}
+
+
+/**
+ * fsl_dma_alloc_chan_resources - Allocate resources for DMA channel.
+ *
+ * This function will create a dma pool for descriptor allocation.
+ *
+ * Return - The number of descriptors allocated.
+ */
+static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+	LIST_HEAD(tmp_list);
+
+	/* We need the descriptor to be aligned to 32bytes
+	 * for meeting FSL DMA specification requirement.
+	 */
+	fsl_chan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool",
+			fsl_chan->device->dev, sizeof(struct fsl_desc_sw),
+			32, 0);
+	if (!fsl_chan->desc_pool) {
+		dev_err(fsl_chan->device->dev, "No memory for channel %d "
+			"descriptor dma pool.\n", fsl_chan->id);
+		return 0;
+	}
+
+	return 1;
+}
+
+/**
+ * fsl_dma_free_chan_resources - Free all resources of the channel.
+ */
+static void fsl_dma_free_chan_resources(struct dma_chan *chan)
+{
+	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+	struct fsl_desc_sw *desc, *_desc;
+	unsigned long flags;
+
+	dev_dbg(fsl_chan->device->dev, "Free all channel resources.\n");
+	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+	list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) {
+#ifdef FSL_DMA_LD_DEBUG
+		dev_dbg(fsl_chan->device->dev,
+				"LD %p will be released.\n", desc);
+#endif
+		list_del(&desc->node);
+		/* free link descritpor */
+		dma_pool_free(fsl_chan->desc_pool, desc, desc->async_tx.phys);
+	}
+	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+	dma_pool_destroy(fsl_chan->desc_pool);
+}
+
+static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+				struct dma_chan *chan, size_t len, int int_en)
+{
+	struct fsl_dma_chan *fsl_chan;
+	struct fsl_desc_sw *first = NULL, *prev = NULL, *new;
+	size_t copy;
+	struct fsl_dma_device *fdev;
+	LIST_HEAD(link_chain);
+
+	if (!chan)
+		return NULL;
+
+	if (!len)
+		return NULL;
+
+	fsl_chan = to_fsl_chan(chan);
+	fdev = fsl_chan->device;
+
+	do {
+		struct fsl_ld_desc ld;
+
+		/* Allocate the link descriptor from DMA pool */
+		new = fsl_dma_alloc_descriptor(fsl_chan, GFP_ATOMIC);
+		if (!new) {
+			dev_err(fdev->dev,
+					"No free memory for link descriptor\n");
+			return NULL;
+		}
+#ifdef FSL_DMA_LD_DEBUG
+		dev_dbg(fdev->dev, "new link desc alloc %p\n", new);
+#endif
+
+		copy = min(len, FSL_DMA_BCR_MAX_CNT);
+
+		memset(&ld, 0, sizeof(struct fsl_ld_desc));
+		ld.count = copy;
+		set_desc(fsl_chan, &new->hw, &ld);
+
+		if (!first)
+			first = new;
+		else {
+			get_desc(fsl_chan, &prev->hw, &ld);
+			ld.next_ld_desc = new->async_tx.phys;
+			set_desc(fsl_chan, &prev->hw, &ld);
+		}
+
+		new->async_tx.cookie = 0;
+		new->async_tx.ack = 1;
+
+		prev = new;
+		len -= copy;
+
+		/* Insert the link descriptor to the LD ring */
+		list_add_tail(&new->node, &first->async_tx.tx_list);
+	} while (len);
+
+	new->async_tx.ack = 0; /* client is in control of this ack */
+	new->async_tx.cookie = -EBUSY;
+
+	/* Set End-of-link to the last link descriptor of new list*/
+	set_ld_eol(fsl_chan, new);
+
+	return first ? &first->async_tx : NULL;
+}
+
+/**
+ * fsl_dma_update_completed_cookie - Update the completed cookie.
+ */
+static void fsl_dma_update_completed_cookie(struct fsl_dma_chan *fsl_chan)
+{
+	struct fsl_desc_sw *cur_desc;
+	dma_addr_t ld_phy;
+
+	ld_phy = get_cdar(fsl_chan) & FSL_DMA_NLDA_MASK;
+
+	if (ld_phy) {
+		cur_desc = (struct fsl_desc_sw *)bus_to_virt(ld_phy);
+
+		if (cur_desc->async_tx.cookie) {
+			if (dma_is_idle(fsl_chan))
+				fsl_chan->completed_cookie =
+					cur_desc->async_tx.cookie;
+			else
+				fsl_chan->completed_cookie =
+					cur_desc->async_tx.cookie - 1;
+		}
+	}
+}
+
+/**
+ * fsl_chan_ld_cleanup -- Clean up link descriptors
+ *
+ * This function clean up the ld_queue of DMA channel.
+ * If 'in_intr' is set, the function will move the link descriptor to
+ * the recycle list. Otherwise, free it directly.
+ */
+static void fsl_chan_ld_cleanup(struct fsl_dma_chan *fsl_chan, int in_intr)
+{
+	struct fsl_desc_sw *desc, *_desc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+
+	fsl_dma_update_completed_cookie(fsl_chan);
+	dev_dbg(fsl_chan->device->dev,
+			"chan completed_cookie = %d\n",
+			fsl_chan->completed_cookie);
+	list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) {
+		if (DMA_IN_PROGRESS == dma_async_is_complete(
+					desc->async_tx.cookie,
+					fsl_chan->completed_cookie,
+					fsl_chan->common.cookie))
+			break;
+
+		/* Remove from ld_queue list */
+		list_del(&desc->node);
+
+		/* If this function is called by interrupt action,
+		 * we just move to recycle list.
+		 * Otherwise, we free it.
+		 */
+		if (in_intr)
+			list_add_tail(&desc->node, &recy_ln_chain);
+		else {
+			/* Run the link descriptor callback function */
+			if (desc->async_tx.callback) {
+				spin_unlock_irqrestore(&fsl_chan->desc_lock,
+								flags);
+				dev_dbg(fsl_chan->device->dev,
+					"link descriptor %p callback\n", desc);
+				desc->async_tx.callback(
+						desc->async_tx.callback_param);
+				spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+			}
+
+			dev_dbg(fsl_chan->device->dev,
+				"link descriptor %p will be recycle.\n", desc);
+			dma_pool_free(fsl_chan->desc_pool, desc,
+						desc->async_tx.phys);
+		}
+	}
+	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+}
+
+/**
+ * fsl_chan_xfer_ld_queue -- Transfer the link descriptors in channel
+ *                           ld_queue.
+ */
+static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan)
+{
+	struct list_head *ld_node;
+	dma_addr_t next_dest_addr;
+	unsigned long flags;
+
+	if (!dma_is_idle(fsl_chan))
+		return;
+
+	dma_halt(fsl_chan);
+
+	/* If there are some link descriptors
+	 * not transfered in queue. We need to start it.
+	 */
+	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+
+	/* Find the first un-transfer desciptor */
+	for (ld_node = fsl_chan->ld_queue.next;
+		(ld_node != &fsl_chan->ld_queue)
+			&& (DMA_SUCCESS == dma_async_is_complete(
+					to_fsl_desc(ld_node)->async_tx.cookie,
+					fsl_chan->completed_cookie,
+					fsl_chan->common.cookie));
+		ld_node = ld_node->next);
+
+	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+
+	if (ld_node != &fsl_chan->ld_queue) {
+		/* Get the ld start address from ld_queue */
+		next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys;
+		dev_dbg(fsl_chan->device->dev,
+			"xfer LDs staring from 0x%016llx\n",
+			(u64)next_dest_addr);
+		set_cdar(fsl_chan, next_dest_addr);
+		dma_start(fsl_chan);
+	} else {
+		set_cdar(fsl_chan, 0);
+		set_ndar(fsl_chan, 0);
+	}
+}
+
+/**
+ * fsl_dma_memcpy_issue_pending -- Issue the DMA start command
+ */
+static void fsl_dma_memcpy_issue_pending(struct dma_chan *chan)
+{
+	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+
+#ifdef FSL_DMA_LD_DEBUG
+	struct fsl_desc_sw *ld;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+	if (list_empty(&fsl_chan->ld_queue)) {
+		spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+		return;
+	}
+
+	dev_dbg(fsl_chan->device->dev, "--memcpy issue--\n");
+	list_for_each_entry(ld, &fsl_chan->ld_queue, node) {
+		int i;
+		dev_dbg(fsl_chan->device->dev, "Ch %d, LD %08x\n",
+				fsl_chan->id, ld->async_tx.phys);
+		for (i = 0; i < 8; i++)
+			dev_dbg(fsl_chan->device->dev,
+					"LD offset %d: %08x\n",
+					i, *(((u32 *)&ld->hw) + i));
+	}
+	dev_dbg(fsl_chan->device->dev, "----------------\n");
+	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+#endif
+
+	fsl_chan_xfer_ld_queue(fsl_chan);
+}
+
+static void fsl_dma_dependency_added(struct dma_chan *chan)
+{
+	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+
+	fsl_chan_ld_cleanup(fsl_chan, 0);
+}
+
+/**
+ * fsl_dma_is_complete -- Determine the DMA status
+ */
+static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
+					dma_cookie_t cookie,
+					dma_cookie_t *done,
+					dma_cookie_t *used)
+{
+	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+	dma_cookie_t last_used;
+	dma_cookie_t last_complete;
+
+	fsl_chan_ld_cleanup(fsl_chan, 0);
+
+	last_used = chan->cookie;
+	last_complete = fsl_chan->completed_cookie;
+
+	if (done)
+		*done = last_complete;
+
+	if (used)
+		*used = last_used;
+
+	return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+{
+	struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
+	dma_addr_t stat;
+
+	stat = get_sr(fsl_chan);
+	dev_dbg(fsl_chan->device->dev, "event: channel %d, stat = 0x%x\n",
+						fsl_chan->id, stat);
+	set_sr(fsl_chan, stat);		/* Clear the event register */
+
+	stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH);
+	if (!stat)
+		return IRQ_NONE;
+
+	/* If the link descriptor segment transfer finishes,
+	 * we will recycle the used descriptor.
+	 */
+	if (stat & FSL_DMA_SR_EOSI) {
+		dev_dbg(fsl_chan->device->dev, "event: End-of-segments INT\n");
+		dev_dbg(fsl_chan->device->dev, "event: clndar 0x%016llx, "
+				"nlndar 0x%016llx\n", (u64)get_cdar(fsl_chan),
+				(u64)get_ndar(fsl_chan));
+		stat &= ~FSL_DMA_SR_EOSI;
+		fsl_chan_ld_cleanup(fsl_chan, 1);
+	}
+
+	/* If it current transfer is the end-of-transfer,
+	 * we should clear the Channel Start bit for
+	 * prepare next transfer.
+	 */
+	if (stat & (FSL_DMA_SR_EOLNI | FSL_DMA_SR_EOCDI)) {
+		dev_dbg(fsl_chan->device->dev, "event: End-of-link INT\n");
+		stat &= ~FSL_DMA_SR_EOLNI;
+		fsl_chan_xfer_ld_queue(fsl_chan);
+	}
+
+	if (stat)
+		dev_dbg(fsl_chan->device->dev, "event: unhandled sr 0x%02x\n",
+					stat);
+
+	dev_dbg(fsl_chan->device->dev, "event: Exit\n");
+	tasklet_hi_schedule(&dma_tasklet);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t fsl_dma_do_interrupt(int irq, void *data)
+{
+	struct fsl_dma_device *fdev = (struct fsl_dma_device *)data;
+	struct fsl_dma_chan *fsl_chan = NULL;
+	u32 gsr;
+	int ch_nr;
+	struct dma_chan *int_chan;
+
+	gsr = (fdev->feature & FSL_DMA_BIG_ENDIAN) ? in_be32(fdev->reg_base)
+			: in_le32(fdev->reg_base);
+	ch_nr = (32 - ffs(gsr)) / 8;
+
+	list_for_each_entry(int_chan, &fdev->common.channels, device_node)
+		if (to_fsl_chan(int_chan)->id == ch_nr)
+			fsl_chan = to_fsl_chan(int_chan);
+
+	return fsl_chan ? fsl_dma_chan_do_interrupt(irq, fsl_chan) : IRQ_NONE;
+
+}
+
+static void dma_do_tasklet(unsigned long unused)
+{
+	struct fsl_desc_sw *desc, *_desc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&recy_ln_lock, flags);
+	list_for_each_entry_safe(desc, _desc, &recy_ln_chain, node) {
+		struct fsl_dma_chan *fsl_chan =
+					to_fsl_chan(desc->async_tx.chan);
+		/* Run the link descriptor callback function */
+		if (desc->async_tx.callback) {
+			spin_unlock_irqrestore(&recy_ln_lock, flags);
+			dev_dbg(fsl_chan->device->dev,
+				"dma_tasklet: link descriptor %p callback\n",
+				desc);
+			desc->async_tx.callback(
+					desc->async_tx.callback_param);
+			spin_lock_irqsave(&recy_ln_lock, flags);
+		}
+		/* Recycle it! */
+		list_del(&desc->node);
+		dev_dbg(fsl_chan->device->dev,
+			"dma_tasklet: link descriptor %p will be recycle.\n",
+			desc);
+		dma_pool_free(fsl_chan->desc_pool, desc,
+					desc->async_tx.phys);
+	}
+	spin_unlock_irqrestore(&recy_ln_lock, flags);
+}
+
+static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+{
+	struct dma_chan *chan;
+	int err = 0;
+	dma_addr_t addr;
+	dma_cookie_t cookie;
+	u8 *src, *dest;
+	int i;
+	size_t test_size;
+	struct dma_async_tx_descriptor *tx1, *tx2, *tx3;
+	struct fsl_dma_device *fdev;
+
+	BUG_ON(!fsl_chan);
+
+	fdev = fsl_chan->device;
+	test_size = 4096;
+
+	src = kmalloc(test_size * 2, GFP_KERNEL);
+	if (!src) {
+		dev_err(fdev->dev,
+				"selftest: Can not alloc memory for test!\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	dest = src + test_size;
+
+	for (i = 0; i < test_size; i++)
+		src[i] = (u8) i;
+
+	chan = &fsl_chan->common;
+
+	if (fsl_dma_alloc_chan_resources(chan) < 1) {
+		dev_err(fdev->dev,
+				"selftest: Can not alloc resources for DMA\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+	/* TX 1 */
+	tx1 = fsl_dma_prep_memcpy(chan, test_size / 2, 0);
+	async_tx_ack(tx1);
+	addr = dma_map_single(chan->device->dev, src, test_size / 2,
+							DMA_TO_DEVICE);
+	fsl_dma_set_src(addr, tx1, 0);
+	addr = dma_map_single(chan->device->dev, dest, test_size / 2,
+							DMA_FROM_DEVICE);
+	fsl_dma_set_dest(addr, tx1, 0);
+
+	cookie = fsl_dma_tx_submit(tx1);
+	fsl_dma_memcpy_issue_pending(chan);
+
+	while (fsl_dma_is_complete(chan, cookie, NULL, NULL)
+			!= DMA_SUCCESS);
+
+	/* Test free and re-alloc channel resources */
+	fsl_dma_free_chan_resources(chan);
+
+	if (fsl_dma_alloc_chan_resources(chan) < 1) {
+		dev_err(fdev->dev,
+				"selftest: Can not alloc resources for DMA\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+	/* Continue to test
+	 * TX 2
+	 */
+	tx2 = fsl_dma_prep_memcpy(chan, test_size / 4, 0);
+	async_tx_ack(tx2);
+	addr = dma_map_single(chan->device->dev, src + test_size / 2,
+					test_size / 4, DMA_TO_DEVICE);
+	fsl_dma_set_src(addr, tx2, 0);
+	addr = dma_map_single(chan->device->dev, dest + test_size / 2,
+					test_size / 4, DMA_FROM_DEVICE);
+	fsl_dma_set_dest(addr, tx2, 0);
+
+	/* TX 3 */
+	tx3 = fsl_dma_prep_memcpy(chan, test_size / 4, 0);
+	async_tx_ack(tx3);
+	addr = dma_map_single(chan->device->dev, src + test_size * 3 / 4,
+					test_size / 4, DMA_TO_DEVICE);
+	fsl_dma_set_src(addr, tx3, 0);
+	addr = dma_map_single(chan->device->dev, dest + test_size * 3 / 4,
+					test_size / 4, DMA_FROM_DEVICE);
+	fsl_dma_set_dest(addr, tx3, 0);
+
+	/* Test exchanging the prepared tx sort */
+	cookie = fsl_dma_tx_submit(tx3);
+	cookie = fsl_dma_tx_submit(tx2);
+
+	fsl_dma_memcpy_issue_pending(chan);
+	while (fsl_dma_is_complete(chan, cookie, NULL, NULL)
+			!= DMA_SUCCESS);
+	err = memcmp(src, dest, test_size);
+	if (err) {
+		for (i = 0; (*(src + i) == *(dest + i)) && (i < test_size);
+				i++);
+		dev_err(fdev->dev, "selftest: Test failed, data %d/%d is "
+				"error! src 0x%x, dest 0x%x\n",
+				i, test_size, *(src + i), *(dest + i));
+	}
+
+	fsl_dma_free_chan_resources(chan);
+
+out:
+	kfree(src);
+	return err;
+}
+
+static struct dma_chan *of_find_dma_chan_by_phandle(phandle phandle)
+{
+	struct device_node *np;
+	struct dma_chan *chan;
+	struct fsl_dma_device *fdev;
+
+	np = of_find_node_by_phandle(phandle);
+	if (!np || !of_device_is_compatible(np->parent, "fsl,dma"))
+		return NULL;
+
+	fdev = dev_get_drvdata(&of_find_device_by_node(np->parent)->dev);
+
+	list_for_each_entry(chan, &fdev->common.channels, device_node)
+		if (to_of_device(to_fsl_chan(chan)->chan_dev)->node == np)
+			return chan;
+	return NULL;
+}
+EXPORT_SYMBOL(of_find_dma_chan_by_phandle);
+
+static int __devinit of_fsl_dma_probe(struct of_device *dev,
+			const struct of_device_id *match)
+{
+	int err;
+	unsigned int irq;
+	struct fsl_dma_device *fdev;
+
+	fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL);
+	if (!fdev) {
+		dev_err(&dev->dev, "No enough memory for 'priv'\n");
+		err = -ENOMEM;
+		goto err;
+	}
+	fdev->dev = &dev->dev;
+	INIT_LIST_HEAD(&fdev->common.channels);
+
+	/* get DMA controller register base */
+	err = of_address_to_resource(dev->node, 0, &fdev->reg);
+	if (err) {
+		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
+				dev->node->full_name);
+		goto err;
+	}
+
+	dev_info(&dev->dev, "Probe the Freescale DMA driver for %s "
+			"controller at 0x%08x...\n",
+			match->compatible, fdev->reg.start);
+	fdev->reg_base = ioremap(fdev->reg.start, fdev->reg.end
+						- fdev->reg.start + 1);
+
+	dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask);
+	fdev->common.device_alloc_chan_resources = fsl_dma_alloc_chan_resources;
+	fdev->common.device_free_chan_resources = fsl_dma_free_chan_resources;
+	fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy;
+	fdev->common.device_is_tx_complete = fsl_dma_is_complete;
+	fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
+	fdev->common.device_dependency_added = fsl_dma_dependency_added;
+	fdev->common.dev = &dev->dev;
+
+	irq = irq_of_parse_and_map(dev->node, 0);
+	if (irq != NO_IRQ) {
+		err = request_irq(irq, &fsl_dma_do_interrupt, IRQF_SHARED,
+					"fsldma-device", fdev);
+		if (err) {
+			dev_err(&dev->dev, "DMA device request_irq error "
+				"with return %d\n", err);
+			goto err;
+		}
+	}
+
+	dev_set_drvdata(&(dev->dev), fdev);
+	dma_async_device_register(&fdev->common);
+	return 0;
+
+err:
+	iounmap(fdev->reg_base);
+	kfree(fdev);
+	return err;
+}
+
+static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
+			const struct of_device_id *match)
+{
+	struct fsl_dma_device *fdev;
+	struct fsl_dma_chan *new_fsl_chan;
+	int err;
+
+	fdev = dev_get_drvdata(dev->dev.parent);
+	BUG_ON(!fdev);
+
+	/* alloc channel */
+	new_fsl_chan = kzalloc(sizeof(struct fsl_dma_chan), GFP_KERNEL);
+	if (!new_fsl_chan) {
+		dev_err(&dev->dev, "No free memory for allocating "
+				"dma channels!\n");
+		err = -ENOMEM;
+		goto err;
+	}
+
+	/* get dma channel register base */
+	err = of_address_to_resource(dev->node, 0, &new_fsl_chan->reg);
+	if (err) {
+		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
+				dev->node->full_name);
+		goto err;
+	}
+
+	if (strcmp(match->compatible, "fsl,mpc8540-dma-channel") == 0)
+		new_fsl_chan->feature = FSL_DMA_IP_86XX | FSL_DMA_BIG_ENDIAN;
+	else if (strcmp(match->compatible, "fsl,mpc8349-dma-channel") == 0)
+		new_fsl_chan->feature = FSL_DMA_IP_83XX | FSL_DMA_LITTLE_ENDIAN;
+	else {
+		dev_err(&dev->dev, "No channel operations!\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	if (!fdev->feature)
+		fdev->feature = new_fsl_chan->feature;
+
+	/* If the DMA device's feature is different than its channels',
+	 * report the bug.
+	 */
+	BUG_ON(fdev->feature != new_fsl_chan->feature);
+
+	new_fsl_chan->device = fdev;
+	new_fsl_chan->chan_dev = &dev->dev;
+	new_fsl_chan->reg_base = ioremap(new_fsl_chan->reg.start,
+			new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1);
+
+	new_fsl_chan->id = ((new_fsl_chan->reg.start - 0x100) & 0xfff) >> 7;
+
+	/* Init the channel */
+	dma_init(new_fsl_chan);
+
+	/* Clear cdar registers */
+	set_cdar(new_fsl_chan, 0);
+
+	spin_lock_init(&new_fsl_chan->desc_lock);
+	INIT_LIST_HEAD(&new_fsl_chan->ld_queue);
+
+	new_fsl_chan->common.device = &fdev->common;
+
+	/* Add the channel to DMA device channel list */
+	list_add_tail(&new_fsl_chan->common.device_node,
+			&fdev->common.channels);
+	fdev->common.chancnt++;
+
+	new_fsl_chan->irq = irq_of_parse_and_map(dev->node, 0);
+	if (new_fsl_chan->irq != NO_IRQ) {
+		err = request_irq(new_fsl_chan->irq,
+					&fsl_dma_chan_do_interrupt, IRQF_SHARED,
+					"fsldma-channel", new_fsl_chan);
+		if (err) {
+			dev_err(&dev->dev, "DMA channel %s request_irq error "
+				"with return %d\n", dev->node->full_name, err);
+			goto err;
+		}
+	}
+
+	err = fsl_dma_self_test(new_fsl_chan);
+	if (err)
+		goto err;
+
+	dev_info(&dev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
+				match->compatible, new_fsl_chan->irq);
+
+	return 0;
+err:
+	dma_halt(new_fsl_chan);
+	iounmap(new_fsl_chan->reg_base);
+	free_irq(new_fsl_chan->irq, new_fsl_chan);
+	list_del(&new_fsl_chan->common.device_node);
+	kfree(new_fsl_chan);
+	return err;
+}
+
+static struct of_device_id of_fsl_dma_ids[] = {
+	{ .compatible = "fsl,dma", },
+};
+
+static struct of_platform_driver of_fsl_dma_driver = {
+	.name = "of-fsl-dma",
+	.match_table = of_fsl_dma_ids,
+	.probe = of_fsl_dma_probe,
+};
+
+static __init int of_fsl_dma_init(void)
+{
+	return of_register_platform_driver(&of_fsl_dma_driver);
+}
+
+static struct of_device_id of_fsl_dma_chan_ids[] = {
+	{ .compatible = "fsl,mpc8540-dma-channel", },
+	{ .compatible = "fsl,mpc8349-dma-channel", },
+};
+
+static struct of_platform_driver of_fsl_dma_chan_driver = {
+	.name = "of-fsl-dma-channel",
+	.match_table = of_fsl_dma_chan_ids,
+	.probe = of_fsl_dma_chan_probe,
+};
+
+static __init int of_fsl_dma_chan_init(void)
+{
+	return of_register_platform_driver(&of_fsl_dma_chan_driver);
+}
+
+subsys_initcall(of_fsl_dma_init);
+device_initcall(of_fsl_dma_chan_init);
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
new file mode 100644
index 0000000..05be9ed
--- /dev/null
+++ b/drivers/dma/fsldma.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author:
+ *   Zhang Wei <wei.zhang@freescale.com>, Jul 2007
+ *   Ebony Zhu <ebony.zhu@freescale.com>, May 2007
+ *
+ * Description:
+ *   This file defines data structures needed by Freescale
+ *   MPC8540 and MPC8349 DMA controller.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#ifndef __FSLDMA_H
+#define __FSLDMA_H
+
+#include <linux/device.h>
+#include <linux/dmapool.h>
+#include <linux/dmaengine.h>
+
+#define FSL_DMA_MR_CS		0x00000001
+#define FSL_DMA_MR_CC		0x00000002
+#define FSL_DMA_MR_EIE		0x00000040
+#define FSL_DMA_MR_XFE		0x00000020
+#define FSL_DMA_MR_EOLNIE	0x00000100
+#define FSL_DMA_MR_EOLSIE	0x00000080
+#define FSL_DMA_MR_EOSIE	0x00000200
+#define FSL_DMA_MR_CDSM		0x00000010
+#define FSL_DMA_MR_CTM		0x00000004
+
+/* Special MR definition for MPC8349 */
+#define FSL_DMA_MR_EOTIE	0x00000080
+
+#define FSL_DMA_SR_CH		0x00000020
+#define FSL_DMA_SR_CB		0x00000004
+#define FSL_DMA_SR_TE		0x00000080
+#define FSL_DMA_SR_EOSI		0x00000002
+#define FSL_DMA_SR_EOLSI	0x00000001
+#define FSL_DMA_SR_EOCDI	0x00000001
+#define FSL_DMA_SR_EOLNI	0x00000008
+
+#define FSL_DMA_SATR_SBPATMU			0x20000000
+#define FSL_DMA_SATR_STRANSINT_RIO		0x00c00000
+#define FSL_DMA_SATR_SREADTYPE_SNOOP_READ	0x00050000
+#define FSL_DMA_SATR_SREADTYPE_BP_IORH		0x00020000
+#define FSL_DMA_SATR_SREADTYPE_BP_NREAD		0x00040000
+#define FSL_DMA_SATR_SREADTYPE_BP_MREAD		0x00070000
+
+#define FSL_DMA_DATR_DBPATMU			0x20000000
+#define FSL_DMA_DATR_DTRANSINT_RIO		0x00c00000
+#define FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE	0x00050000
+#define FSL_DMA_DATR_DWRITETYPE_BP_FLUSH	0x00010000
+
+#define FSL_DMA_EOL		((u64)0x1)
+#define FSL_DMA_SNEN		((u64)0x10)
+#define FSL_DMA_EOSIE		0x8
+#define FSL_DMA_NLDA_MASK	(~(u64)0x1f)
+
+#define FSL_DMA_BCR_MAX_CNT	0x03ffffffu
+
+#define FSL_DMA_DGSR_TE		0x80
+#define FSL_DMA_DGSR_CH		0x20
+#define FSL_DMA_DGSR_PE		0x10
+#define FSL_DMA_DGSR_EOLNI	0x08
+#define FSL_DMA_DGSR_CB		0x04
+#define FSL_DMA_DGSR_EOSI	0x02
+#define FSL_DMA_DGSR_EOLSI	0x01
+
+
+typedef union mix32 {
+	__le32	le;
+	__be32	be;
+} __mix32;
+
+typedef union mix64 {
+	__le64	le;
+	__be64	be;
+} __mix64;
+
+struct fsl_dma_ld_hw {
+	__mix64	src_addr;
+	__mix64	dst_addr;
+	__mix64	next_ln_addr;
+	__mix32	count;
+	__mix32	reserve;
+} __attribute__((aligned(32)));
+
+struct fsl_ld_desc {
+	dma_addr_t dest;
+	dma_addr_t src;
+	u32 count;
+	dma_addr_t next_ld_desc;
+};
+
+struct fsl_desc_sw {
+	struct fsl_dma_ld_hw hw;
+	struct list_head node;
+	struct dma_async_tx_descriptor async_tx;
+	struct list_head *ld;
+	void *priv;
+} __attribute__((aligned(32)));
+
+struct fsl_dma_chan_regs {
+	__mix32	mr;		/* 0x00 - Mode Register */
+	__mix32	sr;		/* 0x04 - Status Register */
+	__mix64	cdar;		/* 0x08 - Cureent descriptor address register */
+	__mix64	sar;		/* 0x10 - Source Address Register */
+	__mix64	dar;		/* 0x18 - Destination Address Register */
+	__mix32	bcr;		/* 0x20 - Byte Count Register */
+	__mix64	ndar;		/* 0x24 - Next Descriptor Address Register */
+};
+
+struct fsl_dma_device {
+	void __iomem *reg_base;		/* DGSR register base */
+	struct resource reg;		/* Resource for register */
+	struct device *dev;
+	struct dma_device common;
+	u32 feature;			/* The same as DMA channels */
+};
+
+/* Define macros for fsl_dma_chan->feature property */
+#define FSL_DMA_LITTLE_ENDIAN	0x00000000
+#define FSL_DMA_BIG_ENDIAN	0x00000001
+
+#define FSL_DMA_IP_MASK		0x00000ff0
+#define FSL_DMA_IP_86XX		0x00000010
+#define FSL_DMA_IP_83XX		0x00000020
+
+struct fsl_dma_chan {
+	struct fsl_dma_chan_regs __iomem *reg_base;
+	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
+	spinlock_t desc_lock;
+	struct list_head ld_queue;	/* Link descriptors queue */
+	struct fsl_dma_device *device;
+	struct dma_chan common;
+	struct dma_pool *desc_pool;
+	struct device *chan_dev;
+	struct resource reg;		/* Resource for register */
+	int irq;
+	int id;				/* Raw id of this channel */
+	u32 feature;
+};
+
+#ifndef __powerpc64
+static u64 in_be64(const u64 __iomem *addr)
+{
+	return ((u64)in_be32((u32 *)addr) << 32) | (in_be32((u32 *)addr + 1));
+}
+
+static void out_be64(u64 __iomem *addr, u64 val)
+{
+	out_be32((u32 *)addr, val >> 32);
+	out_be32((u32 *)addr + 1, (u32)val);
+}
+
+/* There is no asm instructions for 64 bits reverse loads and stores */
+static u64 in_le64(const u64 __iomem *addr)
+{
+	return le64_to_cpu(in_be64(addr));
+}
+
+static void out_le64(u64 __iomem *addr, u64 val)
+{
+	out_be64(addr, cpu_to_le64(val));
+}
+#endif
+
+#define MIX_IN(fsl_chan, addr, width)					\
+		(((fsl_chan)->feature & FSL_DMA_BIG_ENDIAN) ?		\
+			in_be##width(&(addr)->be) : in_le##width(&(addr)->le))
+#define MIX_OUT(fsl_chan, addr, val, width)				\
+		(((fsl_chan)->feature & FSL_DMA_BIG_ENDIAN) ?		\
+			out_be##width(&(addr)->be, val) :		\
+			out_le##width(&(addr)->le, val))
+
+#define MIX_TO_CPU(fsl_chan, mix, width)				\
+		(((fsl_chan)->feature & FSL_DMA_BIG_ENDIAN) ?		\
+			be##width##_to_cpu((mix).be) :			\
+			le##width##_to_cpu((mix).le))
+#define CPU_TO_MIX(fsl_chan, mix, width)				\
+		(((fsl_chan)->feature & FSL_DMA_BIG_ENDIAN) ?		\
+			cpu_to_be##width(mix) : cpu_to_le##width(mix))
+
+#endif	/* __FSLDMA_H */
-- 
1.5.2

^ permalink raw reply related

* random panic and freezes on mpc8349 itx
From: Nicolas Schichan @ 2007-09-07 12:05 UTC (permalink / raw)
  To: linuxppc-embedded


Hi,

I am currently working with an MPC8349ITX board and I have some trouble with 
the kernel as soon as it reaches userland.

If I boot the kernel with all the memory (256MB) available (no mem=... on the 
command line), I get random freezes or random kernel panics. Some times it 
won't even run init. Some times it will panic badly if I try to put some 
pressure to the system (stress --cpu 256). Some times it will hang 
immediately after logging in, ...

If I boot the kernel with mem=64M, these freeze and random panic disapear and 
I am able to run the stress program without any problems.

I have had this strange behaviour on both kernel 2.6.20 and 2.6.22 with 
mpc834x_itx_defconfig (both from kernel.org) (ARCH=powerpc).

I am inclined to say that it is not a broken RAM chip problem because if I use 
a 2.6.17 from kernel.org with all the RAM available (ARCH=ppc) configured 
with mpc834x_sys_defconfig (there was no defconfig for the itx board on this 
version) everything runs fine and I am able to run the stress program without 
any problems.

The panic does not happen very often, 90% of the time, the board hangs and 
stops responding to ping. When a panic do happen it is almost always in a 
different place.

Does any of you have met this problem before ? If you have any clues about 
what is hapenning I'd be glad to hear about it :)

Thank you for your attention,

Regards,

-- 
Nicolas Schichan

^ permalink raw reply

* Re: random panic and freezes on mpc8349 itx
From: Clemens Koller @ 2007-09-07 12:24 UTC (permalink / raw)
  To: Nicolas Schichan; +Cc: linuxppc-embedded
In-Reply-To: <200709071405.06500.nschichan@freebox.fr>

Hi, Nicolas!

Nicolas Schichan schrieb:
> Hi,
> 
> I am currently working with an MPC8349ITX board and I have some trouble with 
> the kernel as soon as it reaches userland.
> 
> If I boot the kernel with all the memory (256MB) available (no mem=... on the 
> command line), I get random freezes or random kernel panics. Some times it 
> won't even run init. Some times it will panic badly if I try to put some 
> pressure to the system (stress --cpu 256). Some times it will hang 
> immediately after logging in, ...

Just some ideas how I prefer to roughly track down random crashes:

Check if the problems dependend of supply voltages, grounding or temperature.
Mounting a prototype to an aluminum board improved uptime a lot in one case.
If you don't see any variations at all, I would guess it's a problem caused
by software.

> If I boot the kernel with mem=64M, these freeze and random panic disapear and 
> I am able to run the stress program without any problems.
> 
> I have had this strange behaviour on both kernel 2.6.20 and 2.6.22 with 
> mpc834x_itx_defconfig (both from kernel.org) (ARCH=powerpc).
> 
> I am inclined to say that it is not a broken RAM chip problem because if I use 
> a 2.6.17 from kernel.org with all the RAM available (ARCH=ppc) configured 
> with mpc834x_sys_defconfig (there was no defconfig for the itx board on this 
> version) everything runs fine and I am able to run the stress program without 
> any problems.

Hmm... check the cpu/memory timing manually (by dumping some registers) and compare.
The two ARCHitectures might do things quite different in the meanwhile.
Otherwise, if you can stay within one ARCH, git bisect might be your friend here.

Regards,
-- 
Clemens Koller
__________________________________
R&D Imaging Devices
Anagramm GmbH
Rupert-Mayer-Straße 45/1
Linhof Werksgelände
D-81379 München
Tel.089-741518-50
Fax 089-741518-19
http://www.anagramm-technology.com

^ permalink raw reply

* Please pull from 'for-2.6.24' branch of 4xx tree
From: Josh Boyer @ 2007-09-07 13:16 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

Hi Paul,

Please do

git pull \
git://git.infradead.org/users/jwboyer/powerpc.git for-2.6.24

It contains the latest 4xx patches for 2.6.24.  Support for 440EPx and
405GP boards are added, a bugfix for 440EP, and a small cleanup of some
DTS files.

josh

 arch/powerpc/boot/4xx.c                |  108 +++++
 arch/powerpc/boot/4xx.h                |    1 +
 arch/powerpc/boot/Makefile             |    5 +-
 arch/powerpc/boot/cuboot-sequoia.c     |   56 +++
 arch/powerpc/boot/dcr.h                |    5 +
 arch/powerpc/boot/dts/ebony.dts        |    4 -
 arch/powerpc/boot/dts/holly.dts        |    4 -
 arch/powerpc/boot/dts/kuroboxHD.dts    |    3 -
 arch/powerpc/boot/dts/kuroboxHG.dts    |    3 -
 arch/powerpc/boot/dts/prpmc2800.dts    |    4 -
 arch/powerpc/boot/dts/sequoia.dts      |  286 ++++++++++++
 arch/powerpc/boot/dts/walnut.dts       |  183 ++++++++
 arch/powerpc/boot/treeboot-walnut.c    |  131 ++++++
 arch/powerpc/configs/sequoia_defconfig |  776 ++++++++++++++++++++++++++++++++
 arch/powerpc/configs/walnut_defconfig  |  773 +++++++++++++++++++++++++++++++
 arch/powerpc/kernel/cputable.c         |   18 +
 arch/powerpc/kernel/head_44x.S         |    2 +-
 arch/powerpc/platforms/40x/Kconfig     |   14 +-
 arch/powerpc/platforms/40x/Makefile    |    2 +-
 arch/powerpc/platforms/40x/walnut.c    |   68 +++
 arch/powerpc/platforms/44x/Kconfig     |   17 +-
 arch/powerpc/platforms/44x/Makefile    |    1 +
 arch/powerpc/platforms/44x/bamboo.c    |    2 +-
 arch/powerpc/platforms/44x/sequoia.c   |   66 +++
 arch/powerpc/platforms/Kconfig         |    2 +-
 arch/powerpc/platforms/Makefile        |    2 +-
 26 files changed, 2504 insertions(+), 32 deletions(-)
 create mode 100644 arch/powerpc/boot/cuboot-sequoia.c
 create mode 100644 arch/powerpc/boot/dts/sequoia.dts
 create mode 100644 arch/powerpc/boot/dts/walnut.dts
 create mode 100644 arch/powerpc/boot/treeboot-walnut.c
 create mode 100644 arch/powerpc/configs/sequoia_defconfig
 create mode 100644 arch/powerpc/configs/walnut_defconfig
 create mode 100644 arch/powerpc/platforms/40x/walnut.c
 create mode 100644 arch/powerpc/platforms/44x/sequoia.c

Josh Boyer (6):
      [POWERPC] Remove dtc build cruft from DTS files
      [POWERPC] Fix bus probe on Bamboo board
      [POWERPC] Walnut DTS
      [POWERPC] Walnut defconfig
      [POWERPC] Walnut board support
      [POWERPC] Walnut zImage wrapper

Valentine Barshak (4):
      [POWERPC] PowerPC 440EPx: Sequoia device tree
      [POWERPC] PowerPC 440EPx: Sequoia defconfig
      [POWERPC] PowerPC 440EPx: Sequoia board support
      [POWERPC] PowerPC 440EPx: Sequoia bootwrapper

^ permalink raw reply

* Re: dtc: Assume properties preced subnodes in the flattened tree
From: Jon Loeliger @ 2007-09-07 13:41 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev
In-Reply-To: <20070904004303.GC20549@localhost.localdomain>

So, like, the other day David Gibson mumbled:
> With kernel commit eff2ebd207af9f501af0ef667a7d14befcb36c1b, we
> clarified that in the flattened tree format, a particular nodes
> properties are required to precede its subdnodes.
> 
> At present however, both dtc and libfdt will process trees which don't
> meet this condition.  This patch simplifies the code for
> fdt_get_property() based on assuming that constraint.  dtc continues
> to be able to handle such an invalid tree - on the grounds that it's
> useful for dtc to be able to correct such a broken tree - but this
> patch adds a warning when this condition is not met while reading a
> flattened tree.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>


Applied.

Thanks,
jdl

^ permalink raw reply

* Re: Document and implement an improved flash device binding
From: Segher Boessenkool @ 2007-09-07 13:58 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev
In-Reply-To: <20070907010449.GL26079@localhost.localdomain>

>>>> Let's have bank-width optional instead, it's more natural
>>>> that way for the common case of just one chip.  Or, you can
>>>> say that either is optional.
>>>
>>> No, I'm disinclined to do that since bank-width is the primary bit of
>>> information that the driver needs.
>>
>> Bzzzzt.  That's not what the device tree is about; it should
>> describe the hardware, it shouldn't be just a config file for
>> the current Linux drivers.
>
> Yes, yes, so you've said many times.

Glad you noticed :-)

> But where there are multiple ways of encoding exactly the same
> information, I don't see that we can't use driver convenience as a
> deciding factor.

But a driver that supports interleaving needs _both_ those pieces
of information, and a driver that doesn't needs the device-width
only.

Sure, the current MTD driver will use some heuristics to guess
the device width, but an interface via which it can get it from
the device tree will have to be added anyway.


Segher

^ permalink raw reply

* Re: [RFC/PATCH 2/2] Generic clockevents and no-idle-HZ for PowerPC
From: Johannes Berg @ 2007-09-07 14:04 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18144.4702.673658.336384@cargo.ozlabs.ibm.com>

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

On Fri, 2007-09-07 at 00:44 +1000, Paul Mackerras wrote:
> This creates a clockevent for the PowerPC decrementer and registers it
> with the generic clock/timer system, and implements the dynamic ticks
> (no idle HZ) option for PowerPC.

I tried both patches applied and with/without CONFIG_NOHZ but my quad G5
won't boot. Anybody else have more luck?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply

* Re: [PATCH v2] powerpc: Add workaround for MPICs with broken register reads
From: Milton Miller @ 2007-09-07 14:11 UTC (permalink / raw)
  To: Olof Johansson; +Cc: paulus, linuxppc-dev
In-Reply-To: <20070907092143.GB32102@lixom.net>


On Sep 7, 2007, at 4:21 AM, Olof Johansson wrote:

> Some versions of PWRficient 1682M have an interrupt controller in which
> the first register in each pair for interrupt sources doesn't always
> read with the right polarity/sense values.
>
> To work around this, keep a software copy of the register instead. 
> Since
> it's not modified from the mpic itself, it's a feasible solution. 
> Still,
> keep it under a config option to avoid wasting memory on other 
> platforms.
>
> Signed-off-by: Olof Johansson <olof@lixom.net>
>
>
> diff --git a/arch/powerpc/platforms/Kconfig 
> b/arch/powerpc/platforms/Kconfig
> index 041df77..f2e7049 100644
> --- a/arch/powerpc/platforms/Kconfig
> +++ b/arch/powerpc/platforms/Kconfig
> @@ -137,6 +137,18 @@ config MPIC_U3_HT_IRQS
>  	depends on PPC_MAPLE
>  	default y
>
> +config MPIC_BROKEN_REGREAD
> +	bool "MPIC workaround for broken register reads"
> +	depends on MPIC
> +	help
> +	  Say Y here to enable a MPIC driver workaround for some chips that
> +	  have a bug that causes some interrupt source information to not
> +	  read back properly. It is safe to use on other chips as well, but
> +	  enabling it uses about 8KB of memory to keep copies of the register
> +	  contents in software.
> +
> +	  Say N if you are unsure.
> +
>

I'm sorry, I didn't mean to imply it should be asked / selectable, just 
that the help should be provided.   I won't object to leaving it except 
that it asks the average user unnecessary questions.   In other words, 
drop the question after bool.

milton

^ permalink raw reply

* Re: [PATCH 06/10] bootwrapper: Move strncmp() from flatdevtree_env.h to string.S/string.h.
From: Scott Wood @ 2007-09-07 14:24 UTC (permalink / raw)
  To: galak, linuxppc-dev
In-Reply-To: <20070907005131.GF26079@localhost.localdomain>

On Fri, Sep 07, 2007 at 10:51:31AM +1000, David Gibson wrote:
> On Wed, Sep 05, 2007 at 02:21:14PM -0500, Scott Wood wrote:
> > It will be needed for PlanetCore firmware support.
> > 
> > Signed-off-by: Scott Wood <scottwood@freescale.com>
> 
> I still have a patch that already does this, plus strchr() as well,
> pending...

Sure, and I noted last time that this patch should be dropped if yours is
merged.  I kept it in the patchset because it's needed to make later
patches build and work.

-Scott

^ permalink raw reply

* Re: Document and implement an improved flash device binding for powerpc (v5)
From: Segher Boessenkool @ 2007-09-07 14:25 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20070907032353.GA3082@localhost.localdomain>

> This patch replaces the binding for flash chips in
> booting-without-of.txt with an clarified and improved version.  It
> also makes drivers/mtd/maps/physmap_of.c recognize this new binding.
> Finally it revises the Ebony device tree source to use the new binding
> as an example.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

Acked-by: Segher Boessenkool <segher@kernel.crashing.org>

Thanks for doing this work David!


> +	/* First look for RedBoot table or partitions on the command
> +	 * line, these take precedence over device tree information */

Any specific reason you chose this order?  Just curious...

> +		.data		= (void *)"jedec_probe",

Hrm, this cast is only getting rid of the const-ness of the
string literal -- maybe .data should be declared const, or
does the majority of users want it writable?


Segher

^ permalink raw reply

* Re: [PATCH 10/10] bootwrapper: Add fsl_get_immr() and 8xx/pq2 clock functions.
From: Scott Wood @ 2007-09-07 14:26 UTC (permalink / raw)
  To: galak, linuxppc-dev
In-Reply-To: <20070907005357.GI26079@localhost.localdomain>

On Fri, Sep 07, 2007 at 10:53:57AM +1000, David Gibson wrote:
> Uh... doesn't this need to go in the series *before* the patch that
> uses fsl_get_immr() for the pq2 code..?

Oops, yes.

-Scott

^ permalink raw reply

* Re: Document and implement an improved flash device binding for powerpc (v5)
From: Josh Boyer @ 2007-09-07 14:28 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, Paul Mackerras, David Gibson
In-Reply-To: <2fcd14e175d5a215cd8d602ac74fce21@kernel.crashing.org>

On Fri, 7 Sep 2007 16:25:10 +0200
Segher Boessenkool <segher@kernel.crashing.org> wrote:

> > This patch replaces the binding for flash chips in
> > booting-without-of.txt with an clarified and improved version.  It
> > also makes drivers/mtd/maps/physmap_of.c recognize this new binding.
> > Finally it revises the Ebony device tree source to use the new binding
> > as an example.
> >
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> 
> Acked-by: Segher Boessenkool <segher@kernel.crashing.org>
> 
> Thanks for doing this work David!

Indeed.  This looks good to me as well.  Once it gets in a tree
somewhere I'll get Walnut switched over.

josh

^ permalink raw reply

* Re: [PATCH 1/5] Add Freescale DMA and DMA channel to Documentation/powerpc/booting-without-of.txt file.
From: Segher Boessenkool @ 2007-09-07 14:43 UTC (permalink / raw)
  To: Zhang Wei; +Cc: linuxppc-dev, paulus
In-Reply-To: <1189162437484-git-send-email-wei.zhang@freescale.com>

> +   l) Freescale DMA

> +    - compatible : Should be "fsl,dma".

Please choose some more specific name.  "fsl,mpc8540-dma" would
be a reasonable choice perhaps.

> +    - reg : Offset and length of DMA general status register.
> +    - ranges : Should be defined as specified in 1) to describe the
> +               DMA controller channels.
> +
> +  Example:
> +	dma@21000 {
> +		reg = <21300 4>;

Those don't agree.  It's probably best to describe the whole
DMA controller register block in this node.  Why do you need
subnodes for the channels at all?


Segher

^ permalink raw reply

* futex priority based wakeup
From: Benedict, Michael @ 2007-09-07 15:02 UTC (permalink / raw)
  To: linuxppc-embedded

I recently upgraded to 2.6.22 to get the priority based futex wakeup
behavior.  However, when I run a simple program (see below), based on
either a pthread_mutex_t or a sem_t, it seems that threads are woken up
in FIFO order.  I am using glibc 2.3.6 with NPTL and TLS, based off
crossdev-0.43.  Could someone help me get priority-based wakeup or point
me to a better place to get this question answered?
	Thank you,
		Michael

Code:

pthread_mutex_t mymutex =3D PTHREAD_MUTEX_INITIALIZER;

void *important(void *ign)
{
        sleep(1);
        printf("important waiting for mutex\n");
        if(pthread_mutex_lock(&mymutex)) {
                perror("sem_wait");
                exit(1);
        } else {
                printf("important got mutex!\n");
                pthread_mutex_unlock(&mymutex);
        }

        return NULL;
}


void *unimportant(void *ign)
{
        printf("unimportant waiting for mutex\n");
        if(pthread_mutex_lock(&mymutex)) {
                perror("sem_wait");
                exit(1);
        } else {
                printf("unimportant got mutex!\n");
                pthread_mutex_unlock(&mymutex);
        }

        return NULL;
}

int main()
{
        struct sched_param p;
        pthread_attr_t attr;
        pthread_t i, u;

        pthread_mutex_lock(&mymutex);

        p.__sched_priority =3D sched_get_priority_min(SCHED_FIFO);
        if(-1 =3D=3D p.__sched_priority) {
                perror("sched_get_priority_min");
                return 1;
        }
        pthread_attr_init(&attr);
        pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
        pthread_attr_setschedparam(&attr, &p);
        pthread_create(&u, &attr, unimportant, NULL);

        p.__sched_priority =3D sched_get_priority_max(SCHED_FIFO);
        pthread_attr_setschedparam(&attr, &p);
        pthread_create(&i, &attr, important, NULL);

        sleep(5);
        printf("main unlocking mutex\n");
        pthread_mutex_unlock(&mymutex);

        pthread_join(u, NULL);
        pthread_join(i, NULL);

        return 0;
}

Which produces:
unimportant waiting for mutex
important waiting for mutex
main unlocking mutex
unimportant got mutex!
important got mutex!

^ permalink raw reply

* Re: Flash paritioning and JFFS2
From: Mirek23 @ 2007-09-07 15:23 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <1187885337.5160.55.camel@louie>


Hi Michael,

>The partition information probably should go in a file that you create
>for your board located at "drivers/mtd/maps/<your_file>.c"

        Thank you very much for your answer. I went through the links you
suggested.
I got a main concept how to setup the kernel to deal with Flash and JFFS2
but I do not know in which file 
should be hardcoded the partition table and what should be its name. I have
the Flash memory which is CFI 
compliant (Intel NOR Flash TE28F640 J3C120) so I presume that for it is a
default driver?
Do I have to create a specific file for it in drivers/mtd/maps/ ?

Best Regards 

Mirek

-- 
View this message in context: http://www.nabble.com/Flash-paritioning-and-JFFS2-tf4317566.html#a12557406
Sent from the linuxppc-embedded mailing list archive at Nabble.com.

^ permalink raw reply

* Re: [PATCH 1/5] Add Freescale DMA and DMA channel to Documentation/powerpc/booting-without-of.txt file.
From: Scott Wood @ 2007-09-07 15:31 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, paulus
In-Reply-To: <3b29878a7d3d1b14f84b5d3b182cdb98@kernel.crashing.org>

On Fri, Sep 07, 2007 at 04:43:35PM +0200, Segher Boessenkool wrote:
> Those don't agree.  It's probably best to describe the whole
> DMA controller register block in this node.  Why do you need
> subnodes for the channels at all?

The channels have separate registers and sometimes separate interrupts --
it's simpler to bind to a channel at a time than to parse a list of reg
blocks and interrupts.  It's also more flexible in case a new chip comes
out with more/fewer channels, or if certain channels are not general
purpose.

-Scott

^ permalink raw reply

* Re: Flash paritioning and JFFS2
From: Michael Brian Willis @ 2007-09-07 15:55 UTC (permalink / raw)
  To: Mirek23; +Cc: linuxppc-embedded
In-Reply-To: <12557406.post@talk.nabble.com>

On Fri, 2007-09-07 at 08:23 -0700, Mirek23 wrote:
>  I have the Flash memory which is CFI 
> compliant (Intel NOR Flash TE28F640 J3C120) so I presume that for it is a
> default driver?
If the flash is CFI compliant, then a default driver will probably
work. 

When the kernel boots up are you able to see a message saying that it
found your flash? You might have to play around with the kernel
configuration to get it to properly recognize your flash. 


> Do I have to create a specific file for it in drivers/mtd/maps/ ?
Yes, at least this is the way I did it. For example, I used
drivers/mtd/maps/tqm85xx.c as a starting point for my board specific
file. (I am using the DENX kernel). 


Regards, 

Michael Willis
Applied Research Labs - University of Texas

^ permalink raw reply

* Re: [PATCH 5/5] Add DMA engine driver for Freescale MPC85xx processors.
From: Randy Dunlap @ 2007-09-07 15:58 UTC (permalink / raw)
  To: Zhang Wei; +Cc: shannon.nelson, linux-kernel, linuxppc-dev, paulus
In-Reply-To: <11891624582950-git-send-email-wei.zhang@freescale.com>

On Fri,  7 Sep 2007 18:54:18 +0800 Zhang Wei wrote:

> Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
> Signed-off-by: Ebony Zhu <ebony.zhu@freescale.com>
> ---
>  drivers/dma/Kconfig  |    8 +
>  drivers/dma/Makefile |    1 +
>  drivers/dma/fsldma.c |  995 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/dma/fsldma.h |  188 ++++++++++
>  4 files changed, 1192 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/dma/fsldma.c
>  create mode 100644 drivers/dma/fsldma.h
> 
> --- /dev/null
> +++ b/drivers/dma/fsldma.c
> @@ -0,0 +1,995 @@

Thanks for using kernel-doc notation.  However, ...

> +/**
> + * fsl_dma_alloc_descriptor - Allocate descriptor from channel's DMA pool.

Function parameters need to be listed & described here.
See Documentation/kernel-doc-nano-HOWTO.txt or other source files
for examples.

(Applies to all documented function interfaces here.)

> + *
> + * Return - The descriptor allocated. NULL for failed.
> + */
> +static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
> +					struct fsl_dma_chan *fsl_chan,
> +					gfp_t flags)
> +{
...
> +}

> +/**
> + * fsl_chan_xfer_ld_queue -- Transfer the link descriptors in channel
> + *                           ld_queue.

The function's "short description" (unfortunately) must be on only one
line.  E.g.:

 * fsl_chan_xfer_ld_queue - Transfer link descriptors in channel ld_queue.

> + */
> +static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan)
> +{
...
> +}

> diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
> new file mode 100644
> index 0000000..05be9ed
> --- /dev/null
> +++ b/drivers/dma/fsldma.h
> @@ -0,0 +1,188 @@
> +struct fsl_dma_chan_regs {
> +	__mix32	mr;		/* 0x00 - Mode Register */
> +	__mix32	sr;		/* 0x04 - Status Register */
> +	__mix64	cdar;		/* 0x08 - Cureent descriptor address register */

                                          Current

> +	__mix64	sar;		/* 0x10 - Source Address Register */
> +	__mix64	dar;		/* 0x18 - Destination Address Register */
> +	__mix32	bcr;		/* 0x20 - Byte Count Register */
> +	__mix64	ndar;		/* 0x24 - Next Descriptor Address Register */
> +};

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

^ permalink raw reply

* RE: [PATCH 5/5] Add DMA engine driver for Freescale MPC85xx processors.
From: Nelson, Shannon @ 2007-09-07 16:00 UTC (permalink / raw)
  To: Zhang Wei, paulus; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <11891624582950-git-send-email-wei.zhang@freescale.com>

>From: Zhang Wei [mailto:wei.zhang@freescale.com]=20
>Sent: Friday, September 07, 2007 3:54 AM
>To: paulus@samba.org; Nelson, Shannon
>Cc: linux-kernel@vger.kernel.org; linuxppc-dev@ozlabs.org;=20
>galak@kernel.crashing.org; Zhang Wei; Ebony Zhu
>Subject: [PATCH 5/5] Add DMA engine driver for Freescale=20
>MPC85xx processors.
>
>The driver implements DMA engine API for Freescale MPC85xx DMA
>controller, which could be used for MEM<-->MEM, IO_ADDR<-->MEM
>and IO_ADDR<-->IO_ADDR data transfer.
>The driver supports the Basic mode of Freescale MPC85xx DMA controller.
>The MPC85xx processors supported include MPC8540/60, MPC8555, MPC8548,
>MPC8641 and so on.
>The support for MPC83xx(MPC8349, MPC8360) is experimental.
>
>Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
>Signed-off-by: Ebony Zhu <ebony.zhu@freescale.com>
>---
> drivers/dma/Kconfig  |    8 +
> drivers/dma/Makefile |    1 +
> drivers/dma/fsldma.c |  995=20
>++++++++++++++++++++++++++++++++++++++++++++++++++
> drivers/dma/fsldma.h |  188 ++++++++++
> 4 files changed, 1192 insertions(+), 0 deletions(-)
> create mode 100644 drivers/dma/fsldma.c
> create mode 100644 drivers/dma/fsldma.h
>
>diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
>index 8f670da..a99e925 100644
>--- a/drivers/dma/Kconfig
>+++ b/drivers/dma/Kconfig
>@@ -40,4 +40,12 @@ config INTEL_IOP_ADMA
>         ---help---
>           Enable support for the Intel(R) IOP Series RAID engines.
>=20
>+config FSL_DMA
>+	bool "Freescale MPC85xx/MPC83xx DMA support"
>+	depends on DMA_ENGINE && PPC
>+	---help---
>+	  Enable support for the Freescale DMA engine. Now, it support
>+	  MPC8560/40, MPC8555, MPC8548 and MPC8641 processors.
>+	  The MPC8349, MPC8360 support is experimental.
>+
> endmenu

If this is experimental, perhaps you should mark the depends line as
such
	depends on on DMA_ENGINE && PPC && EXPERIMENTAL

[...]

>+static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
>+{
>+	struct dma_chan *chan;
>+	int err =3D 0;
>+	dma_addr_t addr;
>+	dma_cookie_t cookie;
>+	u8 *src, *dest;
>+	int i;
>+	size_t test_size;
>+	struct dma_async_tx_descriptor *tx1, *tx2, *tx3;
>+	struct fsl_dma_device *fdev;
>+
>+	BUG_ON(!fsl_chan);
>+
>+	fdev =3D fsl_chan->device;
>+	test_size =3D 4096;
>+
>+	src =3D kmalloc(test_size * 2, GFP_KERNEL);
>+	if (!src) {
>+		dev_err(fdev->dev,
>+				"selftest: Can not alloc memory=20
>for test!\n");
>+		err =3D -ENOMEM;
>+		goto out;
>+	}
>+
>+	dest =3D src + test_size;
>+
>+	for (i =3D 0; i < test_size; i++)
>+		src[i] =3D (u8) i;
>+
>+	chan =3D &fsl_chan->common;
>+
>+	if (fsl_dma_alloc_chan_resources(chan) < 1) {
>+		dev_err(fdev->dev,
>+				"selftest: Can not alloc=20
>resources for DMA\n");
>+		err =3D -ENODEV;
>+		goto out;
>+	}
>+
>+	/* TX 1 */
>+	tx1 =3D fsl_dma_prep_memcpy(chan, test_size / 2, 0);
>+	async_tx_ack(tx1);
>+	addr =3D dma_map_single(chan->device->dev, src, test_size / 2,
>+							DMA_TO_DEVICE);
>+	fsl_dma_set_src(addr, tx1, 0);
>+	addr =3D dma_map_single(chan->device->dev, dest, test_size / 2,
>+						=09
>DMA_FROM_DEVICE);
>+	fsl_dma_set_dest(addr, tx1, 0);
>+
>+	cookie =3D fsl_dma_tx_submit(tx1);
>+	fsl_dma_memcpy_issue_pending(chan);
>+
>+	while (fsl_dma_is_complete(chan, cookie, NULL, NULL)
>+			!=3D DMA_SUCCESS);

Is this guaranteed to finish?  If there's something wrong and the DMA
never completes, you've now hung this thread.  This is why the ioat_dma
engine does an msleep() and then checks once for completion.  You might
think about this...

>+
>+	/* Test free and re-alloc channel resources */
>+	fsl_dma_free_chan_resources(chan);
>+
>+	if (fsl_dma_alloc_chan_resources(chan) < 1) {
>+		dev_err(fdev->dev,
>+				"selftest: Can not alloc=20
>resources for DMA\n");
>+		err =3D -ENODEV;
>+		goto out;
>+	}
>+
>+	/* Continue to test
>+	 * TX 2
>+	 */
>+	tx2 =3D fsl_dma_prep_memcpy(chan, test_size / 4, 0);
>+	async_tx_ack(tx2);
>+	addr =3D dma_map_single(chan->device->dev, src + test_size / 2,
>+					test_size / 4, DMA_TO_DEVICE);
>+	fsl_dma_set_src(addr, tx2, 0);
>+	addr =3D dma_map_single(chan->device->dev, dest + test_size / 2,
>+					test_size / 4, DMA_FROM_DEVICE);
>+	fsl_dma_set_dest(addr, tx2, 0);
>+
>+	/* TX 3 */
>+	tx3 =3D fsl_dma_prep_memcpy(chan, test_size / 4, 0);
>+	async_tx_ack(tx3);
>+	addr =3D dma_map_single(chan->device->dev, src +=20
>test_size * 3 / 4,
>+					test_size / 4, DMA_TO_DEVICE);
>+	fsl_dma_set_src(addr, tx3, 0);
>+	addr =3D dma_map_single(chan->device->dev, dest +=20
>test_size * 3 / 4,
>+					test_size / 4, DMA_FROM_DEVICE);
>+	fsl_dma_set_dest(addr, tx3, 0);
>+
>+	/* Test exchanging the prepared tx sort */
>+	cookie =3D fsl_dma_tx_submit(tx3);
>+	cookie =3D fsl_dma_tx_submit(tx2);
>+
>+	fsl_dma_memcpy_issue_pending(chan);
>+	while (fsl_dma_is_complete(chan, cookie, NULL, NULL)
>+			!=3D DMA_SUCCESS);

Again, is it possible to hang your thread here?

[...]

sln
--
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Mr. Shannon Nelson                 LAN Access Division, Intel Corp.
Shannon.Nelson@intel.com                I don't speak for Intel
(503) 712-7659                    Parents can't afford to be squeamish.

^ permalink raw reply

* Re: [PATCH 1/5] Add Freescale DMA and DMA channel to Documentation/powerpc/booting-without-of.txt file.
From: Segher Boessenkool @ 2007-09-07 16:30 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, paulus
In-Reply-To: <20070907153116.GA15770@ld0162-tx32.am.freescale.net>

>> Those don't agree.  It's probably best to describe the whole
>> DMA controller register block in this node.  Why do you need
>> subnodes for the channels at all?
>
> The channels have separate registers and sometimes separate interrupts 
> --
> it's simpler to bind to a channel at a time than to parse a list of reg
> blocks and interrupts.  It's also more flexible in case a new chip 
> comes
> out with more/fewer channels, or if certain channels are not general
> purpose.

I don't see this as more flexible, but no problem, it will work
for sure.

The "reg" vs. textual unit address issue needs to be solved though.


Segher

^ permalink raw reply

* RE: futex priority based wakeup
From: Ilya Lipovsky @ 2007-09-07 16:41 UTC (permalink / raw)
  To: 'Benedict, Michael', linuxppc-embedded
In-Reply-To: <BAF8B1E0BB28024A90895E746A3B610D1C2BCD@twx-exch01.twacs.local>

Looks like it is a libc issue. Apparently, GNU libc supports priority
futexes only in version 2.5 and higher.

-----Original Message-----
From: linuxppc-embedded-bounces+lipovsky=cs.bu.edu@ozlabs.org
[mailto:linuxppc-embedded-bounces+lipovsky=cs.bu.edu@ozlabs.org] On Behalf
Of Benedict, Michael
Sent: Friday, September 07, 2007 11:02 AM
To: linuxppc-embedded@ozlabs.org
Subject: futex priority based wakeup

I recently upgraded to 2.6.22 to get the priority based futex wakeup
behavior.  However, when I run a simple program (see below), based on
either a pthread_mutex_t or a sem_t, it seems that threads are woken up
in FIFO order.  I am using glibc 2.3.6 with NPTL and TLS, based off
crossdev-0.43.  Could someone help me get priority-based wakeup or point
me to a better place to get this question answered?
	Thank you,
		Michael

Code:

pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;

void *important(void *ign)
{
        sleep(1);
        printf("important waiting for mutex\n");
        if(pthread_mutex_lock(&mymutex)) {
                perror("sem_wait");
                exit(1);
        } else {
                printf("important got mutex!\n");
                pthread_mutex_unlock(&mymutex);
        }

        return NULL;
}


void *unimportant(void *ign)
{
        printf("unimportant waiting for mutex\n");
        if(pthread_mutex_lock(&mymutex)) {
                perror("sem_wait");
                exit(1);
        } else {
                printf("unimportant got mutex!\n");
                pthread_mutex_unlock(&mymutex);
        }

        return NULL;
}

int main()
{
        struct sched_param p;
        pthread_attr_t attr;
        pthread_t i, u;

        pthread_mutex_lock(&mymutex);

        p.__sched_priority = sched_get_priority_min(SCHED_FIFO);
        if(-1 == p.__sched_priority) {
                perror("sched_get_priority_min");
                return 1;
        }
        pthread_attr_init(&attr);
        pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
        pthread_attr_setschedparam(&attr, &p);
        pthread_create(&u, &attr, unimportant, NULL);

        p.__sched_priority = sched_get_priority_max(SCHED_FIFO);
        pthread_attr_setschedparam(&attr, &p);
        pthread_create(&i, &attr, important, NULL);

        sleep(5);
        printf("main unlocking mutex\n");
        pthread_mutex_unlock(&mymutex);

        pthread_join(u, NULL);
        pthread_join(i, NULL);

        return 0;
}

Which produces:
unimportant waiting for mutex
important waiting for mutex
main unlocking mutex
unimportant got mutex!
important got mutex!

_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply

* [GIT PULL] FireWire fix
From: Stefan Richter @ 2007-09-07 17:04 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Kristian Høgsberg, linuxppc-dev, Andrew Morton,
	linux1394-devel, linux-kernel

Linus, please pull from the for-linus branch at

    git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git for-linus

to receive a fix of the laptop-refuses-to-suspend kind. Or simply apply
the patch from this mail.


There is still an old underlying oddness though which I ask the PPC
folks to investigate and possibly fix post 2.6.23:  On iBook G3 and
older PowerBooks, the onboard FireWire controller's pci_dev
current_state remains PCI_UNKNOWN long after initialization. Sounds like
a bug in platform code to me.


Stat, log, diff:

 drivers/firewire/fw-ohci.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

commit 5511142870046a7bed947d51ec9b320856ee120a
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Thu Sep 6 09:50:30 2007 +0200

    firewire: fw-ohci: ignore failure of pci_set_power_state (fix suspend regression)
    
    Fixes (papers over) "Sleep problems with kernels >= 2.6.21 on powerpc",
    http://lkml.org/lkml/2007/8/25/155.  The issue is that the FireWire
    controller's pci_dev.current_state of iBook G3 and presumably older
    PowerBooks is still in PCI_UNKNOWN instead of PCI_D0 when the firewire
    driver's .suspend method is called.
    
    Like it was suggested earlier in http://lkml.org/lkml/2006/10/24/13, we
    do not fail .suspend anymore if pci_set_power_state failed.
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 7e427b4..e14c1ca 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -1945,10 +1945,8 @@ static int pci_suspend(struct pci_dev *pdev, pm_message_t state)
 		return err;
 	}
 	err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
-	if (err) {
-		fw_error("pci_set_power_state failed\n");
-		return err;
-	}
+	if (err)
+		fw_error("pci_set_power_state failed with %d\n", err);
 
 	return 0;
 }

-- 
Stefan Richter
-=====-=-=== =--= --===
http://arcgraph.de/sr/

^ permalink raw reply related


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